ia64/xen-unstable

changeset 13896:d39e8c44da34

[HVM] Save/restore: disentangle max_pfn from nr_pages.
These have been used interchangeably, which is OK for PV domains but
not for HVM. This fixes an over-allocation by 256MB when restoring
HVM guests that have more than 4GB of RAM.
Signed-off-by: Tim Deegan <Tim.Deegan@xensource.com>
author Tim Deegan <Tim.Deegan@xensource.com>
date Fri Feb 09 10:48:41 2007 +0000 (2007-02-09)
parents dda3e75f015d
children c67a4115a471
files tools/libxc/xc_hvm_restore.c tools/libxc/xenguest.h tools/libxc/xg_private.c tools/xcutils/xc_restore.c
line diff
     1.1 --- a/tools/libxc/xc_hvm_restore.c	Fri Feb 09 10:21:12 2007 +0000
     1.2 +++ b/tools/libxc/xc_hvm_restore.c	Fri Feb 09 10:48:41 2007 +0000
     1.3 @@ -41,11 +41,8 @@ static unsigned long hvirt_start;
     1.4  /* #levels of page tables used by the currrent guest */
     1.5  static unsigned int pt_levels;
     1.6  
     1.7 -/* total number of pages used by the current guest */
     1.8 -static unsigned long max_pfn;
     1.9 -
    1.10 -/* A table mapping each PFN to its new MFN. */
    1.11 -static xen_pfn_t *p2m = NULL;
    1.12 +/* A list of PFNs that exist, used when allocating memory to the guest */
    1.13 +static xen_pfn_t *pfns = NULL;
    1.14  
    1.15  static ssize_t
    1.16  read_exact(int fd, void *buf, size_t count)
    1.17 @@ -67,7 +64,7 @@ read_exact(int fd, void *buf, size_t cou
    1.18  }
    1.19  
    1.20  int xc_hvm_restore(int xc_handle, int io_fd,
    1.21 -                     uint32_t dom, unsigned long nr_pfns,
    1.22 +                     uint32_t dom, unsigned long max_pfn,
    1.23                       unsigned int store_evtchn, unsigned long *store_mfn,
    1.24                       unsigned int pae, unsigned int apic)
    1.25  {
    1.26 @@ -90,7 +87,7 @@ int xc_hvm_restore(int xc_handle, int io
    1.27      unsigned long long v_end, memsize;
    1.28      unsigned long shared_page_nr;
    1.29  
    1.30 -    unsigned long mfn, pfn;
    1.31 +    unsigned long pfn;
    1.32      unsigned int prev_pc, this_pc;
    1.33      int verify = 0;
    1.34  
    1.35 @@ -99,22 +96,26 @@ int xc_hvm_restore(int xc_handle, int io
    1.36  
    1.37      struct xen_add_to_physmap xatp;
    1.38  
    1.39 +    /* Number of pages of memory the guest has.  *Not* the same as max_pfn. */
    1.40 +    unsigned long nr_pages;
    1.41 +
    1.42      /* hvm guest mem size (Mb) */
    1.43      memsize = (unsigned long long)*store_mfn;
    1.44      v_end = memsize << 20;
    1.45 +    nr_pages = (unsigned long) memsize << (20 - PAGE_SHIFT);
    1.46  
    1.47 -    DPRINTF("xc_hvm_restore:dom=%d, nr_pfns=0x%lx, store_evtchn=%d, *store_mfn=%ld, pae=%u, apic=%u.\n", 
    1.48 -            dom, nr_pfns, store_evtchn, *store_mfn, pae, apic);
    1.49 +    DPRINTF("xc_hvm_restore:dom=%d, nr_pages=0x%lx, store_evtchn=%d, *store_mfn=%ld, pae=%u, apic=%u.\n", 
    1.50 +            dom, nr_pages, store_evtchn, *store_mfn, pae, apic);
    1.51  
    1.52 -    max_pfn = nr_pfns;
    1.53 -
    1.54 +    
    1.55      if(!get_platform_info(xc_handle, dom,
    1.56                            &max_mfn, &hvirt_start, &pt_levels)) {
    1.57          ERROR("Unable to get platform info.");
    1.58          return 1;
    1.59      }
    1.60  
    1.61 -    DPRINTF("xc_hvm_restore start: max_pfn = %lx, max_mfn = %lx, hvirt_start=%lx, pt_levels=%d\n",
    1.62 +    DPRINTF("xc_hvm_restore start: nr_pages = %lx, max_pfn = %lx, max_mfn = %lx, hvirt_start=%lx, pt_levels=%d\n",
    1.63 +            nr_pages,
    1.64              max_pfn,
    1.65              max_mfn,
    1.66              hvirt_start,
    1.67 @@ -127,30 +128,30 @@ int xc_hvm_restore(int xc_handle, int io
    1.68      }
    1.69  
    1.70  
    1.71 -    p2m = malloc(max_pfn * sizeof(xen_pfn_t));
    1.72 -    if (p2m == NULL) {
    1.73 +    pfns = malloc(max_pfn * sizeof(xen_pfn_t));
    1.74 +    if (pfns == NULL) {
    1.75          ERROR("memory alloc failed");
    1.76          errno = ENOMEM;
    1.77          goto out;
    1.78      }
    1.79  
    1.80 -    if(xc_domain_setmaxmem(xc_handle, dom, PFN_TO_KB(max_pfn)) != 0) {
    1.81 +    if(xc_domain_setmaxmem(xc_handle, dom, PFN_TO_KB(nr_pages)) != 0) {
    1.82          errno = ENOMEM;
    1.83          goto out;
    1.84      }
    1.85  
    1.86      for ( i = 0; i < max_pfn; i++ )
    1.87 -        p2m[i] = i;
    1.88 +        pfns[i] = i;
    1.89      for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < max_pfn; i++ )
    1.90 -        p2m[i] += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT;
    1.91 +        pfns[i] += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT;
    1.92  
    1.93      /* Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. */
    1.94      rc = xc_domain_memory_populate_physmap(
    1.95 -        xc_handle, dom, (max_pfn > 0xa0) ? 0xa0 : max_pfn,
    1.96 -        0, 0, &p2m[0x00]);
    1.97 -    if ( (rc == 0) && (max_pfn > 0xc0) )
    1.98 +        xc_handle, dom, (nr_pages > 0xa0) ? 0xa0 : nr_pages,
    1.99 +        0, 0, &pfns[0x00]);
   1.100 +    if ( (rc == 0) && (nr_pages > 0xc0) )
   1.101          rc = xc_domain_memory_populate_physmap(
   1.102 -            xc_handle, dom, max_pfn - 0xc0, 0, 0, &p2m[0xc0]);
   1.103 +            xc_handle, dom, nr_pages - 0xc0, 0, 0, &pfns[0xc0]);
   1.104      if ( rc != 0 )
   1.105      {
   1.106          PERROR("Could not allocate memory for HVM guest.\n");
   1.107 @@ -171,9 +172,6 @@ int xc_hvm_restore(int xc_handle, int io
   1.108          goto out;
   1.109      }
   1.110  
   1.111 -    for ( i = 0; i < max_pfn; i++)
   1.112 -        p2m[i] = i;
   1.113 -
   1.114      prev_pc = 0;
   1.115  
   1.116      n = 0;
   1.117 @@ -181,7 +179,7 @@ int xc_hvm_restore(int xc_handle, int io
   1.118  
   1.119          int j;
   1.120  
   1.121 -        this_pc = (n * 100) / max_pfn;
   1.122 +        this_pc = (n * 100) / nr_pages;
   1.123          if ( (this_pc - prev_pc) >= 5 )
   1.124          {
   1.125              PPRINTF("\b\b\b\b%3d%%", this_pc);
   1.126 @@ -234,8 +232,6 @@ int xc_hvm_restore(int xc_handle, int io
   1.127              }
   1.128  
   1.129  
   1.130 -            mfn = p2m[pfn];
   1.131 -
   1.132              /* In verify mode, we use a copy; otherwise we work in place */
   1.133              page = verify ? (void *)buf : (region_base + i*PAGE_SIZE);
   1.134  
   1.135 @@ -252,8 +248,8 @@ int xc_hvm_restore(int xc_handle, int io
   1.136  
   1.137                      int v;
   1.138  
   1.139 -                    DPRINTF("************** pfn=%lx mfn=%lx gotcs=%08lx "
   1.140 -                            "actualcs=%08lx\n", pfn, p2m[pfn],
   1.141 +                    DPRINTF("************** pfn=%lx gotcs=%08lx "
   1.142 +                            "actualcs=%08lx\n", pfn, 
   1.143                              csum_page(region_base + i*PAGE_SIZE),
   1.144                              csum_page(buf));
   1.145  
   1.146 @@ -361,7 +357,7 @@ int xc_hvm_restore(int xc_handle, int io
   1.147   out:
   1.148      if ( (rc != 0) && (dom != 0) )
   1.149          xc_domain_destroy(xc_handle, dom);
   1.150 -    free(p2m);
   1.151 +    free(pfns);
   1.152      free(hvm_buf);
   1.153  
   1.154      DPRINTF("Restore exit with rc=%d\n", rc);
     2.1 --- a/tools/libxc/xenguest.h	Fri Feb 09 10:21:12 2007 +0000
     2.2 +++ b/tools/libxc/xenguest.h	Fri Feb 09 10:48:41 2007 +0000
     2.3 @@ -57,7 +57,7 @@ int xc_linux_restore(int xc_handle, int 
     2.4   * @return 0 on success, -1 on failure
     2.5   */
     2.6  int xc_hvm_restore(int xc_handle, int io_fd, uint32_t dom,
     2.7 -                      unsigned long nr_pfns, unsigned int store_evtchn,
     2.8 +                      unsigned long max_pfn, unsigned int store_evtchn,
     2.9                        unsigned long *store_mfn, 
    2.10                        unsigned int pae, unsigned int apic);
    2.11  
     3.1 --- a/tools/libxc/xg_private.c	Fri Feb 09 10:21:12 2007 +0000
     3.2 +++ b/tools/libxc/xg_private.c	Fri Feb 09 10:48:41 2007 +0000
     3.3 @@ -209,7 +209,7 @@ int xc_hvm_save(int xc_handle, int io_fd
     3.4  
     3.5  __attribute__((weak)) 
     3.6  int xc_hvm_restore(int xc_handle, int io_fd, uint32_t dom,
     3.7 -                   unsigned long nr_pfns, unsigned int store_evtchn,
     3.8 +                   unsigned long max_pfn, unsigned int store_evtchn,
     3.9                     unsigned long *store_mfn,
    3.10                     unsigned int pae, unsigned int apic)
    3.11  {
     4.1 --- a/tools/xcutils/xc_restore.c	Fri Feb 09 10:21:12 2007 +0000
     4.2 +++ b/tools/xcutils/xc_restore.c	Fri Feb 09 10:48:41 2007 +0000
     4.3 @@ -18,14 +18,14 @@
     4.4  int
     4.5  main(int argc, char **argv)
     4.6  {
     4.7 -    unsigned int xc_fd, io_fd, domid, nr_pfns, store_evtchn, console_evtchn;
     4.8 +    unsigned int xc_fd, io_fd, domid, max_pfn, store_evtchn, console_evtchn;
     4.9      unsigned int hvm, pae, apic;
    4.10      int ret;
    4.11      unsigned long store_mfn, console_mfn;
    4.12  
    4.13      if (argc != 9)
    4.14  	errx(1,
    4.15 -	     "usage: %s iofd domid nr_pfns store_evtchn console_evtchn hvm pae apic",
    4.16 +	     "usage: %s iofd domid max_pfn store_evtchn console_evtchn hvm pae apic",
    4.17  	     argv[0]);
    4.18  
    4.19      xc_fd = xc_interface_open();
    4.20 @@ -34,7 +34,7 @@ main(int argc, char **argv)
    4.21  
    4.22      io_fd = atoi(argv[1]);
    4.23      domid = atoi(argv[2]);
    4.24 -    nr_pfns = atoi(argv[3]);
    4.25 +    max_pfn = atoi(argv[3]);
    4.26      store_evtchn = atoi(argv[4]);
    4.27      console_evtchn = atoi(argv[5]);
    4.28      hvm  = atoi(argv[6]);
    4.29 @@ -44,10 +44,10 @@ main(int argc, char **argv)
    4.30      if (hvm) {
    4.31           /* pass the memsize to xc_hvm_restore to find the store_mfn */
    4.32          store_mfn = hvm;
    4.33 -        ret = xc_hvm_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn,
    4.34 +        ret = xc_hvm_restore(xc_fd, io_fd, domid, max_pfn, store_evtchn,
    4.35                  &store_mfn, pae, apic);
    4.36      } else 
    4.37 -        ret = xc_linux_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn,
    4.38 +        ret = xc_linux_restore(xc_fd, io_fd, domid, max_pfn, store_evtchn,
    4.39                  &store_mfn, console_evtchn, &console_mfn);
    4.40  
    4.41      if (ret == 0) {