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

[Xen-devel] [PATCH 07/11] x86: properly use map_domain_page() during page table manipulation


  • To: "xen-devel" <xen-devel@xxxxxxxxxxxxx>
  • From: "Jan Beulich" <JBeulich@xxxxxxxx>
  • Date: Tue, 22 Jan 2013 10:55:15 +0000
  • Delivery-date: Tue, 22 Jan 2013 10:55:31 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xen.org>

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>

--- a/xen/arch/x86/debug.c
+++ b/xen/arch/x86/debug.c
@@ -98,8 +98,9 @@ dbg_pv_va2mfn(dbgva_t vaddr, struct doma
 
     if ( pgd3val == 0 )
     {
-        l4t = mfn_to_virt(mfn);
+        l4t = map_domain_page(mfn);
         l4e = l4t[l4_table_offset(vaddr)];
+        unmap_domain_page(l4t);
         mfn = l4e_get_pfn(l4e);
         DBGP2("l4t:%p l4to:%lx l4e:%lx mfn:%lx\n", l4t, 
               l4_table_offset(vaddr), l4e, mfn);
@@ -109,20 +110,23 @@ dbg_pv_va2mfn(dbgva_t vaddr, struct doma
             return INVALID_MFN;
         }
 
-        l3t = mfn_to_virt(mfn);
+        l3t = map_domain_page(mfn);
         l3e = l3t[l3_table_offset(vaddr)];
+        unmap_domain_page(l3t);
         mfn = l3e_get_pfn(l3e);
         DBGP2("l3t:%p l3to:%lx l3e:%lx mfn:%lx\n", l3t, 
               l3_table_offset(vaddr), l3e, mfn);
-        if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) )
+        if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) ||
+             (l3e_get_flags(l3e) & _PAGE_PSE) )
         {
             DBGP1("l3 PAGE not present. vaddr:%lx cr3:%lx\n", vaddr, cr3);
             return INVALID_MFN;
         }
     }
 
-    l2t = mfn_to_virt(mfn);
+    l2t = map_domain_page(mfn);
     l2e = l2t[l2_table_offset(vaddr)];
+    unmap_domain_page(l2t);
     mfn = l2e_get_pfn(l2e);
     DBGP2("l2t:%p l2to:%lx l2e:%lx mfn:%lx\n", l2t, l2_table_offset(vaddr),
           l2e, mfn);
@@ -132,8 +136,9 @@ dbg_pv_va2mfn(dbgva_t vaddr, struct doma
         DBGP1("l2 PAGE not present. vaddr:%lx cr3:%lx\n", vaddr, cr3);
         return INVALID_MFN;
     }
-    l1t = mfn_to_virt(mfn);
+    l1t = map_domain_page(mfn);
     l1e = l1t[l1_table_offset(vaddr)];
+    unmap_domain_page(l1t);
     mfn = l1e_get_pfn(l1e);
     DBGP2("l1t:%p l1to:%lx l1e:%lx mfn:%lx\n", l1t, l1_table_offset(vaddr),
           l1e, mfn);
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -1331,7 +1331,7 @@ static int alloc_l4_table(struct page_in
 {
     struct domain *d = page_get_owner(page);
     unsigned long  pfn = page_to_mfn(page);
-    l4_pgentry_t  *pl4e = page_to_virt(page);
+    l4_pgentry_t  *pl4e = map_domain_page(pfn);
     unsigned int   i;
     int            rc = 0, partial = page->partial_pte;
 
@@ -1365,12 +1365,16 @@ static int alloc_l4_table(struct page_in
                     put_page_from_l4e(pl4e[i], pfn, 0, 0);
         }
         if ( rc < 0 )
+        {
+            unmap_domain_page(pl4e);
             return rc;
+        }
 
         adjust_guest_l4e(pl4e[i], d);
     }
 
     init_guest_l4_table(pl4e, d);
+    unmap_domain_page(pl4e);
 
     return rc > 0 ? 0 : rc;
 }
@@ -1464,7 +1468,7 @@ static int free_l4_table(struct page_inf
 {
     struct domain *d = page_get_owner(page);
     unsigned long pfn = page_to_mfn(page);
-    l4_pgentry_t *pl4e = page_to_virt(page);
+    l4_pgentry_t *pl4e = map_domain_page(pfn);
     int rc = 0, partial = page->partial_pte;
     unsigned int  i = page->nr_validated_ptes - !partial;
 
@@ -1487,6 +1491,9 @@ static int free_l4_table(struct page_inf
         page->partial_pte = 0;
         rc = -EAGAIN;
     }
+
+    unmap_domain_page(pl4e);
+
     return rc > 0 ? 0 : rc;
 }
 
@@ -4983,15 +4990,23 @@ int mmio_ro_do_page_fault(struct vcpu *v
     return rc != X86EMUL_UNHANDLEABLE ? EXCRET_fault_fixed : 0;
 }
 
-void free_xen_pagetable(void *v)
+void *alloc_xen_pagetable(void)
 {
-    if ( system_state == SYS_STATE_early_boot )
-        return;
+    if ( system_state != SYS_STATE_early_boot )
+    {
+        void *ptr = alloc_xenheap_page();
 
-    if ( is_xen_heap_page(virt_to_page(v)) )
+        BUG_ON(!dom0 && !ptr);
+        return ptr;
+    }
+
+    return mfn_to_virt(alloc_boot_pages(1, 1));
+}
+
+void free_xen_pagetable(void *v)
+{
+    if ( system_state != SYS_STATE_early_boot )
         free_xenheap_page(v);
-    else
-        free_domheap_page(virt_to_page(v));
 }
 
 /* Convert to from superpage-mapping flags for map_pages_to_xen(). */
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -180,6 +180,11 @@ static void show_guest_stack(struct vcpu
         printk(" %p", _p(addr));
         stack++;
     }
+    if ( mask == PAGE_SIZE )
+    {
+        BUILD_BUG_ON(PAGE_SIZE == STACK_SIZE);
+        unmap_domain_page(stack);
+    }
     if ( i == 0 )
         printk("Stack empty.");
     printk("\n");
--- a/xen/arch/x86/x86_64/compat/traps.c
+++ b/xen/arch/x86/x86_64/compat/traps.c
@@ -56,6 +56,11 @@ void compat_show_guest_stack(struct vcpu
         printk(" %08x", addr);
         stack++;
     }
+    if ( mask == PAGE_SIZE )
+    {
+        BUILD_BUG_ON(PAGE_SIZE == STACK_SIZE);
+        unmap_domain_page(stack);
+    }
     if ( i == 0 )
         printk("Stack empty.");
     printk("\n");
--- a/xen/arch/x86/x86_64/mm.c
+++ b/xen/arch/x86/x86_64/mm.c
@@ -65,22 +65,6 @@ int __mfn_valid(unsigned long mfn)
                            pdx_group_valid));
 }
 
-void *alloc_xen_pagetable(void)
-{
-    unsigned long mfn;
-
-    if ( system_state != SYS_STATE_early_boot )
-    {
-        struct page_info *pg = alloc_domheap_page(NULL, 0);
-
-        BUG_ON(!dom0 && !pg);
-        return pg ? page_to_virt(pg) : NULL;
-    }
-
-    mfn = alloc_boot_pages(1, 1);
-    return mfn_to_virt(mfn);
-}
-
 l3_pgentry_t *virt_to_xen_l3e(unsigned long v)
 {
     l4_pgentry_t *pl4e;
@@ -154,35 +138,45 @@ void *do_page_walk(struct vcpu *v, unsig
     if ( is_hvm_vcpu(v) )
         return NULL;
 
-    l4t = mfn_to_virt(mfn);
+    l4t = map_domain_page(mfn);
     l4e = l4t[l4_table_offset(addr)];
-    mfn = l4e_get_pfn(l4e);
+    unmap_domain_page(l4t);
     if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
         return NULL;
 
-    l3t = mfn_to_virt(mfn);
+    l3t = map_l3t_from_l4e(l4e);
     l3e = l3t[l3_table_offset(addr)];
+    unmap_domain_page(l3t);
     mfn = l3e_get_pfn(l3e);
     if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) || !mfn_valid(mfn) )
         return NULL;
     if ( (l3e_get_flags(l3e) & _PAGE_PSE) )
-        return mfn_to_virt(mfn) + (addr & ((1UL << L3_PAGETABLE_SHIFT) - 1));
+    {
+        mfn += PFN_DOWN(addr & ((1UL << L3_PAGETABLE_SHIFT) - 1));
+        goto ret;
+    }
 
-    l2t = mfn_to_virt(mfn);
+    l2t = map_domain_page(mfn);
     l2e = l2t[l2_table_offset(addr)];
+    unmap_domain_page(l2t);
     mfn = l2e_get_pfn(l2e);
     if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) || !mfn_valid(mfn) )
         return NULL;
     if ( (l2e_get_flags(l2e) & _PAGE_PSE) )
-        return mfn_to_virt(mfn) + (addr & ((1UL << L2_PAGETABLE_SHIFT) - 1));
+    {
+        mfn += PFN_DOWN(addr & ((1UL << L2_PAGETABLE_SHIFT) - 1));
+        goto ret;
+    }
 
-    l1t = mfn_to_virt(mfn);
+    l1t = map_domain_page(mfn);
     l1e = l1t[l1_table_offset(addr)];
+    unmap_domain_page(l1t);
     mfn = l1e_get_pfn(l1e);
     if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) || !mfn_valid(mfn) )
         return NULL;
 
-    return mfn_to_virt(mfn) + (addr & ~PAGE_MASK);
+ ret:
+    return map_domain_page(mfn) + (addr & ~PAGE_MASK);
 }
 
 void __init pfn_pdx_hole_setup(unsigned long mask)
@@ -519,10 +513,9 @@ static int setup_compat_m2p_table(struct
 static int setup_m2p_table(struct mem_hotadd_info *info)
 {
     unsigned long i, va, smap, emap;
-    unsigned int n, memflags;
+    unsigned int n;
     l2_pgentry_t *l2_ro_mpt = NULL;
     l3_pgentry_t *l3_ro_mpt = NULL;
-    struct page_info *l2_pg;
     int ret = 0;
 
     ASSERT(l4e_get_flags(idle_pg_table[l4_table_offset(RO_MPT_VIRT_START)])
@@ -560,7 +553,6 @@ static int setup_m2p_table(struct mem_ho
         }
 
         va = RO_MPT_VIRT_START + i * sizeof(*machine_to_phys_mapping);
-        memflags = MEMF_node(phys_to_nid(i << PAGE_SHIFT));
 
         for ( n = 0; n < CNT; ++n)
             if ( mfn_valid(i + n * PDX_GROUP_COUNT) )
@@ -587,19 +579,18 @@ static int setup_m2p_table(struct mem_ho
                   l2_table_offset(va);
             else
             {
-                l2_pg = alloc_domheap_page(NULL, memflags);
-
-                if (!l2_pg)
+                l2_ro_mpt = alloc_xen_pagetable();
+                if ( !l2_ro_mpt )
                 {
                     ret = -ENOMEM;
                     goto error;
                 }
 
-                l2_ro_mpt = page_to_virt(l2_pg);
                 clear_page(l2_ro_mpt);
                 l3e_write(&l3_ro_mpt[l3_table_offset(va)],
-                  l3e_from_page(l2_pg, __PAGE_HYPERVISOR | _PAGE_USER));
-               l2_ro_mpt += l2_table_offset(va);
+                          l3e_from_paddr(__pa(l2_ro_mpt),
+                                         __PAGE_HYPERVISOR | _PAGE_USER));
+                l2_ro_mpt += l2_table_offset(va);
             }
 
             /* NB. Cannot be GLOBAL as shadow_mode_translate reuses this area. 
*/
@@ -762,12 +753,12 @@ void __init paging_init(void)
                  l4_table_offset(HIRO_COMPAT_MPT_VIRT_START));
     l3_ro_mpt = l4e_to_l3e(idle_pg_table[l4_table_offset(
         HIRO_COMPAT_MPT_VIRT_START)]);
-    if ( (l2_pg = alloc_domheap_page(NULL, 0)) == NULL )
+    if ( (l2_ro_mpt = alloc_xen_pagetable()) == NULL )
         goto nomem;
-    compat_idle_pg_table_l2 = l2_ro_mpt = page_to_virt(l2_pg);
+    compat_idle_pg_table_l2 = l2_ro_mpt;
     clear_page(l2_ro_mpt);
     l3e_write(&l3_ro_mpt[l3_table_offset(HIRO_COMPAT_MPT_VIRT_START)],
-              l3e_from_page(l2_pg, __PAGE_HYPERVISOR));
+              l3e_from_paddr(__pa(l2_ro_mpt), __PAGE_HYPERVISOR));
     l2_ro_mpt += l2_table_offset(HIRO_COMPAT_MPT_VIRT_START);
     /* Allocate and map the compatibility mode machine-to-phys table. */
     mpt_size = (mpt_size >> 1) + (1UL << (L2_PAGETABLE_SHIFT - 1));
--- a/xen/arch/x86/x86_64/traps.c
+++ b/xen/arch/x86/x86_64/traps.c
@@ -175,8 +175,9 @@ void show_page_walk(unsigned long addr)
 
     printk("Pagetable walk from %016lx:\n", addr);
 
-    l4t = mfn_to_virt(mfn);
+    l4t = map_domain_page(mfn);
     l4e = l4t[l4_table_offset(addr)];
+    unmap_domain_page(l4t);
     mfn = l4e_get_pfn(l4e);
     pfn = mfn_valid(mfn) && machine_to_phys_mapping_valid ?
           get_gpfn_from_mfn(mfn) : INVALID_M2P_ENTRY;
@@ -186,8 +187,9 @@ void show_page_walk(unsigned long addr)
          !mfn_valid(mfn) )
         return;
 
-    l3t = mfn_to_virt(mfn);
+    l3t = map_domain_page(mfn);
     l3e = l3t[l3_table_offset(addr)];
+    unmap_domain_page(l3t);
     mfn = l3e_get_pfn(l3e);
     pfn = mfn_valid(mfn) && machine_to_phys_mapping_valid ?
           get_gpfn_from_mfn(mfn) : INVALID_M2P_ENTRY;
@@ -199,8 +201,9 @@ void show_page_walk(unsigned long addr)
          !mfn_valid(mfn) )
         return;
 
-    l2t = mfn_to_virt(mfn);
+    l2t = map_domain_page(mfn);
     l2e = l2t[l2_table_offset(addr)];
+    unmap_domain_page(l2t);
     mfn = l2e_get_pfn(l2e);
     pfn = mfn_valid(mfn) && machine_to_phys_mapping_valid ?
           get_gpfn_from_mfn(mfn) : INVALID_M2P_ENTRY;
@@ -212,8 +215,9 @@ void show_page_walk(unsigned long addr)
          !mfn_valid(mfn) )
         return;
 
-    l1t = mfn_to_virt(mfn);
+    l1t = map_domain_page(mfn);
     l1e = l1t[l1_table_offset(addr)];
+    unmap_domain_page(l1t);
     mfn = l1e_get_pfn(l1e);
     pfn = mfn_valid(mfn) && machine_to_phys_mapping_valid ?
           get_gpfn_from_mfn(mfn) : INVALID_M2P_ENTRY;
--- a/xen/include/asm-x86/page.h
+++ b/xen/include/asm-x86/page.h
@@ -172,6 +172,10 @@ static inline l4_pgentry_t l4e_from_padd
 #define l3e_to_l2e(x)              ((l2_pgentry_t *)__va(l3e_get_paddr(x)))
 #define l4e_to_l3e(x)              ((l3_pgentry_t *)__va(l4e_get_paddr(x)))
 
+#define map_l1t_from_l2e(x)        ((l1_pgentry_t 
*)map_domain_page(l2e_get_pfn(x)))
+#define map_l2t_from_l3e(x)        ((l2_pgentry_t 
*)map_domain_page(l3e_get_pfn(x)))
+#define map_l3t_from_l4e(x)        ((l3_pgentry_t 
*)map_domain_page(l4e_get_pfn(x)))
+
 /* Given a virtual address, get an entry offset into a page table. */
 #define l1_table_offset(a)         \
     (((a) >> L1_PAGETABLE_SHIFT) & (L1_PAGETABLE_ENTRIES - 1))


Attachment: x86-map-domain-pagetable.patch
Description: Text document

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel

 


Rackspace

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