[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-3.0.4-testing] [XEN] Snapshot guest entries when shadowing PAE tables.



# HG changeset patch
# User Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
# Date 1170083098 0
# Node ID d401cb96d8a0da5febe737b86f453a88f1f45bb7
# Parent  8a4c107eae1e306674e4523bbbcca4b50773a186
[XEN] Snapshot guest entries when shadowing PAE tables.
This fixes a crash when migrating Solaris guests.
Also delete some old and unused linear pagetable definitions.

Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
---
 xen/arch/x86/hvm/svm/svm.c            |    2 
 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 
 6 files changed, 63 insertions(+), 72 deletions(-)

diff -r 8a4c107eae1e -r d401cb96d8a0 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Mon Jan 29 14:28:40 2007 +0000
+++ b/xen/arch/x86/hvm/svm/svm.c        Mon Jan 29 15:04:58 2007 +0000
@@ -2567,7 +2567,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 8a4c107eae1e -r d401cb96d8a0 xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c    Mon Jan 29 14:28:40 2007 +0000
+++ b/xen/arch/x86/mm/shadow/multi.c    Mon Jan 29 15:04:58 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.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.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.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=%" SH_PRI_mfn "\n", mfn_x(gw->l3mfn));
 #endif /* PAE or 64... */
-    SHADOW_PRINTK("   l3mfn=%" SH_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);
@@ -3127,8 +3128,7 @@ sh_update_linear_entries(struct vcpu *v)
 #else /* GUEST_PAGING_LEVELS == 3 */
         
         shadow_l3e = (shadow_l3e_t *)&v->arch.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.shadow.gl3e;
 
 #endif /* GUEST_PAGING_LEVELS */
         
@@ -3226,38 +3226,36 @@ sh_update_linear_entries(struct vcpu *v)
 }
 
 
-/* Removes vcpu->arch.guest_vtable and vcpu->arch.shadow_table[].
+/* Removes vcpu->arch.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.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.shadow.guest_vtable == NULL);
+#else
+    if ( v->arch.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.shadow.guest_vtable);
+        v->arch.shadow.guest_vtable = NULL;
+    }
+#endif
+
 
     ////
     //// vcpu->arch.shadow_table[]
     ////
-
 
 #if GUEST_PAGING_LEVELS == 3
     /* PAE guests have four shadow_table entries */
@@ -3352,7 +3350,9 @@ sh_update_cr3(struct vcpu *v)
     struct domain *d = v->domain;
     mfn_t gmfn;
 #if GUEST_PAGING_LEVELS == 3
+    guest_l3e_t *gl3e;
     u32 guest_idx=0;
+    int i;
 #endif
 
     ASSERT(shadow_locked_by_me(v->domain));
@@ -3407,55 +3407,54 @@ sh_update_cr3(struct vcpu *v)
     }
 
     ////
-    //// vcpu->arch.guest_vtable
+    //// vcpu->arch.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.shadow.guest_vtable )
+            sh_unmap_domain_page_global(v->arch.shadow.guest_vtable);
+        v->arch.shadow.guest_vtable = sh_map_domain_page_global(gmfn);
     }
     else
-        v->arch.guest_vtable = __linear_l4_table;
+        v->arch.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 ( shadow_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.shadow.guest_vtable == NULL);
+
+    if ( shadow_mode_external(d) && shadow_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.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.shadow.guest_vtable )
+            sh_unmap_domain_page_global(v->arch.shadow.guest_vtable);
+        v->arch.shadow.guest_vtable = sh_map_domain_page_global(gmfn);
     }
     else
-        v->arch.guest_vtable = __linear_l2_table;
+        v->arch.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.shadow.guest_vtable);
 #endif
 
     ////
@@ -3473,10 +3472,10 @@ sh_update_cr3(struct vcpu *v)
     /* 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.shadow.gl3e;
         /* First, make all four entries read-only. */
         for ( i = 0; i < 4; i++ )
         {
diff -r 8a4c107eae1e -r d401cb96d8a0 xen/arch/x86/mm/shadow/page-guest32.h
--- a/xen/arch/x86/mm/shadow/page-guest32.h     Mon Jan 29 14:28:40 2007 +0000
+++ b/xen/arch/x86/mm/shadow/page-guest32.h     Mon Jan 29 15:04:58 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 8a4c107eae1e -r d401cb96d8a0 xen/arch/x86/mm/shadow/types.h
--- a/xen/arch/x86/mm/shadow/types.h    Mon Jan 29 14:28:40 2007 +0000
+++ b/xen/arch/x86/mm/shadow/types.h    Mon Jan 29 15:04:58 2007 +0000
@@ -453,10 +453,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 8a4c107eae1e -r d401cb96d8a0 xen/include/asm-x86/domain.h
--- a/xen/include/asm-x86/domain.h      Mon Jan 29 14:28:40 2007 +0000
+++ b/xen/include/asm-x86/domain.h      Mon Jan 29 15:04:58 2007 +0000
@@ -138,7 +138,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 guets top-level pagetable */
+    void *guest_vtable;
     /* Pointers to mode-specific entry points. */
     struct shadow_paging_mode *mode;
     /* Last MFN that we emulated a write to. */
@@ -194,8 +198,6 @@ struct arch_vcpu
     pagetable_t shadow_table[4];        /* (MFN) shadow(s) of guest */
     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 8a4c107eae1e -r d401cb96d8a0 xen/include/asm-x86/page.h
--- a/xen/include/asm-x86/page.h        Mon Jan 29 14:28:40 2007 +0000
+++ b/xen/include/asm-x86/page.h        Mon Jan 29 15:04:58 2007 +0000
@@ -275,9 +275,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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.