# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1245315923 -3600
# Node ID cecc76506afc76e6f34b994d06abd35c753baf64
# Parent d835ad2f6980240c4437273e4e2d46bc820c4009
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>
---
xen/arch/x86/domain.c | 61 ++++++++++++++++++++++++++++++-----------
xen/arch/x86/domain_build.c | 3 --
xen/arch/x86/mm.c | 4 --
xen/arch/x86/mm/hap/hap.c | 2 -
xen/arch/x86/mm/shadow/multi.c | 2 -
xen/include/asm-x86/domain.h | 19 ++++++++++++
6 files changed, 68 insertions(+), 23 deletions(-)
diff -r d835ad2f6980 -r cecc76506afc xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c Thu Jun 18 10:04:57 2009 +0100
+++ b/xen/arch/x86/domain.c Thu Jun 18 10:05:23 2009 +0100
@@ -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;
-#endif
- int i, pdpt_order, paging_initialised = 0;
+#else
+ int pdpt_order;
+#endif
+ int i, paging_initialised = 0;
int rc = -ENOMEM;
d->arch.hvm_domain.hap_enabled =
@@ -393,6 +410,8 @@ 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);
@@ -400,21 +419,22 @@ int arch_domain_create(struct domain *d,
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));
}
diff -r d835ad2f6980 -r cecc76506afc xen/arch/x86/domain_build.c
--- a/xen/arch/x86/domain_build.c Thu Jun 18 10:04:57 2009 +0100
+++ b/xen/arch/x86/domain_build.c Thu Jun 18 10:05:23 2009 +0100
@@ -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;
diff -r d835ad2f6980 -r cecc76506afc xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Thu Jun 18 10:04:57 2009 +0100
+++ b/xen/arch/x86/mm.c Thu Jun 18 10:05:23 2009 +0100
@@ -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++ )
diff -r d835ad2f6980 -r cecc76506afc xen/arch/x86/mm/hap/hap.c
--- a/xen/arch/x86/mm/hap/hap.c Thu Jun 18 10:04:57 2009 +0100
+++ b/xen/arch/x86/mm/hap/hap.c Thu Jun 18 10:05:23 2009 +0100
@@ -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. */
diff -r d835ad2f6980 -r cecc76506afc xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c Thu Jun 18 10:04:57 2009 +0100
+++ b/xen/arch/x86/mm/shadow/multi.c Thu Jun 18 10:05:23 2009 +0100
@@ -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
diff -r d835ad2f6980 -r cecc76506afc xen/include/asm-x86/domain.h
--- a/xen/include/asm-x86/domain.h Thu Jun 18 10:04:57 2009 +0100
+++ b/xen/include/asm-x86/domain.h Thu Jun 18 10:05:23 2009 +0100
@@ -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
@@ -301,6 +303,21 @@ struct arch_domain
} __cacheline_aligned;
#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__
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|