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

[Xen-devel] [PATCH 2/3] x86_64: don't allocate L1 per-domain page table pages in a single chunk



Instead, allocate them on demand, and adjust the consumer to no longer
assume the allocated space is contiguous.

This another prerequisite to extend to number of vCPU-s the hypervisor
can support per guest.

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

--- 2009-06-10.orig/xen/arch/x86/domain.c       2009-05-27 13:54:05.000000000 
+0200
+++ 2009-06-10/xen/arch/x86/domain.c    2009-06-10 10:48:19.000000000 +0200
@@ -322,6 +322,22 @@ int vcpu_initialise(struct vcpu *v)
 
 #if defined(__i386__)
     mapcache_vcpu_init(v);
+#else
+    {
+        unsigned int idx = perdomain_pt_pgidx(v);
+        struct page_info *pg;
+
+        if ( !perdomain_pt_page(d, idx) )
+        {
+            pg = alloc_domheap_page(NULL, MEMF_node(vcpu_to_node(v)));
+            if ( !pg )
+                return -ENOMEM;
+            clear_page(page_to_virt(pg));
+            perdomain_pt_page(d, idx) = pg;
+            d->arch.mm_perdomain_l2[l2_table_offset(PERDOMAIN_VIRT_START)+idx]
+                = l2e_from_page(pg, __PAGE_HYPERVISOR);
+        }
+    }
 #endif
 
     pae_l3_cache_init(&v->arch.pae_l3_cache);
@@ -357,8 +373,7 @@ int vcpu_initialise(struct vcpu *v)
             real_cr4_to_pv_guest_cr4(mmu_cr4_features);
     }
 
-    v->arch.perdomain_ptes =
-        d->arch.mm_perdomain_pt + (v->vcpu_id << GDT_LDT_VCPU_SHIFT);
+    v->arch.perdomain_ptes = perdomain_ptes(d, v);
 
     spin_lock_init(&v->arch.shadow_ldt_lock);
 
@@ -378,8 +393,10 @@ int arch_domain_create(struct domain *d,
 {
 #ifdef __x86_64__
     struct page_info *pg;
+#else
+    int pdpt_order;
 #endif
-    int i, pdpt_order, paging_initialised = 0;
+    int i, paging_initialised = 0;
     int rc = -ENOMEM;
 
     d->arch.hvm_domain.hap_enabled =
@@ -394,27 +411,30 @@ int arch_domain_create(struct domain *d,
     d->arch.relmem = RELMEM_not_started;
     INIT_PAGE_LIST_HEAD(&d->arch.relmem_list);
 
+#if defined(__i386__)
+
     pdpt_order = get_order_from_bytes(PDPT_L1_ENTRIES * sizeof(l1_pgentry_t));
     d->arch.mm_perdomain_pt = alloc_xenheap_pages(pdpt_order, 0);
     if ( d->arch.mm_perdomain_pt == NULL )
         goto fail;
     memset(d->arch.mm_perdomain_pt, 0, PAGE_SIZE << pdpt_order);
 
-#if defined(__i386__)
-
     mapcache_domain_init(d);
 
 #else /* __x86_64__ */
 
+    d->arch.mm_perdomain_pt_pages = xmalloc_array(struct page_info *,
+                                                  PDPT_L2_ENTRIES);
+    if ( !d->arch.mm_perdomain_pt_pages )
+        goto fail;
+    memset(d->arch.mm_perdomain_pt_pages, 0,
+           PDPT_L2_ENTRIES * sizeof(*d->arch.mm_perdomain_pt_pages));
+
     pg = alloc_domheap_page(NULL, MEMF_node(domain_to_node(d)));
     if ( pg == NULL )
         goto fail;
     d->arch.mm_perdomain_l2 = page_to_virt(pg);
     clear_page(d->arch.mm_perdomain_l2);
-    for ( i = 0; i < (1 << pdpt_order); i++ )
-        d->arch.mm_perdomain_l2[l2_table_offset(PERDOMAIN_VIRT_START)+i] =
-            l2e_from_page(virt_to_page(d->arch.mm_perdomain_pt)+i,
-                          __PAGE_HYPERVISOR);
 
     pg = alloc_domheap_page(NULL, MEMF_node(domain_to_node(d)));
     if ( pg == NULL )
@@ -503,13 +523,19 @@ int arch_domain_create(struct domain *d,
         free_domheap_page(virt_to_page(d->arch.mm_perdomain_l2));
     if ( d->arch.mm_perdomain_l3 )
         free_domheap_page(virt_to_page(d->arch.mm_perdomain_l3));
-#endif
+    xfree(d->arch.mm_perdomain_pt_pages);
+#else
     free_xenheap_pages(d->arch.mm_perdomain_pt, pdpt_order);
+#endif
     return rc;
 }
 
 void arch_domain_destroy(struct domain *d)
 {
+#ifdef __x86_64__
+    unsigned int i;
+#endif
+
     if ( is_hvm_domain(d) )
         hvm_domain_destroy(d);
 
@@ -520,11 +546,17 @@ void arch_domain_destroy(struct domain *
 
     paging_final_teardown(d);
 
+#ifdef __i386__
     free_xenheap_pages(
         d->arch.mm_perdomain_pt,
         get_order_from_bytes(PDPT_L1_ENTRIES * sizeof(l1_pgentry_t)));
-
-#ifdef __x86_64__
+#else
+    for ( i = 0; i < PDPT_L2_ENTRIES; ++i )
+    {
+        if ( perdomain_pt_page(d, i) )
+            free_domheap_page(perdomain_pt_page(d, i));
+    }
+    xfree(d->arch.mm_perdomain_pt_pages);
     free_domheap_page(virt_to_page(d->arch.mm_perdomain_l2));
     free_domheap_page(virt_to_page(d->arch.mm_perdomain_l3));
 #endif
@@ -1272,8 +1304,7 @@ static void __context_switch(void)
         struct page_info *page = virt_to_page(gdt);
         unsigned int i;
         for ( i = 0; i < NR_RESERVED_GDT_PAGES; i++ )
-            l1e_write(n->domain->arch.mm_perdomain_pt +
-                      (n->vcpu_id << GDT_LDT_VCPU_SHIFT) +
+            l1e_write(n->arch.perdomain_ptes +
                       FIRST_RESERVED_GDT_PAGE + i,
                       l1e_from_page(page + i, __PAGE_HYPERVISOR));
     }
--- 2009-06-10.orig/xen/arch/x86/domain_build.c 2009-05-27 13:54:05.000000000 
+0200
+++ 2009-06-10/xen/arch/x86/domain_build.c      2009-06-10 10:46:31.000000000 
+0200
@@ -480,8 +480,7 @@ int __init construct_dom0(
 
     for ( i = 0; i < PDPT_L2_ENTRIES; i++ )
         l2tab[l2_linear_offset(PERDOMAIN_VIRT_START) + i] =
-            l2e_from_page(virt_to_page(d->arch.mm_perdomain_pt) + i,
-                          __PAGE_HYPERVISOR);
+            l2e_from_page(perdomain_pt_page(d, i), __PAGE_HYPERVISOR);
 
     l2tab += l2_linear_offset(v_start);
     mfn = alloc_spfn;
--- 2009-06-10.orig/xen/arch/x86/mm.c   2009-06-10 10:46:17.000000000 +0200
+++ 2009-06-10/xen/arch/x86/mm.c        2009-06-10 10:46:31.000000000 +0200
@@ -1207,9 +1207,7 @@ static int create_pae_xen_mappings(struc
            L2_PAGETABLE_XEN_SLOTS * sizeof(l2_pgentry_t));
     for ( i = 0; i < PDPT_L2_ENTRIES; i++ )
     {
-        l2e = l2e_from_page(
-            virt_to_page(d->arch.mm_perdomain_pt) + i,
-            __PAGE_HYPERVISOR);
+        l2e = l2e_from_page(perdomain_pt_page(d, i), __PAGE_HYPERVISOR);
         l2e_write(&pl2e[l2_table_offset(PERDOMAIN_VIRT_START) + i], l2e);
     }
     for ( i = 0; i < (LINEARPT_MBYTES >> (L2_PAGETABLE_SHIFT - 20)); i++ )
--- 2009-06-10.orig/xen/arch/x86/mm/hap/hap.c   2009-06-08 08:44:53.000000000 
+0200
+++ 2009-06-10/xen/arch/x86/mm/hap/hap.c        2009-06-10 10:46:31.000000000 
+0200
@@ -437,7 +437,7 @@ static void hap_install_xen_entries_in_l
     for ( i = 0; i < PDPT_L2_ENTRIES; i++ )
         l2e[l2_table_offset(PERDOMAIN_VIRT_START) + i] =
             l2e_from_pfn(
-                mfn_x(page_to_mfn(virt_to_page(d->arch.mm_perdomain_pt) + i)),
+                mfn_x(page_to_mfn(perdomain_pt_page(d, i))),
                 __PAGE_HYPERVISOR);
 
     /* No linear mapping; will be set up by monitor-table contructor. */
--- 2009-06-10.orig/xen/arch/x86/mm/shadow/multi.c      2009-06-08 
08:44:53.000000000 +0200
+++ 2009-06-10/xen/arch/x86/mm/shadow/multi.c   2009-06-10 10:46:31.000000000 
+0200
@@ -1470,7 +1470,7 @@ static void sh_install_xen_entries_in_l2
     for ( i = 0; i < PDPT_L2_ENTRIES; i++ )
         sl2e[shadow_l2_table_offset(PERDOMAIN_VIRT_START) + i] =
             shadow_l2e_from_mfn(
-                page_to_mfn(virt_to_page(d->arch.mm_perdomain_pt) + i),
+                page_to_mfn(perdomain_pt_page(d, i)),
                 __PAGE_HYPERVISOR);
     
     /* We don't set up a linear mapping here because we can't until this
--- 2009-06-10.orig/xen/include/asm-x86/domain.h        2009-05-27 
13:54:07.000000000 +0200
+++ 2009-06-10/xen/include/asm-x86/domain.h     2009-06-10 10:46:31.000000000 
+0200
@@ -231,10 +231,12 @@ struct domain_mca_msrs
 
 struct arch_domain
 {
-    l1_pgentry_t *mm_perdomain_pt;
 #ifdef CONFIG_X86_64
+    struct page_info **mm_perdomain_pt_pages;
     l2_pgentry_t *mm_perdomain_l2;
     l3_pgentry_t *mm_perdomain_l3;
+#else
+    l1_pgentry_t *mm_perdomain_pt;
 #endif
 
 #ifdef CONFIG_X86_32
@@ -302,6 +304,21 @@ struct arch_domain
 
 #define has_arch_pdevs(d)    (!list_empty(&(d)->arch.pdev_list))
 
+#ifdef CONFIG_X86_64
+#define perdomain_pt_pgidx(v) \
+      ((v)->vcpu_id >> (PAGETABLE_ORDER - GDT_LDT_VCPU_SHIFT))
+#define perdomain_ptes(d, v) \
+    ((l1_pgentry_t *)page_to_virt((d)->arch.mm_perdomain_pt_pages \
+      [perdomain_pt_pgidx(v)]) + (((v)->vcpu_id << GDT_LDT_VCPU_SHIFT) & \
+                                  (L1_PAGETABLE_ENTRIES - 1)))
+#define perdomain_pt_page(d, n) ((d)->arch.mm_perdomain_pt_pages[n])
+#else
+#define perdomain_ptes(d, v) \
+    ((d)->arch.mm_perdomain_pt + ((v)->vcpu_id << GDT_LDT_VCPU_SHIFT))
+#define perdomain_pt_page(d, n) \
+    (virt_to_page((d)->arch.mm_perdomain_pt) + (n))
+#endif
+
 
 #ifdef __i386__
 struct pae_l3_cache {



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


 


Rackspace

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