WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] [HVM] Shadow: don't shadow the p2m table.

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [HVM] Shadow: don't shadow the p2m table.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 07 Sep 2007 09:13:35 -0700
Delivery-date: Fri, 07 Sep 2007 09:20:26 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
# Date 1188554782 -3600
# Node ID 86a154e1ef5d404dd0d6577a03e913e0829462f3
# Parent  9fd5becfba6badee5456501670f46a2e93be5465
[HVM] Shadow: don't shadow the p2m table.
For HVM vcpus with paging disabled, we used to shadow the p2m table,
and skip the p2m lookup to go from gfn to mfn.  Instead, we now
provide a simple pagetable that gives a one-to-one mapping of 4GB, and
shadow that, making the translations from gfn to mfn via the p2m.
This removes the paging-disabled special-case code from the shadow
fault handler, and allows us to expand the p2m interface, since all HVM
translations now go through the same p2m lookups.
Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
---
 xen/arch/x86/domain.c            |    6 +-
 xen/arch/x86/hvm/hvm.c           |    5 -
 xen/arch/x86/mm/hap/hap.c        |    2 
 xen/arch/x86/mm/paging.c         |    5 -
 xen/arch/x86/mm/shadow/common.c  |   95 +++++++++++++++++++-------------
 xen/arch/x86/mm/shadow/multi.c   |  114 ++++++++++++++++-----------------------
 xen/arch/x86/mm/shadow/private.h |    7 ++
 xen/arch/x86/mm/shadow/types.h   |   21 +------
 xen/include/asm-x86/domain.h     |    5 +
 xen/include/asm-x86/p2m.h        |    3 -
 xen/include/asm-x86/paging.h     |   16 -----
 11 files changed, 128 insertions(+), 151 deletions(-)

diff -r 9fd5becfba6b -r 86a154e1ef5d xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Fri Aug 31 10:59:41 2007 +0100
+++ b/xen/arch/x86/domain.c     Fri Aug 31 11:06:22 2007 +0100
@@ -1723,12 +1723,12 @@ void domain_relinquish_resources(struct 
 
     BUG_ON(!cpus_empty(d->domain_dirty_cpumask));
 
+    /* Tear down paging-assistance stuff. */
+    paging_teardown(d);
+
     /* Drop the in-use references to page-table bases. */
     for_each_vcpu ( d, v )
         vcpu_destroy_pagetables(v);
-
-    /* Tear down paging-assistance stuff. */
-    paging_teardown(d);
 
     /*
      * Relinquish GDT mappings. No need for explicit unmapping of the LDT as
diff -r 9fd5becfba6b -r 86a154e1ef5d xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Fri Aug 31 10:59:41 2007 +0100
+++ b/xen/arch/x86/hvm/hvm.c    Fri Aug 31 11:06:22 2007 +0100
@@ -517,7 +517,7 @@ int hvm_set_cr0(unsigned long value)
 int hvm_set_cr0(unsigned long value)
 {
     struct vcpu *v = current;
-    unsigned long mfn, old_base_mfn, old_value = v->arch.hvm_vcpu.guest_cr[0];
+    unsigned long mfn, old_value = v->arch.hvm_vcpu.guest_cr[0];
   
     HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx", value);
 
@@ -569,10 +569,7 @@ int hvm_set_cr0(unsigned long value)
             }
 
             /* Now arch.guest_table points to machine physical. */
-            old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
             v->arch.guest_table = pagetable_from_pfn(mfn);
-            if ( old_base_mfn )
-                put_page(mfn_to_page(old_base_mfn));
 
             HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx",
                         v->arch.hvm_vcpu.guest_cr[3], mfn);
diff -r 9fd5becfba6b -r 86a154e1ef5d xen/arch/x86/mm/hap/hap.c
--- a/xen/arch/x86/mm/hap/hap.c Fri Aug 31 10:59:41 2007 +0100
+++ b/xen/arch/x86/mm/hap/hap.c Fri Aug 31 11:06:22 2007 +0100
@@ -621,8 +621,6 @@ static void hap_update_paging_modes(stru
         hvm_pae_enabled(v)       ? &hap_paging_pae_mode  :
                                    &hap_paging_protected_mode;
 
-    v->arch.paging.translate_enabled = hvm_paging_enabled(v);
-
     if ( pagetable_is_null(v->arch.monitor_table) )
     {
         mfn_t mmfn = hap_make_monitor_table(v);
diff -r 9fd5becfba6b -r 86a154e1ef5d xen/arch/x86/mm/paging.c
--- a/xen/arch/x86/mm/paging.c  Fri Aug 31 10:59:41 2007 +0100
+++ b/xen/arch/x86/mm/paging.c  Fri Aug 31 11:06:22 2007 +0100
@@ -496,10 +496,9 @@ void paging_dump_vcpu_info(struct vcpu *
         if ( paging_mode_shadow(v->domain) )
         {
             if ( v->arch.paging.mode )
-                printk("shadowed %u-on-%u, %stranslated\n",
+                printk("shadowed %u-on-%u\n",
                        v->arch.paging.mode->guest_levels,
-                       v->arch.paging.mode->shadow.shadow_levels,
-                       paging_vcpu_mode_translate(v) ? "" : "not ");
+                       v->arch.paging.mode->shadow.shadow_levels);
             else
                 printk("not shadowed\n");
         }
diff -r 9fd5becfba6b -r 86a154e1ef5d xen/arch/x86/mm/shadow/common.c
--- a/xen/arch/x86/mm/shadow/common.c   Fri Aug 31 10:59:41 2007 +0100
+++ b/xen/arch/x86/mm/shadow/common.c   Fri Aug 31 11:06:22 2007 +0100
@@ -2207,7 +2207,6 @@ static void sh_update_paging_modes(struc
 {
     struct domain *d = v->domain;
     struct paging_mode *old_mode = v->arch.paging.mode;
-    mfn_t old_guest_table;
 
     ASSERT(shadow_locked_by_me(d));
 
@@ -2256,7 +2255,6 @@ static void sh_update_paging_modes(struc
 #else
 #error unexpected paging mode
 #endif
-        v->arch.paging.translate_enabled = !!shadow_mode_translate(d);
     }
     else
     {
@@ -2266,37 +2264,17 @@ static void sh_update_paging_modes(struc
         ASSERT(shadow_mode_translate(d));
         ASSERT(shadow_mode_external(d));
 
-        v->arch.paging.translate_enabled = hvm_paging_enabled(v);
-        if ( !v->arch.paging.translate_enabled )
-        {
-            /* Set v->arch.guest_table to use the p2m map, and choose
-             * the appropriate shadow mode */
-            old_guest_table = pagetable_get_mfn(v->arch.guest_table);
-#if CONFIG_PAGING_LEVELS == 2
-            v->arch.guest_table =
-                pagetable_from_pfn(pagetable_get_pfn(d->arch.phys_table));
-            v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,2,2);
-#elif CONFIG_PAGING_LEVELS == 3 
-            v->arch.guest_table =
-                pagetable_from_pfn(pagetable_get_pfn(d->arch.phys_table));
-            v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,3,3);
-#else /* CONFIG_PAGING_LEVELS == 4 */
-            { 
-                l4_pgentry_t *l4e; 
-                /* Use the start of the first l3 table as a PAE l3 */
-                ASSERT(pagetable_get_pfn(d->arch.phys_table) != 0);
-                l4e = 
sh_map_domain_page(pagetable_get_mfn(d->arch.phys_table));
-                ASSERT(l4e_get_flags(l4e[0]) & _PAGE_PRESENT);
-                v->arch.guest_table =
-                    pagetable_from_pfn(l4e_get_pfn(l4e[0]));
-                sh_unmap_domain_page(l4e);
-            }
-            v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,3,3);
-#endif
-            /* Fix up refcounts on guest_table */
-            get_page(mfn_to_page(pagetable_get_mfn(v->arch.guest_table)), d);
-            if ( mfn_x(old_guest_table) != 0 )
-                put_page(mfn_to_page(old_guest_table));
+        if ( !hvm_paging_enabled(v) )
+        {
+            /* When the guest has CR0.PG clear, we provide a 32-bit, non-PAE
+             * pagetable for it, mapping 4 GB one-to-one using a single l2
+             * page of 1024 superpage mappings */
+            v->arch.guest_table = d->arch.paging.shadow.unpaged_pagetable;
+#if CONFIG_PAGING_LEVELS >= 3
+            v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode, 3, 2);
+#else
+            v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode, 2, 2);
+#endif
         }
         else
         {
@@ -2428,7 +2406,9 @@ int shadow_enable(struct domain *d, u32 
  * Returns 0 for success, -errno for failure. */
 {    
     unsigned int old_pages;
-    int rv = 0;
+    struct page_info *pg = NULL;
+    uint32_t *e;
+    int i, rv = 0;
 
     mode |= PG_SH_enable;
 
@@ -2469,6 +2449,28 @@ int shadow_enable(struct domain *d, u32 
             goto out_unlocked;
     }
 
+    /* HVM domains need an extra pagetable for vcpus that think they
+     * have paging disabled */
+    if ( is_hvm_domain(d) )
+    {
+        /* Get a single page from the shadow pool.  Take it via the 
+         * P2M interface to make freeing it simpler afterwards. */
+        pg = shadow_alloc_p2m_page(d);
+        if ( pg == NULL )
+        {
+            rv = -ENOMEM;
+            goto out_unlocked;
+        }
+        /* Fill it with 32-bit, non-PAE superpage entries, each mapping 4MB
+         * of virtual address space onto the same physical address range */ 
+        e = sh_map_domain_page(page_to_mfn(pg));
+        for ( i = 0; i < PAGE_SIZE / sizeof(*e); i++ )
+            e[i] = ((0x400000U * i)
+                    | _PAGE_PRESENT | _PAGE_RW | _PAGE_USER 
+                    | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_PSE);
+        sh_unmap_domain_page(e);
+        pg->u.inuse.type_info = PGT_l2_page_table | 1 | PGT_validated;
+    }
 
     shadow_lock(d);
 
@@ -2491,6 +2493,10 @@ int shadow_enable(struct domain *d, u32 
      * see the guest use more than one l4 per vcpu. */
     d->arch.paging.shadow.opt_flags = SHOPT_LINUX_L3_TOPLEVEL;
 #endif
+
+    /* Record the 1-to-1 pagetable we just made */
+    if ( is_hvm_domain(d) )
+        d->arch.paging.shadow.unpaged_pagetable = pagetable_from_page(pg);
 
     /* Update the bits */
     sh_new_mode(d, mode);
@@ -2500,6 +2506,8 @@ int shadow_enable(struct domain *d, u32 
  out_unlocked:
     if ( rv != 0 && !pagetable_is_null(d->arch.phys_table) )
         p2m_teardown(d);
+    if ( rv != 0 && pg != NULL )
+        shadow_free_p2m_page(d, pg);
     domain_unpause(d);
     return rv;
 }
@@ -2579,6 +2587,21 @@ void shadow_teardown(struct domain *d)
         ASSERT(d->arch.paging.shadow.total_pages == 0);
     }
 
+    /* Free the non-paged-vcpus pagetable; must happen after we've 
+     * destroyed any shadows of it or sh_destroy_shadow will get confused. */
+    if ( !pagetable_is_null(d->arch.paging.shadow.unpaged_pagetable) )
+    {
+        for_each_vcpu(d, v)
+        {
+            ASSERT(is_hvm_vcpu(v));
+            if ( !hvm_paging_enabled(v) )
+                v->arch.guest_table = pagetable_null();
+        }
+        shadow_free_p2m_page(d, 
+            pagetable_get_page(d->arch.paging.shadow.unpaged_pagetable));
+        d->arch.paging.shadow.unpaged_pagetable = pagetable_null();
+    }
+
     /* We leave the "permanent" shadow modes enabled, but clear the
      * log-dirty mode bit.  We don't want any more mark_dirty()
      * calls now that we've torn down the bitmap */
@@ -2755,10 +2778,6 @@ shadow_write_p2m_entry(struct vcpu *v, u
     
     /* update the entry with new content */
     safe_write_pte(p, new);
-
-    /* The P2M can be shadowed: keep the shadows synced */
-    if ( d->vcpu[0] != NULL )
-        (void)sh_validate_guest_entry(d->vcpu[0], table_mfn, p, sizeof(*p));
 
     /* install P2M in monitors for PAE Xen */
 #if CONFIG_PAGING_LEVELS == 3
diff -r 9fd5becfba6b -r 86a154e1ef5d xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c    Fri Aug 31 10:59:41 2007 +0100
+++ b/xen/arch/x86/mm/shadow/multi.c    Fri Aug 31 11:06:22 2007 +0100
@@ -173,9 +173,12 @@ guest_supports_superpages(struct vcpu *v
 guest_supports_superpages(struct vcpu *v)
 {
     /* The _PAGE_PSE bit must be honoured in HVM guests, whenever
-     * CR4.PSE is set or the guest is in PAE or long mode */
-    return (is_hvm_vcpu(v) && (GUEST_PAGING_LEVELS != 2 
-                             || (v->arch.hvm_vcpu.guest_cr[4] & X86_CR4_PSE)));
+     * CR4.PSE is set or the guest is in PAE or long mode. 
+     * It's also used in the dummy PT for vcpus with CR4.PG cleared. */
+    return (is_hvm_vcpu(v) && 
+            (GUEST_PAGING_LEVELS != 2 
+             || !hvm_paging_enabled(v)
+             || (v->arch.hvm_vcpu.guest_cr[4] & X86_CR4_PSE)));
 }
 
 static inline int
@@ -205,8 +208,9 @@ static inline int
 static inline int 
 guest_walk_tables(struct vcpu *v, unsigned long va, walk_t *gw, int guest_op)
 {
-    ASSERT(!guest_op || shadow_locked_by_me(v->domain));
-
+    struct domain *d = v->domain;
+    ASSERT(!guest_op || shadow_locked_by_me(d));
+    
     perfc_incr(shadow_guest_walk);
     memset(gw, 0, sizeof(*gw));
     gw->va = va;
@@ -219,11 +223,11 @@ guest_walk_tables(struct vcpu *v, unsign
         + 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));
+    gw->l3mfn = gfn_to_mfn(d, guest_l4e_get_gfn(*gw->l4e));
     if ( !mfn_valid(gw->l3mfn) ) return 1;
     /* This mfn is a pagetable: make sure the guest can't write to it. */
     if ( guest_op && sh_remove_write_access(v, gw->l3mfn, 3, va) != 0 )
-        flush_tlb_mask(v->domain->domain_dirty_cpumask); 
+        flush_tlb_mask(d->domain_dirty_cpumask); 
     gw->l3e = ((guest_l3e_t *)sh_map_domain_page(gw->l3mfn))
         + guest_l3_table_offset(va);
 #else /* PAE only... */
@@ -232,11 +236,11 @@ guest_walk_tables(struct vcpu *v, unsign
 #endif /* PAE or 64... */
     /* Walk down to the l2e */
     if ( !(guest_l3e_get_flags(*gw->l3e) & _PAGE_PRESENT) ) return 0;
-    gw->l2mfn = vcpu_gfn_to_mfn(v, guest_l3e_get_gfn(*gw->l3e));
+    gw->l2mfn = gfn_to_mfn(d, guest_l3e_get_gfn(*gw->l3e));
     if ( !mfn_valid(gw->l2mfn) ) return 1;
     /* This mfn is a pagetable: make sure the guest can't write to it. */
     if ( guest_op && sh_remove_write_access(v, gw->l2mfn, 2, va) != 0 )
-        flush_tlb_mask(v->domain->domain_dirty_cpumask); 
+        flush_tlb_mask(d->domain_dirty_cpumask); 
     gw->l2e = ((guest_l2e_t *)sh_map_domain_page(gw->l2mfn))
         + guest_l2_table_offset(va);
 #else /* 32-bit only... */
@@ -274,12 +278,12 @@ guest_walk_tables(struct vcpu *v, unsign
     else 
     {
         /* Not a superpage: carry on and find the l1e. */
-        gw->l1mfn = vcpu_gfn_to_mfn(v, guest_l2e_get_gfn(*gw->l2e));
+        gw->l1mfn = gfn_to_mfn(d, guest_l2e_get_gfn(*gw->l2e));
         if ( !mfn_valid(gw->l1mfn) ) return 1;
         /* This mfn is a pagetable: make sure the guest can't write to it. */
         if ( guest_op 
              && sh_remove_write_access(v, gw->l1mfn, 1, va) != 0 )
-            flush_tlb_mask(v->domain->domain_dirty_cpumask); 
+            flush_tlb_mask(d->domain_dirty_cpumask); 
         gw->l1e = ((guest_l1e_t *)sh_map_domain_page(gw->l1mfn))
             + guest_l1_table_offset(va);
         gw->eff_l1e = *gw->l1e;
@@ -2191,6 +2195,7 @@ static int validate_gl4e(struct vcpu *v,
     guest_l4e_t *new_gl4e = new_ge;
     shadow_l4e_t *sl4p = se;
     mfn_t sl3mfn = _mfn(INVALID_MFN);
+    struct domain *d = v->domain;
     int result = 0;
 
     perfc_incr(shadow_validate_gl4e_calls);
@@ -2198,7 +2203,7 @@ static int validate_gl4e(struct vcpu *v,
     if ( guest_l4e_get_flags(*new_gl4e) & _PAGE_PRESENT )
     {
         gfn_t gl3gfn = guest_l4e_get_gfn(*new_gl4e);
-        mfn_t gl3mfn = vcpu_gfn_to_mfn(v, gl3gfn);
+        mfn_t gl3mfn = gfn_to_mfn(d, gl3gfn);
         if ( mfn_valid(gl3mfn) )
             sl3mfn = get_shadow_status(v, gl3mfn, SH_type_l3_shadow);
         else
@@ -2208,11 +2213,11 @@ static int validate_gl4e(struct vcpu *v,
                              sl3mfn, &new_sl4e, ft_prefetch);
 
     // check for updates to xen reserved slots
-    if ( !shadow_mode_external(v->domain) )
+    if ( !shadow_mode_external(d) )
     {
         int shadow_index = (((unsigned long)sl4p & ~PAGE_MASK) /
                             sizeof(shadow_l4e_t));
-        int reserved_xen_slot = !is_guest_l4_slot(v->domain, shadow_index);
+        int reserved_xen_slot = !is_guest_l4_slot(d, shadow_index);
 
         if ( unlikely(reserved_xen_slot) )
         {
@@ -2250,7 +2255,7 @@ static int validate_gl3e(struct vcpu *v,
     if ( guest_l3e_get_flags(*new_gl3e) & _PAGE_PRESENT )
     {
         gfn_t gl2gfn = guest_l3e_get_gfn(*new_gl3e);
-        mfn_t gl2mfn = vcpu_gfn_to_mfn(v, gl2gfn);
+        mfn_t gl2mfn = gfn_to_mfn(v->domain, gl2gfn);
         if ( mfn_valid(gl2mfn) )
             sl2mfn = get_shadow_status(v, gl2mfn, SH_type_l2_shadow);
         else
@@ -2294,7 +2299,7 @@ static int validate_gl2e(struct vcpu *v,
         }
         else
         {
-            mfn_t gl1mfn = vcpu_gfn_to_mfn(v, gl1gfn);
+            mfn_t gl1mfn = gfn_to_mfn(v->domain, gl1gfn);
             if ( mfn_valid(gl1mfn) )
                 sl1mfn = get_shadow_status(v, gl1mfn, SH_type_l1_shadow);
             else
@@ -2361,10 +2366,9 @@ static int validate_gl1e(struct vcpu *v,
     perfc_incr(shadow_validate_gl1e_calls);
 
     gfn = guest_l1e_get_gfn(*new_gl1e);
-    gmfn = vcpu_gfn_to_mfn(v, gfn);
-
-    mmio = (is_hvm_vcpu(v) && paging_vcpu_mode_translate(v) && 
-            mmio_space(gfn_to_paddr(gfn)));
+    gmfn = gfn_to_mfn(v->domain, gfn);
+
+    mmio = (is_hvm_vcpu(v) && mmio_space(gfn_to_paddr(gfn)));
     l1e_propagate_from_guest(v, new_gl1e, _mfn(INVALID_MFN), gmfn, &new_sl1e, 
                              ft_prefetch, mmio);
     
@@ -2593,10 +2597,8 @@ static void sh_prefetch(struct vcpu *v, 
 
         /* Look at the gfn that the l1e is pointing at */
         gfn = guest_l1e_get_gfn(gl1e);
-        gmfn = vcpu_gfn_to_mfn(v, gfn);
-        mmio = ( is_hvm_vcpu(v) 
-                 && paging_vcpu_mode_translate(v) 
-                 && mmio_space(gfn_to_paddr(gfn)) );
+        gmfn = gfn_to_mfn(v->domain, gfn);
+        mmio = ( is_hvm_vcpu(v) && mmio_space(gfn_to_paddr(gfn)) );
 
         /* Propagate the entry.  Safe to use a pointer to our local 
          * gl1e, since this is not a demand-fetch so there will be no 
@@ -2657,23 +2659,14 @@ static int sh_page_fault(struct vcpu *v,
         {
             if ( sh_l1e_is_gnp(sl1e) )
             {
-                if ( likely(!is_hvm_domain(d) ||
-                            paging_vcpu_mode_translate(v)) )
-                { 
-                    /* Not-present in a guest PT: pass to the guest as
-                     * a not-present fault (by flipping two bits). */
-                    ASSERT(regs->error_code & PFEC_page_present);
-                    regs->error_code ^= (PFEC_reserved_bit|PFEC_page_present);
-                    reset_early_unshadow(v);
-                    perfc_incr(shadow_fault_fast_gnp);
-                    SHADOW_PRINTK("fast path not-present\n");
-                    return 0;
-                }
-                else 
-                {
-                    /* Not-present in the P2M: MMIO */
-                    gpa = va;
-                }
+                /* Not-present in a guest PT: pass to the guest as
+                 * a not-present fault (by flipping two bits). */
+                ASSERT(regs->error_code & PFEC_page_present);
+                regs->error_code ^= (PFEC_reserved_bit|PFEC_page_present);
+                reset_early_unshadow(v);
+                perfc_incr(shadow_fault_fast_gnp);
+                SHADOW_PRINTK("fast path not-present\n");
+                return 0;
             }
             else
             {
@@ -2745,13 +2738,6 @@ static int sh_page_fault(struct vcpu *v,
     //
     if ( unlikely(!(guest_l1e_get_flags(gw.eff_l1e) & _PAGE_PRESENT)) )
     {
-        if ( is_hvm_domain(d) && !paging_vcpu_mode_translate(v) )
-        {
-            /* Not present in p2m map, means this is mmio */
-            gpa = va;
-            goto mmio;
-        }
-
         perfc_incr(shadow_fault_bail_not_present);
         goto not_a_shadow_fault;
     }
@@ -2801,10 +2787,8 @@ static int sh_page_fault(struct vcpu *v,
 
     /* What mfn is the guest trying to access? */
     gfn = guest_l1e_get_gfn(gw.eff_l1e);
-    gmfn = vcpu_gfn_to_mfn(v, gfn);
-    mmio = (is_hvm_domain(d)
-            && paging_vcpu_mode_translate(v) 
-            && mmio_space(gfn_to_paddr(gfn)));
+    gmfn = gfn_to_mfn(d, gfn);
+    mmio = (is_hvm_domain(d) && mmio_space(gfn_to_paddr(gfn)));
 
     if ( !mmio && !mfn_valid(gmfn) )
     {
@@ -3523,20 +3507,18 @@ sh_update_cr3(struct vcpu *v, int do_loc
         ASSERT(shadow_mode_external(d));
 
         // Is paging enabled on this vcpu?
-        if ( paging_vcpu_mode_translate(v) )
+        if ( hvm_paging_enabled(v) )
         {
             gfn = _gfn(paddr_to_pfn(v->arch.hvm_vcpu.guest_cr[3]));
-            gmfn = vcpu_gfn_to_mfn(v, gfn);
+            gmfn = gfn_to_mfn(d, gfn);
             ASSERT(mfn_valid(gmfn));
             ASSERT(pagetable_get_pfn(v->arch.guest_table) == mfn_x(gmfn));
         } 
         else 
         {
-            /* Paging disabled: guest_table points at (part of) p2m */
-#if SHADOW_PAGING_LEVELS != 3 /* in 3-on-4, guest-table is in slot 0 of p2m */
-            /* For everything else, they sould be the same */
-            ASSERT(v->arch.guest_table.pfn == d->arch.phys_table.pfn);
-#endif
+            /* Paging disabled: guest_table points at a 32-bit 1-to-1 map */
+            ASSERT(v->arch.guest_table.pfn
+                   == d->arch.paging.shadow.unpaged_pagetable.pfn);
         }
     }
 #endif
@@ -3574,11 +3556,11 @@ sh_update_cr3(struct vcpu *v, int do_loc
       * 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 */
+     if ( shadow_mode_external(d) ) 
+         /* Find where in the page the l3 table is */
          guest_idx = guest_index((void *)v->arch.hvm_vcpu.guest_cr[3]);
      else
-         /* Paging disabled or PV: l3 is at the start of a page */ 
+         /* PV guest: l3 is at the start of a page */ 
          guest_idx = 0; 
 
      // Ignore the low 2 bits of guest_idx -- they are really just
@@ -3635,7 +3617,7 @@ sh_update_cr3(struct vcpu *v, int do_loc
             if ( guest_l3e_get_flags(gl3e[i]) & _PAGE_PRESENT )
             {
                 gl2gfn = guest_l3e_get_gfn(gl3e[i]);
-                gl2mfn = vcpu_gfn_to_mfn(v, gl2gfn);
+                gl2mfn = gfn_to_mfn(d, gl2gfn);
                 flush |= sh_remove_write_access(v, gl2mfn, 2, 0); 
             }
         }
@@ -3647,7 +3629,7 @@ sh_update_cr3(struct vcpu *v, int do_loc
             if ( guest_l3e_get_flags(gl3e[i]) & _PAGE_PRESENT )
             {
                 gl2gfn = guest_l3e_get_gfn(gl3e[i]);
-                gl2mfn = vcpu_gfn_to_mfn(v, gl2gfn);
+                gl2mfn = gfn_to_mfn(d, gl2gfn);
                 sh_set_toplevel_shadow(v, i, gl2mfn, (i == 3) 
                                        ? SH_type_l2h_shadow 
                                        : SH_type_l2_shadow);
@@ -4001,7 +3983,7 @@ static inline void * emulate_map_dest(st
         }
     }
 #endif
-    mfn = vcpu_gfn_to_mfn(v, gfn);
+    mfn = gfn_to_mfn(v->domain, gfn);
 
     errcode = PFEC_write_access;
     if ( !(flags & _PAGE_PRESENT) ) 
@@ -4268,7 +4250,7 @@ audit_gfn_to_mfn(struct vcpu *v, gfn_t g
          != PGT_writable_page ) 
         return _mfn(gfn_x(gfn)); /* This is a paging-disabled shadow */
     else 
-        return gfn_to_mfn(v->domain, gfn_x(gfn));
+        return gfn_to_mfn(v->domain, gfn);
 } 
 
 
diff -r 9fd5becfba6b -r 86a154e1ef5d xen/arch/x86/mm/shadow/private.h
--- a/xen/arch/x86/mm/shadow/private.h  Fri Aug 31 10:59:41 2007 +0100
+++ b/xen/arch/x86/mm/shadow/private.h  Fri Aug 31 11:06:22 2007 +0100
@@ -431,6 +431,13 @@ int shadow_cmpxchg_guest_entry(struct vc
 #undef mfn_valid
 #define mfn_valid(_mfn) (mfn_x(_mfn) < max_page)
 
+/* Override pagetable_t <-> struct page_info conversions to work with mfn_t */
+#undef pagetable_get_page
+#define pagetable_get_page(x)   mfn_to_page(pagetable_get_mfn(x))
+#undef pagetable_from_page
+#define pagetable_from_page(pg) pagetable_from_mfn(page_to_mfn(pg))
+
+
 #if GUEST_PAGING_LEVELS >= 3
 # define is_lo_pte(_vaddr) (((_vaddr)&0x4)==0)
 #else
diff -r 9fd5becfba6b -r 86a154e1ef5d xen/arch/x86/mm/shadow/types.h
--- a/xen/arch/x86/mm/shadow/types.h    Fri Aug 31 10:59:41 2007 +0100
+++ b/xen/arch/x86/mm/shadow/types.h    Fri Aug 31 11:06:22 2007 +0100
@@ -406,27 +406,16 @@ valid_gfn(gfn_t m)
     return VALID_GFN(gfn_x(m));
 }
 
-/* Translation between mfns and gfns */
-
-// vcpu-specific version of gfn_to_mfn().  This is where we hide the dirty
-// little secret that, for hvm guests with paging disabled, nearly all of the
-// shadow code actually think that the guest is running on *untranslated* page
-// tables (which is actually domain->phys_table).
-//
-
-static inline mfn_t
-vcpu_gfn_to_mfn(struct vcpu *v, gfn_t gfn)
-{
-    if ( !paging_vcpu_mode_translate(v) )
-        return _mfn(gfn_x(gfn));
-    return gfn_to_mfn(v->domain, gfn_x(gfn));
-}
-
 static inline paddr_t
 gfn_to_paddr(gfn_t gfn)
 {
     return ((paddr_t)gfn_x(gfn)) << PAGE_SHIFT;
 }
+
+/* Override gfn_to_mfn to work with gfn_t */
+#undef gfn_to_mfn
+#define gfn_to_mfn(d, g) _gfn_to_mfn((d), gfn_x(g))
+
 
 /* Type used for recording a walk through guest pagetables.  It is
  * filled in by the pagetable walk function, and also used as a cache
diff -r 9fd5becfba6b -r 86a154e1ef5d xen/include/asm-x86/domain.h
--- a/xen/include/asm-x86/domain.h      Fri Aug 31 10:59:41 2007 +0100
+++ b/xen/include/asm-x86/domain.h      Fri Aug 31 11:06:22 2007 +0100
@@ -86,6 +86,9 @@ struct shadow_domain {
     unsigned int      free_pages;   /* number of pages on freelists */
     unsigned int      p2m_pages;    /* number of pages allocates to p2m */
 
+    /* 1-to-1 map for use when HVM vcpus have paging disabled */
+    pagetable_t unpaged_pagetable;
+
     /* Shadow hashtable */
     struct shadow_page_info **hash_table;
     int hash_walking;  /* Some function is walking the hash table */
@@ -181,8 +184,6 @@ struct paging_vcpu {
 struct paging_vcpu {
     /* Pointers to mode-specific entry points. */
     struct paging_mode *mode;
-    /* HVM guest: paging enabled (CR0.PG)?  */
-    unsigned int translate_enabled:1;
     /* HVM guest: last emulate was to a pagetable */
     unsigned int last_write_was_pt:1;
     /* Translated guest: virtual TLB */
diff -r 9fd5becfba6b -r 86a154e1ef5d xen/include/asm-x86/p2m.h
--- a/xen/include/asm-x86/p2m.h Fri Aug 31 10:59:41 2007 +0100
+++ b/xen/include/asm-x86/p2m.h Fri Aug 31 11:06:22 2007 +0100
@@ -61,7 +61,8 @@ mfn_t gfn_to_mfn_foreign(struct domain *
 mfn_t gfn_to_mfn_foreign(struct domain *d, unsigned long gpfn);
 
 /* General conversion function from gfn to mfn */
-static inline mfn_t gfn_to_mfn(struct domain *d, unsigned long gfn)
+#define gfn_to_mfn(d, g) _gfn_to_mfn((d), (g))
+static inline mfn_t _gfn_to_mfn(struct domain *d, unsigned long gfn)
 {
     if ( !paging_mode_translate(d) )
         return _mfn(gfn);
diff -r 9fd5becfba6b -r 86a154e1ef5d xen/include/asm-x86/paging.h
--- a/xen/include/asm-x86/paging.h      Fri Aug 31 10:59:41 2007 +0100
+++ b/xen/include/asm-x86/paging.h      Fri Aug 31 11:06:22 2007 +0100
@@ -65,19 +65,6 @@
 
 /* flags used for paging debug */
 #define PAGING_DEBUG_LOGDIRTY 0
-
-/******************************************************************************
- * The equivalent for a particular vcpu of a shadowed domain. */
-
-/* Is this vcpu using the P2M table to translate between GFNs and MFNs?
- *
- * This is true of translated HVM domains on a vcpu which has paging
- * enabled.  (HVM vcpus with paging disabled are using the p2m table as
- * its paging table, so no translation occurs in this case.)
- * It is also true for all vcpus of translated PV domains. */
-#define paging_vcpu_mode_translate(_v) ((_v)->arch.paging.translate_enabled)
-
-
 
 /*****************************************************************************
  * Mode-specific entry points into the shadow code.  
@@ -222,9 +209,6 @@ static inline int paging_invlpg(struct v
 #define INVALID_GFN (-1UL)
 static inline unsigned long paging_gva_to_gfn(struct vcpu *v, unsigned long va)
 {
-    if ( unlikely(!paging_vcpu_mode_translate(v)) )
-        return va >> PAGE_SHIFT;
-
     return v->arch.paging.mode->gva_to_gfn(v, va);
 }
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [HVM] Shadow: don't shadow the p2m table., Xen patchbot-unstable <=