ia64/xen-unstable

changeset 19787:cecc76506afc

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@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jun 18 10:05:23 2009 +0100 (2009-06-18)
parents d835ad2f6980
children 2f9e1348aa98
files xen/arch/x86/domain.c xen/arch/x86/domain_build.c xen/arch/x86/mm.c xen/arch/x86/mm/hap/hap.c xen/arch/x86/mm/shadow/multi.c xen/include/asm-x86/domain.h
line diff
     1.1 --- a/xen/arch/x86/domain.c	Thu Jun 18 10:04:57 2009 +0100
     1.2 +++ b/xen/arch/x86/domain.c	Thu Jun 18 10:05:23 2009 +0100
     1.3 @@ -322,6 +322,22 @@ int vcpu_initialise(struct vcpu *v)
     1.4  
     1.5  #if defined(__i386__)
     1.6      mapcache_vcpu_init(v);
     1.7 +#else
     1.8 +    {
     1.9 +        unsigned int idx = perdomain_pt_pgidx(v);
    1.10 +        struct page_info *pg;
    1.11 +
    1.12 +        if ( !perdomain_pt_page(d, idx) )
    1.13 +        {
    1.14 +            pg = alloc_domheap_page(NULL, MEMF_node(vcpu_to_node(v)));
    1.15 +            if ( !pg )
    1.16 +                return -ENOMEM;
    1.17 +            clear_page(page_to_virt(pg));
    1.18 +            perdomain_pt_page(d, idx) = pg;
    1.19 +            d->arch.mm_perdomain_l2[l2_table_offset(PERDOMAIN_VIRT_START)+idx]
    1.20 +                = l2e_from_page(pg, __PAGE_HYPERVISOR);
    1.21 +        }
    1.22 +    }
    1.23  #endif
    1.24  
    1.25      pae_l3_cache_init(&v->arch.pae_l3_cache);
    1.26 @@ -357,8 +373,7 @@ int vcpu_initialise(struct vcpu *v)
    1.27              real_cr4_to_pv_guest_cr4(mmu_cr4_features);
    1.28      }
    1.29  
    1.30 -    v->arch.perdomain_ptes =
    1.31 -        d->arch.mm_perdomain_pt + (v->vcpu_id << GDT_LDT_VCPU_SHIFT);
    1.32 +    v->arch.perdomain_ptes = perdomain_ptes(d, v);
    1.33  
    1.34      spin_lock_init(&v->arch.shadow_ldt_lock);
    1.35  
    1.36 @@ -378,8 +393,10 @@ int arch_domain_create(struct domain *d,
    1.37  {
    1.38  #ifdef __x86_64__
    1.39      struct page_info *pg;
    1.40 +#else
    1.41 +    int pdpt_order;
    1.42  #endif
    1.43 -    int i, pdpt_order, paging_initialised = 0;
    1.44 +    int i, paging_initialised = 0;
    1.45      int rc = -ENOMEM;
    1.46  
    1.47      d->arch.hvm_domain.hap_enabled =
    1.48 @@ -394,27 +411,30 @@ int arch_domain_create(struct domain *d,
    1.49      d->arch.relmem = RELMEM_not_started;
    1.50      INIT_PAGE_LIST_HEAD(&d->arch.relmem_list);
    1.51  
    1.52 +#if defined(__i386__)
    1.53 +
    1.54      pdpt_order = get_order_from_bytes(PDPT_L1_ENTRIES * sizeof(l1_pgentry_t));
    1.55      d->arch.mm_perdomain_pt = alloc_xenheap_pages(pdpt_order, 0);
    1.56      if ( d->arch.mm_perdomain_pt == NULL )
    1.57          goto fail;
    1.58      memset(d->arch.mm_perdomain_pt, 0, PAGE_SIZE << pdpt_order);
    1.59  
    1.60 -#if defined(__i386__)
    1.61 -
    1.62      mapcache_domain_init(d);
    1.63  
    1.64  #else /* __x86_64__ */
    1.65  
    1.66 +    d->arch.mm_perdomain_pt_pages = xmalloc_array(struct page_info *,
    1.67 +                                                  PDPT_L2_ENTRIES);
    1.68 +    if ( !d->arch.mm_perdomain_pt_pages )
    1.69 +        goto fail;
    1.70 +    memset(d->arch.mm_perdomain_pt_pages, 0,
    1.71 +           PDPT_L2_ENTRIES * sizeof(*d->arch.mm_perdomain_pt_pages));
    1.72 +
    1.73      pg = alloc_domheap_page(NULL, MEMF_node(domain_to_node(d)));
    1.74      if ( pg == NULL )
    1.75          goto fail;
    1.76      d->arch.mm_perdomain_l2 = page_to_virt(pg);
    1.77      clear_page(d->arch.mm_perdomain_l2);
    1.78 -    for ( i = 0; i < (1 << pdpt_order); i++ )
    1.79 -        d->arch.mm_perdomain_l2[l2_table_offset(PERDOMAIN_VIRT_START)+i] =
    1.80 -            l2e_from_page(virt_to_page(d->arch.mm_perdomain_pt)+i,
    1.81 -                          __PAGE_HYPERVISOR);
    1.82  
    1.83      pg = alloc_domheap_page(NULL, MEMF_node(domain_to_node(d)));
    1.84      if ( pg == NULL )
    1.85 @@ -503,13 +523,19 @@ int arch_domain_create(struct domain *d,
    1.86          free_domheap_page(virt_to_page(d->arch.mm_perdomain_l2));
    1.87      if ( d->arch.mm_perdomain_l3 )
    1.88          free_domheap_page(virt_to_page(d->arch.mm_perdomain_l3));
    1.89 +    xfree(d->arch.mm_perdomain_pt_pages);
    1.90 +#else
    1.91 +    free_xenheap_pages(d->arch.mm_perdomain_pt, pdpt_order);
    1.92  #endif
    1.93 -    free_xenheap_pages(d->arch.mm_perdomain_pt, pdpt_order);
    1.94      return rc;
    1.95  }
    1.96  
    1.97  void arch_domain_destroy(struct domain *d)
    1.98  {
    1.99 +#ifdef __x86_64__
   1.100 +    unsigned int i;
   1.101 +#endif
   1.102 +
   1.103      if ( is_hvm_domain(d) )
   1.104          hvm_domain_destroy(d);
   1.105  
   1.106 @@ -520,11 +546,17 @@ void arch_domain_destroy(struct domain *
   1.107  
   1.108      paging_final_teardown(d);
   1.109  
   1.110 +#ifdef __i386__
   1.111      free_xenheap_pages(
   1.112          d->arch.mm_perdomain_pt,
   1.113          get_order_from_bytes(PDPT_L1_ENTRIES * sizeof(l1_pgentry_t)));
   1.114 -
   1.115 -#ifdef __x86_64__
   1.116 +#else
   1.117 +    for ( i = 0; i < PDPT_L2_ENTRIES; ++i )
   1.118 +    {
   1.119 +        if ( perdomain_pt_page(d, i) )
   1.120 +            free_domheap_page(perdomain_pt_page(d, i));
   1.121 +    }
   1.122 +    xfree(d->arch.mm_perdomain_pt_pages);
   1.123      free_domheap_page(virt_to_page(d->arch.mm_perdomain_l2));
   1.124      free_domheap_page(virt_to_page(d->arch.mm_perdomain_l3));
   1.125  #endif
   1.126 @@ -1272,8 +1304,7 @@ static void __context_switch(void)
   1.127          struct page_info *page = virt_to_page(gdt);
   1.128          unsigned int i;
   1.129          for ( i = 0; i < NR_RESERVED_GDT_PAGES; i++ )
   1.130 -            l1e_write(n->domain->arch.mm_perdomain_pt +
   1.131 -                      (n->vcpu_id << GDT_LDT_VCPU_SHIFT) +
   1.132 +            l1e_write(n->arch.perdomain_ptes +
   1.133                        FIRST_RESERVED_GDT_PAGE + i,
   1.134                        l1e_from_page(page + i, __PAGE_HYPERVISOR));
   1.135      }
     2.1 --- a/xen/arch/x86/domain_build.c	Thu Jun 18 10:04:57 2009 +0100
     2.2 +++ b/xen/arch/x86/domain_build.c	Thu Jun 18 10:05:23 2009 +0100
     2.3 @@ -480,8 +480,7 @@ int __init construct_dom0(
     2.4  
     2.5      for ( i = 0; i < PDPT_L2_ENTRIES; i++ )
     2.6          l2tab[l2_linear_offset(PERDOMAIN_VIRT_START) + i] =
     2.7 -            l2e_from_page(virt_to_page(d->arch.mm_perdomain_pt) + i,
     2.8 -                          __PAGE_HYPERVISOR);
     2.9 +            l2e_from_page(perdomain_pt_page(d, i), __PAGE_HYPERVISOR);
    2.10  
    2.11      l2tab += l2_linear_offset(v_start);
    2.12      mfn = alloc_spfn;
     3.1 --- a/xen/arch/x86/mm.c	Thu Jun 18 10:04:57 2009 +0100
     3.2 +++ b/xen/arch/x86/mm.c	Thu Jun 18 10:05:23 2009 +0100
     3.3 @@ -1207,9 +1207,7 @@ static int create_pae_xen_mappings(struc
     3.4             L2_PAGETABLE_XEN_SLOTS * sizeof(l2_pgentry_t));
     3.5      for ( i = 0; i < PDPT_L2_ENTRIES; i++ )
     3.6      {
     3.7 -        l2e = l2e_from_page(
     3.8 -            virt_to_page(d->arch.mm_perdomain_pt) + i,
     3.9 -            __PAGE_HYPERVISOR);
    3.10 +        l2e = l2e_from_page(perdomain_pt_page(d, i), __PAGE_HYPERVISOR);
    3.11          l2e_write(&pl2e[l2_table_offset(PERDOMAIN_VIRT_START) + i], l2e);
    3.12      }
    3.13      for ( i = 0; i < (LINEARPT_MBYTES >> (L2_PAGETABLE_SHIFT - 20)); i++ )
     4.1 --- a/xen/arch/x86/mm/hap/hap.c	Thu Jun 18 10:04:57 2009 +0100
     4.2 +++ b/xen/arch/x86/mm/hap/hap.c	Thu Jun 18 10:05:23 2009 +0100
     4.3 @@ -437,7 +437,7 @@ static void hap_install_xen_entries_in_l
     4.4      for ( i = 0; i < PDPT_L2_ENTRIES; i++ )
     4.5          l2e[l2_table_offset(PERDOMAIN_VIRT_START) + i] =
     4.6              l2e_from_pfn(
     4.7 -                mfn_x(page_to_mfn(virt_to_page(d->arch.mm_perdomain_pt) + i)),
     4.8 +                mfn_x(page_to_mfn(perdomain_pt_page(d, i))),
     4.9                  __PAGE_HYPERVISOR);
    4.10  
    4.11      /* No linear mapping; will be set up by monitor-table contructor. */
     5.1 --- a/xen/arch/x86/mm/shadow/multi.c	Thu Jun 18 10:04:57 2009 +0100
     5.2 +++ b/xen/arch/x86/mm/shadow/multi.c	Thu Jun 18 10:05:23 2009 +0100
     5.3 @@ -1470,7 +1470,7 @@ static void sh_install_xen_entries_in_l2
     5.4      for ( i = 0; i < PDPT_L2_ENTRIES; i++ )
     5.5          sl2e[shadow_l2_table_offset(PERDOMAIN_VIRT_START) + i] =
     5.6              shadow_l2e_from_mfn(
     5.7 -                page_to_mfn(virt_to_page(d->arch.mm_perdomain_pt) + i),
     5.8 +                page_to_mfn(perdomain_pt_page(d, i)),
     5.9                  __PAGE_HYPERVISOR);
    5.10      
    5.11      /* We don't set up a linear mapping here because we can't until this
     6.1 --- a/xen/include/asm-x86/domain.h	Thu Jun 18 10:04:57 2009 +0100
     6.2 +++ b/xen/include/asm-x86/domain.h	Thu Jun 18 10:05:23 2009 +0100
     6.3 @@ -231,10 +231,12 @@ struct domain_mca_msrs
     6.4  
     6.5  struct arch_domain
     6.6  {
     6.7 -    l1_pgentry_t *mm_perdomain_pt;
     6.8  #ifdef CONFIG_X86_64
     6.9 +    struct page_info **mm_perdomain_pt_pages;
    6.10      l2_pgentry_t *mm_perdomain_l2;
    6.11      l3_pgentry_t *mm_perdomain_l3;
    6.12 +#else
    6.13 +    l1_pgentry_t *mm_perdomain_pt;
    6.14  #endif
    6.15  
    6.16  #ifdef CONFIG_X86_32
    6.17 @@ -302,6 +304,21 @@ struct arch_domain
    6.18  
    6.19  #define has_arch_pdevs(d)    (!list_empty(&(d)->arch.pdev_list))
    6.20  
    6.21 +#ifdef CONFIG_X86_64
    6.22 +#define perdomain_pt_pgidx(v) \
    6.23 +      ((v)->vcpu_id >> (PAGETABLE_ORDER - GDT_LDT_VCPU_SHIFT))
    6.24 +#define perdomain_ptes(d, v) \
    6.25 +    ((l1_pgentry_t *)page_to_virt((d)->arch.mm_perdomain_pt_pages \
    6.26 +      [perdomain_pt_pgidx(v)]) + (((v)->vcpu_id << GDT_LDT_VCPU_SHIFT) & \
    6.27 +                                  (L1_PAGETABLE_ENTRIES - 1)))
    6.28 +#define perdomain_pt_page(d, n) ((d)->arch.mm_perdomain_pt_pages[n])
    6.29 +#else
    6.30 +#define perdomain_ptes(d, v) \
    6.31 +    ((d)->arch.mm_perdomain_pt + ((v)->vcpu_id << GDT_LDT_VCPU_SHIFT))
    6.32 +#define perdomain_pt_page(d, n) \
    6.33 +    (virt_to_page((d)->arch.mm_perdomain_pt) + (n))
    6.34 +#endif
    6.35 +
    6.36  
    6.37  #ifdef __i386__
    6.38  struct pae_l3_cache {