diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index d3f2076cbe..f2b46e8c07 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -295,7 +295,7 @@ void arch_vmx_do_launch(struct exec_domain *ed) reset_stack_and_jump(vmx_asm_do_launch); } -static void alloc_monitor_pagetable(struct exec_domain *ed) +unsigned long alloc_monitor_pagetable(struct exec_domain *ed) { unsigned long mmfn; l2_pgentry_t *mpl2e; @@ -319,12 +319,13 @@ static void alloc_monitor_pagetable(struct exec_domain *ed) mk_l2_pgentry((__pa(d->arch.mm_perdomain_pt) & PAGE_MASK) | __PAGE_HYPERVISOR); - ed->arch.monitor_table = mk_pagetable(mmfn << PAGE_SHIFT); ed->arch.monitor_vtable = mpl2e; // map the phys_to_machine map into the Read-Only MPT space for this domain mpl2e[l2_table_offset(RO_MPT_VIRT_START)] = mk_l2_pgentry(pagetable_val(ed->arch.phys_table) | __PAGE_HYPERVISOR); + + return mmfn; } /* @@ -408,13 +409,7 @@ static int vmx_final_setup_guest(struct exec_domain *ed, shadow_mode_enable(ed->domain, SHM_enable|SHM_translate|SHM_external); } - /* We don't call update_pagetables() as we actively want fields such as - * the linear_pg_table to be inaccessible so that we bail out early of - * shadow_fault() in case the vmx guest tries illegal accesses with - * paging turned off. - */ - //update_pagetables(ed); /* this assigns shadow_pagetable */ - alloc_monitor_pagetable(ed); /* this assigns monitor_pagetable */ + update_pagetables(ed); return 0; diff --git a/xen/include/asm-x86/shadow.h b/xen/include/asm-x86/shadow.h index c02079fa89..670394ce60 100644 --- a/xen/include/asm-x86/shadow.h +++ b/xen/include/asm-x86/shadow.h @@ -781,13 +781,27 @@ static inline void __update_pagetables(struct exec_domain *ed) static inline void update_pagetables(struct exec_domain *ed) { struct domain *d = ed->domain; + int paging_enabled = +#ifdef CONFIG_VMX + !VMX_DOMAIN(ed) || + test_bit(VMX_CPU_STATE_PG_ENABLED, &ed->arch.arch_vmx.cpu_state); +#else + 1; +#endif - if ( unlikely(shadow_mode_enabled(d)) ) + /* + * We don't call __update_pagetables() when vmx guest paging is + * disabled as we want the linear_pg_table to be inaccessible so that + * we bail out early of shadow_fault() if the vmx guest tries illegal + * accesses while it thinks paging is turned off. + */ + if ( unlikely(shadow_mode_enabled(d)) && paging_enabled ) { shadow_lock(d); __update_pagetables(ed); shadow_unlock(d); } + if ( !shadow_mode_external(d) ) { #ifdef __x86_64__ @@ -800,6 +814,15 @@ static inline void update_pagetables(struct exec_domain *ed) else ed->arch.monitor_table = ed->arch.guest_table; } + else + { + // External page tables... + // Allocate a monitor page table if we don't already have one. + // + if ( unlikely(!pagetable_val(ed->arch.monitor_table)) ) + ed->arch.monitor_table = + mk_pagetable(alloc_monitor_pagetable(ed) << PAGE_SHIFT); + } } #if SHADOW_DEBUG diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h index 15db59d73d..8db16e2512 100644 --- a/xen/include/xen/domain.h +++ b/xen/include/xen/domain.h @@ -27,4 +27,6 @@ extern void domain_relinquish_memory(struct domain *d); extern void dump_pageframe_info(struct domain *d); +extern unsigned long alloc_monitor_pagetable(struct exec_domain *ed); + #endif /* __XEN_DOMAIN_H__ */