]> xenbits.xensource.com Git - xen.git/commitdiff
[HVM] Shadow: don't shadow the p2m table.
authorTim Deegan <Tim.Deegan@xensource.com>
Fri, 31 Aug 2007 10:06:22 +0000 (11:06 +0100)
committerTim Deegan <Tim.Deegan@xensource.com>
Fri, 31 Aug 2007 10:06:22 +0000 (11:06 +0100)
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@xensource.com>
xen/arch/x86/domain.c
xen/arch/x86/hvm/hvm.c
xen/arch/x86/mm/hap/hap.c
xen/arch/x86/mm/paging.c
xen/arch/x86/mm/shadow/common.c
xen/arch/x86/mm/shadow/multi.c
xen/arch/x86/mm/shadow/private.h
xen/arch/x86/mm/shadow/types.h
xen/include/asm-x86/domain.h
xen/include/asm-x86/p2m.h
xen/include/asm-x86/paging.h

index 4f56b65f0a5abbc9d3e65e92c2a11d453392b0b7..0f4077f48cf81f3dde2127de26e9842eb565b159 100644 (file)
@@ -1723,13 +1723,13 @@ void domain_relinquish_resources(struct domain *d)
 
     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
      * it automatically gets squashed when the guest's mappings go away.
index cb07b1928925cca0b90db4187606534c68b7a77c..91b5640e541f36b1721c6d377a11feb7539b49a8 100644 (file)
@@ -517,7 +517,7 @@ void hvm_triple_fault(void)
 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);
index 63f16756598f9dd90b91ff9a359ba8f88174a221..af72e0859ebcd00c5bd599d2dfd5bff902ae6dcf 100644 (file)
@@ -621,8 +621,6 @@ static void hap_update_paging_modes(struct vcpu *v)
         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);
index a78f40921a8247b1c9924d479ab61a9b4e47832b..ac4db900a53a8acda7781794b90f4bc610e29677 100644 (file)
@@ -496,10 +496,9 @@ void paging_dump_vcpu_info(struct vcpu *v)
         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");
         }
index 983d442a6c4187fed925e2226a6671d8ac22ea79..b429e99fcf74e58256e4a1ed6ecb5a7d52b985c2 100644 (file)
@@ -2207,7 +2207,6 @@ static void sh_update_paging_modes(struct vcpu *v)
 {
     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(struct vcpu *v)
 #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(struct vcpu *v)
         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 )
+        if ( !hvm_paging_enabled(v) )
         {
-            /* 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);
+            /* 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
-            /* 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));
         }
         else
         {
@@ -2428,7 +2406,9 @@ int shadow_enable(struct domain *d, u32 mode)
  * 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 mode)
             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);
 
@@ -2492,6 +2494,10 @@ int shadow_enable(struct domain *d, u32 mode)
     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 mode)
  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 */
@@ -2756,10 +2779,6 @@ shadow_write_p2m_entry(struct vcpu *v, unsigned long gfn,
     /* 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
     if ( level == 3 ) {
index 84857e43e12303f49951966eda77610a505c9773..34a2d0d07477e05796b4d4f9d0a4bf4ad305f1d6 100644 (file)
@@ -173,9 +173,12 @@ static inline int
 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 @@ guest_supports_nx(struct vcpu *v)
 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, unsigned long va, walk_t *gw, int guest_op)
         + 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, unsigned long va, walk_t *gw, int guest_op)
 #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, unsigned long va, walk_t *gw, int guest_op)
     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, void *new_ge, mfn_t sl4mfn, void *se)
     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, void *new_ge, mfn_t sl4mfn, void *se)
     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, void *new_ge, mfn_t sl4mfn, void *se)
                              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, void *new_ge, mfn_t sl3mfn, void *se)
     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, void *new_ge, mfn_t sl2mfn, void *se)
         }
         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, void *new_ge, mfn_t sl1mfn, void *se)
     perfc_incr(shadow_validate_gl1e_calls);
 
     gfn = guest_l1e_get_gfn(*new_gl1e);
-    gmfn = vcpu_gfn_to_mfn(v, gfn);
+    gmfn = gfn_to_mfn(v->domain, gfn);
 
-    mmio = (is_hvm_vcpu(v) && paging_vcpu_mode_translate(v) && 
-            mmio_space(gfn_to_paddr(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, walk_t *gw,
 
         /* 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_locking)
         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_locking)
       * 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_locking)
             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_locking)
             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(struct vcpu *v,
         }
     }
 #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 gfn, mfn_t gmfn)
          != 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);
 } 
 
 
index 16aad820752c6268704062bc7f9ecdc2fed33a05..173520b0614de72c8779dba4dcb907297950a7cf 100644 (file)
@@ -431,6 +431,13 @@ int shadow_cmpxchg_guest_entry(struct vcpu *v, intpte_t *p,
 #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
index 1595a25a5b70cdf36034c2fea4290c6691ff5f9c..3985279c0646dea41ab77a8615d76791ad899472 100644 (file)
@@ -406,28 +406,17 @@ 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
  * for later walks.  
index f8d311a91ddb2016a87a252cf9eedfdd6bf1a295..9e7659583dfcc8ca67f27d20357cfdfd3f6b42aa 100644 (file)
@@ -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_domain {
 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 */
index 1863da5c3ec16c7049f16c4c9db75016c4780bd8..1a82ebafa398429869b34e053a1516d790e9d6a6 100644 (file)
@@ -61,7 +61,8 @@ static inline mfn_t gfn_to_mfn_current(unsigned long gfn)
 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);
index 35067b289ba4af44a400ac0016ab9b86f77aa609..842c4c7134e03d0ce22804414c092cf2d46b56a5 100644 (file)
 /* 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 vcpu *v, unsigned long va)
 #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);
 }