debuggers.hg

changeset 21146:6868816898bd

1GB Page Table Support for HVM Guest 1/3

This patch changes Xen tools to allocate 1GB first. If such requests
fail, it will fall back to 2MB and then 4KB. We skip 1GB allocation
for the MMIO space between 3GB and 4GB.

Signed-off-by: Wei Huang <wei.huang2@amd.com>
Signed-off-by: Dongxiao Xu <dongxiao.xu@intel.com>
Acked-by: Tim Deegan <tim.deegan@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Apr 06 07:02:17 2010 +0100 (2010-04-06)
parents a3f52abcd7da
children 1ea7b73b3061
files tools/libxc/xc_hvm_build.c
line diff
     1.1 --- a/tools/libxc/xc_hvm_build.c	Tue Apr 06 06:59:32 2010 +0100
     1.2 +++ b/tools/libxc/xc_hvm_build.c	Tue Apr 06 07:02:17 2010 +0100
     1.3 @@ -19,8 +19,10 @@
     1.4  
     1.5  #include <xen/libelf/libelf.h>
     1.6  
     1.7 -#define SUPERPAGE_PFN_SHIFT  9
     1.8 -#define SUPERPAGE_NR_PFNS    (1UL << SUPERPAGE_PFN_SHIFT)
     1.9 +#define SUPERPAGE_2MB_SHIFT   9
    1.10 +#define SUPERPAGE_2MB_NR_PFNS (1UL << SUPERPAGE_2MB_SHIFT)
    1.11 +#define SUPERPAGE_1GB_SHIFT   18
    1.12 +#define SUPERPAGE_1GB_NR_PFNS (1UL << SUPERPAGE_1GB_SHIFT)
    1.13  
    1.14  #define SPECIALPAGE_BUFIOREQ 0
    1.15  #define SPECIALPAGE_XENSTORE 1
    1.16 @@ -100,6 +102,19 @@ static int loadelfimage(
    1.17      return rc;
    1.18  }
    1.19  
    1.20 +/*
    1.21 + * Check whether there exists mmio hole in the specified memory range.
    1.22 + * Returns 1 if exists, else returns 0.
    1.23 + */
    1.24 +static int check_mmio_hole(uint64_t start, uint64_t memsize)
    1.25 +{
    1.26 +    if ( start + memsize <= HVM_BELOW_4G_MMIO_START ||
    1.27 +         start >= HVM_BELOW_4G_MMIO_START + HVM_BELOW_4G_MMIO_LENGTH )
    1.28 +        return 0;
    1.29 +    else
    1.30 +        return 1;
    1.31 +}
    1.32 +
    1.33  static int setup_guest(int xc_handle,
    1.34                         uint32_t dom, int memsize, int target,
    1.35                         char *image, unsigned long image_size)
    1.36 @@ -117,8 +132,9 @@ static int setup_guest(int xc_handle,
    1.37      uint64_t v_start, v_end;
    1.38      int rc;
    1.39      xen_capabilities_info_t caps;
    1.40 +    unsigned long stat_normal_pages = 0, stat_2mb_pages = 0, 
    1.41 +        stat_1gb_pages = 0;
    1.42      int pod_mode = 0;
    1.43 -    
    1.44  
    1.45      /* An HVM guest must be initialised with at least 2MB memory. */
    1.46      if ( memsize < 2 || target < 2 )
    1.47 @@ -166,35 +182,40 @@ static int setup_guest(int xc_handle,
    1.48  
    1.49      /*
    1.50       * Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000.
    1.51 -     * We allocate pages in batches of no more than 8MB to ensure that
    1.52 -     * we can be preempted and hence dom0 remains responsive.
    1.53 +     *
    1.54 +     * We attempt to allocate 1GB pages if possible. It falls back on 2MB
    1.55 +     * pages if 1GB allocation fails. 4KB pages will be used eventually if
    1.56 +     * both fail.
    1.57 +     * 
    1.58 +     * Under 2MB mode, we allocate pages in batches of no more than 8MB to 
    1.59 +     * ensure that we can be preempted and hence dom0 remains responsive.
    1.60       */
    1.61      rc = xc_domain_memory_populate_physmap(
    1.62          xc_handle, dom, 0xa0, 0, 0, &page_array[0x00]);
    1.63      cur_pages = 0xc0;
    1.64 +    stat_normal_pages = 0xc0;
    1.65      while ( (rc == 0) && (nr_pages > cur_pages) )
    1.66      {
    1.67 -        /* Clip count to maximum 8MB extent. */
    1.68 +        /* Clip count to maximum 1GB extent. */
    1.69          unsigned long count = nr_pages - cur_pages;
    1.70 -        if ( count > 2048 )
    1.71 -            count = 2048;
    1.72 +        unsigned long max_pages = SUPERPAGE_1GB_NR_PFNS;
    1.73  
    1.74 -        /* Clip partial superpage extents to superpage boundaries. */
    1.75 -        if ( ((cur_pages & (SUPERPAGE_NR_PFNS-1)) != 0) &&
    1.76 -             (count > (-cur_pages & (SUPERPAGE_NR_PFNS-1))) )
    1.77 -            count = -cur_pages & (SUPERPAGE_NR_PFNS-1); /* clip s.p. tail */
    1.78 -        else if ( ((count & (SUPERPAGE_NR_PFNS-1)) != 0) &&
    1.79 -                  (count > SUPERPAGE_NR_PFNS) )
    1.80 -            count &= ~(SUPERPAGE_NR_PFNS - 1); /* clip non-s.p. tail */
    1.81 -
    1.82 -        /* Attempt to allocate superpage extents. */
    1.83 -        if ( ((count | cur_pages) & (SUPERPAGE_NR_PFNS - 1)) == 0 )
    1.84 +        if ( count > max_pages )
    1.85 +            count = max_pages;
    1.86 +        
    1.87 +        /* Attemp to allocate 1GB super page. Because in each pass we only
    1.88 +         * allocate at most 1GB, we don't have to clip super page boundaries.
    1.89 +         */
    1.90 +        if ( ((count | cur_pages) & (SUPERPAGE_1GB_NR_PFNS - 1)) == 0 &&
    1.91 +             /* Check if there exists MMIO hole in the 1GB memory range */
    1.92 +             !check_mmio_hole(cur_pages << PAGE_SHIFT,
    1.93 +                              SUPERPAGE_1GB_NR_PFNS << PAGE_SHIFT) )
    1.94          {
    1.95              long done;
    1.96 -            xen_pfn_t sp_extents[count >> SUPERPAGE_PFN_SHIFT];
    1.97 +            xen_pfn_t sp_extents[count >> SUPERPAGE_1GB_SHIFT];
    1.98              struct xen_memory_reservation sp_req = {
    1.99 -                .nr_extents   = count >> SUPERPAGE_PFN_SHIFT,
   1.100 -                .extent_order = SUPERPAGE_PFN_SHIFT,
   1.101 +                .nr_extents   = count >> SUPERPAGE_1GB_SHIFT,
   1.102 +                .extent_order = SUPERPAGE_1GB_SHIFT,
   1.103                  .domid        = dom
   1.104              };
   1.105  
   1.106 @@ -203,11 +224,12 @@ static int setup_guest(int xc_handle,
   1.107  
   1.108              set_xen_guest_handle(sp_req.extent_start, sp_extents);
   1.109              for ( i = 0; i < sp_req.nr_extents; i++ )
   1.110 -                sp_extents[i] = page_array[cur_pages+(i<<SUPERPAGE_PFN_SHIFT)];
   1.111 +                sp_extents[i] = page_array[cur_pages+(i<<SUPERPAGE_1GB_SHIFT)];
   1.112              done = xc_memory_op(xc_handle, XENMEM_populate_physmap, &sp_req);
   1.113              if ( done > 0 )
   1.114              {
   1.115 -                done <<= SUPERPAGE_PFN_SHIFT;
   1.116 +                stat_1gb_pages += done;
   1.117 +                done <<= SUPERPAGE_1GB_SHIFT;
   1.118                  if ( pod_mode && target_pages > cur_pages )
   1.119                  {
   1.120                      int d = target_pages - cur_pages;
   1.121 @@ -218,12 +240,61 @@ static int setup_guest(int xc_handle,
   1.122              }
   1.123          }
   1.124  
   1.125 +        if ( count != 0 )
   1.126 +        {
   1.127 +            /* Clip count to maximum 8MB extent. */
   1.128 +            max_pages = SUPERPAGE_2MB_NR_PFNS * 4;
   1.129 +            if ( count > max_pages )
   1.130 +                count = max_pages;
   1.131 +            
   1.132 +            /* Clip partial superpage extents to superpage boundaries. */
   1.133 +            if ( ((cur_pages & (SUPERPAGE_2MB_NR_PFNS-1)) != 0) &&
   1.134 +                 (count > (-cur_pages & (SUPERPAGE_2MB_NR_PFNS-1))) )
   1.135 +                count = -cur_pages & (SUPERPAGE_2MB_NR_PFNS-1);
   1.136 +            else if ( ((count & (SUPERPAGE_2MB_NR_PFNS-1)) != 0) &&
   1.137 +                      (count > SUPERPAGE_2MB_NR_PFNS) )
   1.138 +                count &= ~(SUPERPAGE_2MB_NR_PFNS - 1); /* clip non-s.p. tail */
   1.139 +
   1.140 +            /* Attempt to allocate superpage extents. */
   1.141 +            if ( ((count | cur_pages) & (SUPERPAGE_2MB_NR_PFNS - 1)) == 0 )
   1.142 +            {
   1.143 +                long done;
   1.144 +                xen_pfn_t sp_extents[count >> SUPERPAGE_2MB_SHIFT];
   1.145 +                struct xen_memory_reservation sp_req = {
   1.146 +                    .nr_extents   = count >> SUPERPAGE_2MB_SHIFT,
   1.147 +                    .extent_order = SUPERPAGE_2MB_SHIFT,
   1.148 +                    .domid        = dom
   1.149 +                };
   1.150 +
   1.151 +                if ( pod_mode )
   1.152 +                    sp_req.mem_flags = XENMEMF_populate_on_demand;
   1.153 +
   1.154 +                set_xen_guest_handle(sp_req.extent_start, sp_extents);
   1.155 +                for ( i = 0; i < sp_req.nr_extents; i++ )
   1.156 +                    sp_extents[i] = page_array[cur_pages+(i<<SUPERPAGE_2MB_SHIFT)];
   1.157 +                done = xc_memory_op(xc_handle, XENMEM_populate_physmap, &sp_req);
   1.158 +                if ( done > 0 )
   1.159 +                {
   1.160 +                    stat_2mb_pages += done;
   1.161 +                    done <<= SUPERPAGE_2MB_SHIFT;
   1.162 +                    if ( pod_mode && target_pages > cur_pages )
   1.163 +                    {
   1.164 +                        int d = target_pages - cur_pages;
   1.165 +                        pod_pages += ( done < d ) ? done : d;
   1.166 +                    }
   1.167 +                    cur_pages += done;
   1.168 +                    count -= done;
   1.169 +                }
   1.170 +            }
   1.171 +        }
   1.172 +
   1.173          /* Fall back to 4kB extents. */
   1.174          if ( count != 0 )
   1.175          {
   1.176              rc = xc_domain_memory_populate_physmap(
   1.177                  xc_handle, dom, count, 0, 0, &page_array[cur_pages]);
   1.178              cur_pages += count;
   1.179 +            stat_normal_pages += count;
   1.180              if ( pod_mode )
   1.181                  pod_pages -= count;
   1.182          }
   1.183 @@ -241,6 +312,12 @@ static int setup_guest(int xc_handle,
   1.184          goto error_out;
   1.185      }
   1.186  
   1.187 +    IPRINTF("PHYSICAL MEMORY ALLOCATION:\n"
   1.188 +            "  4KB PAGES: 0x%016lx\n"
   1.189 +            "  2MB PAGES: 0x%016lx\n"
   1.190 +            "  1GB PAGES: 0x%016lx\n",
   1.191 +            stat_normal_pages, stat_2mb_pages, stat_1gb_pages);
   1.192 +    
   1.193      if ( loadelfimage(&elf, xc_handle, dom, page_array) != 0 )
   1.194          goto error_out;
   1.195