[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [XEN] Snapshot PAE l3es when they are shadowed.
# HG changeset patch # User Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx> # Date 1171464378 0 # Node ID a00b8d3800a82a993344c9546ddc1f00a9c514be # Parent cbbd748c4b58f66367b750a2fbba4da5b71fd94c [XEN] Snapshot PAE l3es when they are shadowed. We don't update the shadows so we mustn't look at the guest l3es or we'll be confused by them if they change. Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx> --- xen/arch/x86/hvm/svm/svm.c | 2 xen/arch/x86/mm.c | 3 xen/arch/x86/mm/shadow/multi.c | 115 ++++++++++++++++------------------ xen/arch/x86/mm/shadow/page-guest32.h | 5 - xen/arch/x86/mm/shadow/types.h | 2 xen/include/asm-x86/domain.h | 8 +- xen/include/asm-x86/page.h | 3 7 files changed, 63 insertions(+), 75 deletions(-) diff -r cbbd748c4b58 -r a00b8d3800a8 xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Wed Feb 14 14:44:07 2007 +0000 +++ b/xen/arch/x86/hvm/svm/svm.c Wed Feb 14 14:46:18 2007 +0000 @@ -2679,7 +2679,7 @@ void walk_shadow_and_guest_pt(unsigned l shadow_sync_va(v, gva); gpte.l1 = 0; - __copy_from_user(&gpte, &linear_pg_table[ l1_linear_offset(gva) ], + __copy_from_user(&gpte, &__linear_l1_table[ l1_linear_offset(gva) ], sizeof(gpte) ); printk( "G-PTE = %x, flags=%x\n", gpte.l1, l1e_get_flags(gpte) ); diff -r cbbd748c4b58 -r a00b8d3800a8 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Wed Feb 14 14:44:07 2007 +0000 +++ b/xen/arch/x86/mm.c Wed Feb 14 14:46:18 2007 +0000 @@ -374,9 +374,6 @@ void write_ptbase(struct vcpu *v) /* Should be called after CR3 is updated. * Updates vcpu->arch.cr3 and, for HVM guests, vcpu->arch.hvm_vcpu.cpu_cr3. * - * Also updates other state derived from CR3 (vcpu->arch.guest_vtable, - * shadow_vtable, etc). - * * Uses values found in vcpu->arch.(guest_table and guest_table_user), and * for HVM guests, arch.monitor_table and hvm's guest CR3. * diff -r cbbd748c4b58 -r a00b8d3800a8 xen/arch/x86/mm/shadow/multi.c --- a/xen/arch/x86/mm/shadow/multi.c Wed Feb 14 14:44:07 2007 +0000 +++ b/xen/arch/x86/mm/shadow/multi.c Wed Feb 14 14:46:18 2007 +0000 @@ -237,7 +237,8 @@ guest_walk_tables(struct vcpu *v, unsign #if GUEST_PAGING_LEVELS >= 4 /* 64-bit only... */ /* Get l4e from the top level table */ gw->l4mfn = pagetable_get_mfn(v->arch.guest_table); - gw->l4e = (guest_l4e_t *)v->arch.guest_vtable + guest_l4_table_offset(va); + gw->l4e = (guest_l4e_t *)v->arch.paging.shadow.guest_vtable + + guest_l4_table_offset(va); /* Walk down to the l3e */ if ( !(guest_l4e_get_flags(*gw->l4e) & _PAGE_PRESENT) ) return 0; gw->l3mfn = vcpu_gfn_to_mfn(v, guest_l4e_get_gfn(*gw->l4e)); @@ -248,9 +249,8 @@ guest_walk_tables(struct vcpu *v, unsign gw->l3e = ((guest_l3e_t *)sh_map_domain_page(gw->l3mfn)) + guest_l3_table_offset(va); #else /* PAE only... */ - /* Get l3e from the top level table */ - gw->l3mfn = pagetable_get_mfn(v->arch.guest_table); - gw->l3e = (guest_l3e_t *)v->arch.guest_vtable + guest_l3_table_offset(va); + /* Get l3e from the cache of the guest's top level table */ + gw->l3e = (guest_l3e_t *)&v->arch.paging.shadow.gl3e[guest_l3_table_offset(va)]; #endif /* PAE or 64... */ /* Walk down to the l2e */ if ( !(guest_l3e_get_flags(*gw->l3e) & _PAGE_PRESENT) ) return 0; @@ -264,7 +264,8 @@ guest_walk_tables(struct vcpu *v, unsign #else /* 32-bit only... */ /* Get l2e from the top level table */ gw->l2mfn = pagetable_get_mfn(v->arch.guest_table); - gw->l2e = (guest_l2e_t *)v->arch.guest_vtable + guest_l2_table_offset(va); + gw->l2e = (guest_l2e_t *)v->arch.paging.shadow.guest_vtable + + guest_l2_table_offset(va); #endif /* All levels... */ if ( !(guest_l2e_get_flags(*gw->l2e) & _PAGE_PRESENT) ) return 0; @@ -357,8 +358,8 @@ static inline void print_gw(walk_t *gw) SHADOW_PRINTK(" l4e=%p\n", gw->l4e); if ( gw->l4e ) SHADOW_PRINTK(" *l4e=%" SH_PRI_gpte "\n", gw->l4e->l4); + SHADOW_PRINTK(" l3mfn=%" PRI_mfn "\n", mfn_x(gw->l3mfn)); #endif /* PAE or 64... */ - SHADOW_PRINTK(" l3mfn=%" PRI_mfn "\n", mfn_x(gw->l3mfn)); SHADOW_PRINTK(" l3e=%p\n", gw->l3e); if ( gw->l3e ) SHADOW_PRINTK(" *l3e=%" SH_PRI_gpte "\n", gw->l3e->l3); @@ -3169,8 +3170,7 @@ sh_update_linear_entries(struct vcpu *v) #else /* GUEST_PAGING_LEVELS == 3 */ shadow_l3e = (shadow_l3e_t *)&v->arch.paging.shadow.l3table; - /* Always safe to use guest_vtable, because it's globally mapped */ - guest_l3e = v->arch.guest_vtable; + guest_l3e = (guest_l3e_t *)&v->arch.paging.shadow.gl3e; #endif /* GUEST_PAGING_LEVELS */ @@ -3268,38 +3268,36 @@ sh_update_linear_entries(struct vcpu *v) } -/* Removes vcpu->arch.guest_vtable and vcpu->arch.shadow_table[]. +/* Removes vcpu->arch.paging.shadow.guest_vtable and vcpu->arch.shadow_table[]. * Does all appropriate management/bookkeeping/refcounting/etc... */ static void sh_detach_old_tables(struct vcpu *v) { - struct domain *d = v->domain; mfn_t smfn; int i = 0; //// - //// vcpu->arch.guest_vtable + //// vcpu->arch.paging.shadow.guest_vtable //// - if ( v->arch.guest_vtable ) - { -#if GUEST_PAGING_LEVELS == 4 + +#if GUEST_PAGING_LEVELS == 3 + /* PAE guests don't have a mapping of the guest top-level table */ + ASSERT(v->arch.paging.shadow.guest_vtable == NULL); +#else + if ( v->arch.paging.shadow.guest_vtable ) + { + struct domain *d = v->domain; if ( shadow_mode_external(d) || shadow_mode_translate(d) ) - sh_unmap_domain_page_global(v->arch.guest_vtable); -#elif GUEST_PAGING_LEVELS == 3 - if ( 1 || shadow_mode_external(d) || shadow_mode_translate(d) ) - sh_unmap_domain_page_global(v->arch.guest_vtable); -#elif GUEST_PAGING_LEVELS == 2 - if ( shadow_mode_external(d) || shadow_mode_translate(d) ) - sh_unmap_domain_page_global(v->arch.guest_vtable); -#endif - v->arch.guest_vtable = NULL; - } + sh_unmap_domain_page_global(v->arch.paging.shadow.guest_vtable); + v->arch.paging.shadow.guest_vtable = NULL; + } +#endif + //// //// vcpu->arch.shadow_table[] //// - #if GUEST_PAGING_LEVELS == 3 /* PAE guests have four shadow_table entries */ @@ -3398,7 +3396,9 @@ sh_update_cr3(struct vcpu *v, int do_loc struct domain *d = v->domain; mfn_t gmfn; #if GUEST_PAGING_LEVELS == 3 + guest_l3e_t *gl3e; u32 guest_idx=0; + int i; #endif /* Don't do anything on an uninitialised vcpu */ @@ -3457,55 +3457,54 @@ sh_update_cr3(struct vcpu *v, int do_loc //// - //// vcpu->arch.guest_vtable + //// vcpu->arch.paging.shadow.guest_vtable //// #if GUEST_PAGING_LEVELS == 4 if ( shadow_mode_external(d) || shadow_mode_translate(d) ) { - if ( v->arch.guest_vtable ) - sh_unmap_domain_page_global(v->arch.guest_vtable); - v->arch.guest_vtable = sh_map_domain_page_global(gmfn); + if ( v->arch.paging.shadow.guest_vtable ) + sh_unmap_domain_page_global(v->arch.paging.shadow.guest_vtable); + v->arch.paging.shadow.guest_vtable = sh_map_domain_page_global(gmfn); } else - v->arch.guest_vtable = __linear_l4_table; + v->arch.paging.shadow.guest_vtable = __linear_l4_table; #elif GUEST_PAGING_LEVELS == 3 - if ( v->arch.guest_vtable ) - sh_unmap_domain_page_global(v->arch.guest_vtable); - if ( shadow_mode_external(d) ) - { - if ( paging_vcpu_mode_translate(v) ) - /* Paging enabled: find where in the page the l3 table is */ - guest_idx = guest_index((void *)hvm_get_guest_ctrl_reg(v, 3)); - else - /* Paging disabled: l3 is at the start of a page (in the p2m) */ - guest_idx = 0; - - // Ignore the low 2 bits of guest_idx -- they are really just - // cache control. - guest_idx &= ~3; - - // XXX - why does this need a global map? - v->arch.guest_vtable = - (guest_l3e_t *)sh_map_domain_page_global(gmfn) + guest_idx; - } + /* On PAE guests we don't use a mapping of the guest's own top-level + * table. We cache the current state of that table and shadow that, + * until the next CR3 write makes us refresh our cache. */ + ASSERT(v->arch.paging.shadow.guest_vtable == NULL); + + if ( shadow_mode_external(d) && paging_vcpu_mode_translate(v) ) + /* Paging enabled: find where in the page the l3 table is */ + guest_idx = guest_index((void *)hvm_get_guest_ctrl_reg(v, 3)); else - v->arch.guest_vtable = sh_map_domain_page_global(gmfn); + /* Paging disabled or PV: l3 is at the start of a page */ + guest_idx = 0; + + // Ignore the low 2 bits of guest_idx -- they are really just + // cache control. + guest_idx &= ~3; + + gl3e = ((guest_l3e_t *)sh_map_domain_page(gmfn)) + guest_idx; + for ( i = 0; i < 4 ; i++ ) + v->arch.paging.shadow.gl3e[i] = gl3e[i]; + sh_unmap_domain_page(gl3e); #elif GUEST_PAGING_LEVELS == 2 if ( shadow_mode_external(d) || shadow_mode_translate(d) ) { - if ( v->arch.guest_vtable ) - sh_unmap_domain_page_global(v->arch.guest_vtable); - v->arch.guest_vtable = sh_map_domain_page_global(gmfn); + if ( v->arch.paging.shadow.guest_vtable ) + sh_unmap_domain_page_global(v->arch.paging.shadow.guest_vtable); + v->arch.paging.shadow.guest_vtable = sh_map_domain_page_global(gmfn); } else - v->arch.guest_vtable = __linear_l2_table; + v->arch.paging.shadow.guest_vtable = __linear_l2_table; #else #error this should never happen #endif #if 0 - printk("%s %s %d gmfn=%05lx guest_vtable=%p\n", - __func__, __FILE__, __LINE__, gmfn, v->arch.guest_vtable); + printk("%s %s %d gmfn=%05lx shadow.guest_vtable=%p\n", + __func__, __FILE__, __LINE__, gmfn, v->arch.paging.shadow.guest_vtable); #endif //// @@ -3523,10 +3522,10 @@ sh_update_cr3(struct vcpu *v, int do_loc /* PAE guests have four shadow_table entries, based on the * current values of the guest's four l3es. */ { - int i, flush = 0; + int flush = 0; gfn_t gl2gfn; mfn_t gl2mfn; - guest_l3e_t *gl3e = (guest_l3e_t*)v->arch.guest_vtable; + guest_l3e_t *gl3e = (guest_l3e_t*)&v->arch.paging.shadow.gl3e; /* First, make all four entries read-only. */ for ( i = 0; i < 4; i++ ) { diff -r cbbd748c4b58 -r a00b8d3800a8 xen/arch/x86/mm/shadow/page-guest32.h --- a/xen/arch/x86/mm/shadow/page-guest32.h Wed Feb 14 14:44:07 2007 +0000 +++ b/xen/arch/x86/mm/shadow/page-guest32.h Wed Feb 14 14:46:18 2007 +0000 @@ -87,11 +87,6 @@ static inline l2_pgentry_32_t l2e_from_p #define l2_table_offset_32(a) \ (((a) >> L2_PAGETABLE_SHIFT_32) & (L2_PAGETABLE_ENTRIES_32 - 1)) -#define linear_l1_table_32 \ - ((l1_pgentry_32_t *)(LINEAR_PT_VIRT_START)) - -#define linear_pg_table_32 linear_l1_table_32 - #endif /* __X86_PAGE_GUEST_H__ */ /* diff -r cbbd748c4b58 -r a00b8d3800a8 xen/arch/x86/mm/shadow/types.h --- a/xen/arch/x86/mm/shadow/types.h Wed Feb 14 14:44:07 2007 +0000 +++ b/xen/arch/x86/mm/shadow/types.h Wed Feb 14 14:46:18 2007 +0000 @@ -447,10 +447,8 @@ struct shadow_walk_t guest_l2e_t *l2e; /* Pointer to guest's level 2 entry */ guest_l1e_t *l1e; /* Pointer to guest's level 1 entry */ guest_l1e_t eff_l1e; /* Effective level 1 entry */ -#if GUEST_PAGING_LEVELS >= 3 #if GUEST_PAGING_LEVELS >= 4 mfn_t l4mfn; /* MFN that the level 4 entry is in */ -#endif mfn_t l3mfn; /* MFN that the level 3 entry is in */ #endif mfn_t l2mfn; /* MFN that the level 2 entry is in */ diff -r cbbd748c4b58 -r a00b8d3800a8 xen/include/asm-x86/domain.h --- a/xen/include/asm-x86/domain.h Wed Feb 14 14:44:07 2007 +0000 +++ b/xen/include/asm-x86/domain.h Wed Feb 14 14:46:18 2007 +0000 @@ -92,7 +92,11 @@ struct shadow_vcpu { #if CONFIG_PAGING_LEVELS >= 3 /* PAE guests: per-vcpu shadow top-level table */ l3_pgentry_t l3table[4] __attribute__((__aligned__(32))); -#endif + /* PAE guests: per-vcpu cache of the top-level *guest* entries */ + l3_pgentry_t gl3e[4] __attribute__((__aligned__(32))); +#endif + /* Non-PAE guests: pointer to guest top-level pagetable */ + void *guest_vtable; /* Last MFN that we emulated a write to. */ unsigned long last_emulated_mfn; /* MFN of the last shadow that we shot a writeable mapping in */ @@ -242,8 +246,6 @@ struct arch_vcpu pagetable_t monitor_table; /* (MFN) hypervisor PT (for HVM) */ unsigned long cr3; /* (MA) value to install in HW CR3 */ - void *guest_vtable; /* virtual addr of pagetable */ - /* Current LDT details. */ unsigned long shadow_ldt_mapcnt; diff -r cbbd748c4b58 -r a00b8d3800a8 xen/include/asm-x86/page.h --- a/xen/include/asm-x86/page.h Wed Feb 14 14:44:07 2007 +0000 +++ b/xen/include/asm-x86/page.h Wed Feb 14 14:46:18 2007 +0000 @@ -278,9 +278,6 @@ typedef struct { u64 pfn; } pagetable_t; #define __linear_l4_table \ ((l4_pgentry_t *)(__linear_l3_table + l3_linear_offset(LINEAR_PT_VIRT_START))) -#define linear_l1_table __linear_l1_table -#define linear_pg_table linear_l1_table -#define linear_l2_table(v) ((l2_pgentry_t *)(v)->arch.guest_vtable) #ifndef __ASSEMBLY__ #if CONFIG_PAGING_LEVELS == 3 _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |