ia64/xen-unstable

changeset 14314:560183e6452a

[HVM] Save/restore: tidy PFN handling in the tools.
Make the differences clearer between the number of frames, the max PFN
and the size of the pfn array, and handle te framebuffer more cleanly.
Signed-off-by: Tim Deegan <Tim.Deegan@xensource.com>
author Tim Deegan <Tim.Deegan@xensource.com>
date Thu Mar 08 16:40:35 2007 +0000 (2007-03-08)
parents eedbddf55e51
children 68c917da8b9b
files tools/libxc/xc_hvm_restore.c tools/libxc/xc_hvm_save.c tools/libxc/xenguest.h tools/python/xen/xend/XendCheckpoint.py
line diff
     1.1 --- a/tools/libxc/xc_hvm_restore.c	Thu Mar 08 16:38:15 2007 +0000
     1.2 +++ b/tools/libxc/xc_hvm_restore.c	Thu Mar 08 16:40:35 2007 +0000
     1.3 @@ -101,6 +101,9 @@ int xc_hvm_restore(int xc_handle, int io
     1.4      /* Number of pages of memory the guest has.  *Not* the same as max_pfn. */
     1.5      unsigned long nr_pages;
     1.6  
     1.7 +    /* The size of an array big enough to contain all guest pfns */
     1.8 +    unsigned long pfn_array_size = max_pfn + 1;
     1.9 +
    1.10      /* hvm guest mem size (Mb) */
    1.11      memsize = (unsigned long long)*store_mfn;
    1.12      v_end = memsize << 20;
    1.13 @@ -127,7 +130,7 @@ int xc_hvm_restore(int xc_handle, int io
    1.14      }
    1.15  
    1.16  
    1.17 -    pfns = malloc(max_pfn * sizeof(xen_pfn_t));
    1.18 +    pfns = malloc(pfn_array_size * sizeof(xen_pfn_t));
    1.19      if (pfns == NULL) {
    1.20          ERROR("memory alloc failed");
    1.21          errno = ENOMEM;
    1.22 @@ -139,11 +142,11 @@ int xc_hvm_restore(int xc_handle, int io
    1.23          goto out;
    1.24      }
    1.25  
    1.26 -    for ( i = 0; i < max_pfn; i++ )
    1.27 +    for ( i = 0; i < pfn_array_size; i++ )
    1.28          pfns[i] = i;
    1.29 -    for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < max_pfn; i++ )
    1.30 +    for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < pfn_array_size; i++ )
    1.31          pfns[i] += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT;
    1.32 -    arch_max_pfn = pfns[max_pfn - 1];/* used later */
    1.33 +    arch_max_pfn = pfns[max_pfn];/* used later */
    1.34  
    1.35      /* Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. */
    1.36      rc = xc_domain_memory_populate_physmap(
    1.37 @@ -297,29 +300,6 @@ int xc_hvm_restore(int xc_handle, int io
    1.38      *store_mfn = (v_end >> PAGE_SHIFT) - 2;
    1.39      DPRINTF("hvm restore:calculate new store_mfn=0x%lx,v_end=0x%llx..\n", *store_mfn, v_end);
    1.40  
    1.41 -    /* restore hvm context including pic/pit/shpage */
    1.42 -    if (!read_exact(io_fd, &rec_len, sizeof(uint32_t))) {
    1.43 -        ERROR("error read hvm context size!\n");
    1.44 -        goto out;
    1.45 -    }
    1.46 -
    1.47 -    hvm_buf = malloc(rec_len);
    1.48 -    if (hvm_buf == NULL) {
    1.49 -        ERROR("memory alloc for hvm context buffer failed");
    1.50 -        errno = ENOMEM;
    1.51 -        goto out;
    1.52 -    }
    1.53 -
    1.54 -    if (!read_exact(io_fd, hvm_buf, rec_len)) {
    1.55 -        ERROR("error read hvm buffer!\n");
    1.56 -        goto out;
    1.57 -    }
    1.58 -
    1.59 -    if (( rc = xc_domain_hvm_setcontext(xc_handle, dom, hvm_buf, rec_len))) {
    1.60 -        ERROR("error set hvm buffer!\n");
    1.61 -        goto out;
    1.62 -    }
    1.63 -
    1.64      if (!read_exact(io_fd, &nr_vcpus, sizeof(uint32_t))) {
    1.65          ERROR("error read nr vcpu !\n");
    1.66          goto out;
    1.67 @@ -347,6 +327,29 @@ int xc_hvm_restore(int xc_handle, int io
    1.68          }
    1.69      }
    1.70  
    1.71 +    /* restore hvm context including pic/pit/shpage */
    1.72 +    if (!read_exact(io_fd, &rec_len, sizeof(uint32_t))) {
    1.73 +        ERROR("error read hvm context size!\n");
    1.74 +        goto out;
    1.75 +    }
    1.76 +
    1.77 +    hvm_buf = malloc(rec_len);
    1.78 +    if (hvm_buf == NULL) {
    1.79 +        ERROR("memory alloc for hvm context buffer failed");
    1.80 +        errno = ENOMEM;
    1.81 +        goto out;
    1.82 +    }
    1.83 +
    1.84 +    if (!read_exact(io_fd, hvm_buf, rec_len)) {
    1.85 +        ERROR("error read hvm buffer!\n");
    1.86 +        goto out;
    1.87 +    }
    1.88 +
    1.89 +    if (( rc = xc_domain_hvm_setcontext(xc_handle, dom, hvm_buf, rec_len))) {
    1.90 +        ERROR("error set hvm buffer!\n");
    1.91 +        goto out;
    1.92 +    }
    1.93 +
    1.94      /* Shared-info pfn */
    1.95      if (!read_exact(io_fd, &(shared_info_frame), sizeof(uint32_t)) ) {
    1.96          ERROR("reading the shared-info pfn failed!\n");
     2.1 --- a/tools/libxc/xc_hvm_save.c	Thu Mar 08 16:38:15 2007 +0000
     2.2 +++ b/tools/libxc/xc_hvm_save.c	Thu Mar 08 16:40:35 2007 +0000
     2.3 @@ -54,9 +54,6 @@ static unsigned long hvirt_start;
     2.4  /* #levels of page tables used by the current guest */
     2.5  static unsigned int pt_levels;
     2.6  
     2.7 -/* total number of pages used by the current guest */
     2.8 -static unsigned long max_pfn;
     2.9 -
    2.10  int xc_hvm_drain_io(int handle, domid_t dom)
    2.11  {
    2.12      DECLARE_HYPERCALL;
    2.13 @@ -80,7 +77,7 @@ int xc_hvm_drain_io(int handle, domid_t 
    2.14  */
    2.15  
    2.16  #define BITS_PER_LONG (sizeof(unsigned long) * 8)
    2.17 -#define BITMAP_SIZE   ((max_pfn + BITS_PER_LONG - 1) / 8)
    2.18 +#define BITMAP_SIZE   ((pfn_array_size + BITS_PER_LONG - 1) / 8)
    2.19  
    2.20  #define BITMAP_ENTRY(_nr,_bmap) \
    2.21     ((unsigned long *)(_bmap))[(_nr)/BITS_PER_LONG]
    2.22 @@ -202,7 +199,7 @@ static int print_stats(int xc_handle, ui
    2.23      return 0;
    2.24  }
    2.25  
    2.26 -static int analysis_phase(int xc_handle, uint32_t domid, int max_pfn,
    2.27 +static int analysis_phase(int xc_handle, uint32_t domid, int pfn_array_size,
    2.28                            unsigned long *arr, int runs)
    2.29  {
    2.30      long long start, now;
    2.31 @@ -215,7 +212,7 @@ static int analysis_phase(int xc_handle,
    2.32          int i;
    2.33  
    2.34          xc_shadow_control(xc_handle, domid, XEN_DOMCTL_SHADOW_OP_CLEAN,
    2.35 -                          arr, max_pfn, NULL, 0, NULL);
    2.36 +                          arr, pfn_array_size, NULL, 0, NULL);
    2.37          DPRINTF("#Flush\n");
    2.38          for ( i = 0; i < 40; i++ ) {
    2.39              usleep(50000);
    2.40 @@ -255,7 +252,7 @@ static int suspend_and_state(int (*suspe
    2.41  
    2.42  
    2.43      if (info->shutdown && info->shutdown_reason == SHUTDOWN_suspend)
    2.44 -        return 0; // success
    2.45 +        return 0; // success        
    2.46  
    2.47      if (info->paused) {
    2.48          // try unpausing domain, wait, and retest
    2.49 @@ -287,11 +284,21 @@ int xc_hvm_save(int xc_handle, int io_fd
    2.50      int rc = 1, i, j, last_iter, iter = 0;
    2.51      int live  = (flags & XCFLAGS_LIVE);
    2.52      int debug = (flags & XCFLAGS_DEBUG);
    2.53 +    int stdvga = (flags & XCFLAGS_STDVGA);
    2.54      int sent_last_iter, skip_this_iter;
    2.55  
    2.56 +    /* The highest guest-physical frame number used by the current guest */
    2.57 +    unsigned long max_pfn;
    2.58 +
    2.59 +    /* The size of an array big enough to contain all guest pfns */
    2.60 +    unsigned long pfn_array_size;
    2.61 +
    2.62      /* The new domain's shared-info frame number. */
    2.63      unsigned long shared_info_frame;
    2.64  
    2.65 +    /* Other magic frames: ioreqs and xenstore comms */
    2.66 +    unsigned long ioreq_pfn, bufioreq_pfn, store_pfn;
    2.67 +
    2.68      /* A copy of the CPU context of the guest. */
    2.69      vcpu_guest_context_t ctxt;
    2.70  
    2.71 @@ -310,7 +317,7 @@ int xc_hvm_save(int xc_handle, int io_fd
    2.72  
    2.73      uint32_t rec_size, nr_vcpus;
    2.74  
    2.75 -    /* power of 2 order of max_pfn */
    2.76 +    /* power of 2 order of pfn_array_size */
    2.77      int order_nr;
    2.78  
    2.79      /* bitmap of pages:
    2.80 @@ -372,6 +379,15 @@ int xc_hvm_save(int xc_handle, int io_fd
    2.81          goto out;
    2.82      }
    2.83  
    2.84 +    if ( xc_get_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, &store_pfn)
    2.85 +         || xc_get_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, &ioreq_pfn)
    2.86 +         || xc_get_hvm_param(xc_handle, dom, 
    2.87 +                             HVM_PARAM_BUFIOREQ_PFN, &bufioreq_pfn) )
    2.88 +    {
    2.89 +        ERROR("HVM: Could not read magic PFN parameters");
    2.90 +        goto out;
    2.91 +    }
    2.92 +
    2.93      DPRINTF("saved hvm domain info:max_memkb=0x%lx, max_mfn=0x%lx, "
    2.94              "nr_pages=0x%lx\n", info.max_memkb, max_mfn, info.nr_pages); 
    2.95  
    2.96 @@ -387,6 +403,7 @@ int xc_hvm_save(int xc_handle, int io_fd
    2.97          }
    2.98  
    2.99          last_iter = 0;
   2.100 +
   2.101          DPRINTF("hvm domain live migration debug start: logdirty enable.\n");
   2.102      } else {
   2.103          /* This is a non-live suspend. Issue the call back to get the
   2.104 @@ -407,20 +424,28 @@ int xc_hvm_save(int xc_handle, int io_fd
   2.105  
   2.106      /* Calculate the highest PFN of "normal" memory:
   2.107       * HVM memory is sequential except for the VGA and MMIO holes. */
   2.108 -    max_pfn = info.nr_pages;
   2.109 +    max_pfn = info.nr_pages - 1;
   2.110 +    /* If the domain has a Cirrus framebuffer and we haven't already 
   2.111 +     * suspended qemu-dm, it will have 8MB of framebuffer memory 
   2.112 +     * still allocated, which we don't want to copy: qemu will save it 
   2.113 +     * for us later */
   2.114 +    if ( live && !stdvga )
   2.115 +        max_pfn -= 0x800;
   2.116      /* Skip the VGA hole from 0xa0000 to 0xc0000 */
   2.117 -    max_pfn += 0x20;   
   2.118 +    max_pfn += 0x20;
   2.119      /* Skip the MMIO hole: 256MB just below 4GB */
   2.120      if ( max_pfn >= (HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT) )
   2.121          max_pfn += (HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT); 
   2.122  
   2.123 -    skip_this_iter = 0;/*XXX*/
   2.124 -    /* pretend we sent all the pages last iteration */
   2.125 -    sent_last_iter = max_pfn;
   2.126 +    /* Size of any array that covers 0 ... max_pfn */
   2.127 +    pfn_array_size = max_pfn + 1;
   2.128  
   2.129 -    /* calculate the power of 2 order of max_pfn, e.g.
   2.130 +    /* pretend we sent all the pages last iteration */
   2.131 +    sent_last_iter = pfn_array_size;
   2.132 +
   2.133 +    /* calculate the power of 2 order of pfn_array_size, e.g.
   2.134         15->4 16->4 17->5 */
   2.135 -    for (i = max_pfn-1, order_nr = 0; i ; i >>= 1, order_nr++)
   2.136 +    for (i = pfn_array_size-1, order_nr = 0; i ; i >>= 1, order_nr++)
   2.137          continue;
   2.138  
   2.139      /* Setup to_send / to_fix and to_skip bitmaps */
   2.140 @@ -454,7 +479,7 @@ int xc_hvm_save(int xc_handle, int io_fd
   2.141          return 1;
   2.142      }
   2.143  
   2.144 -    analysis_phase(xc_handle, dom, max_pfn, to_skip, 0);
   2.145 +    analysis_phase(xc_handle, dom, pfn_array_size, to_skip, 0);
   2.146  
   2.147  
   2.148      /* We want zeroed memory so use calloc rather than malloc. */
   2.149 @@ -484,9 +509,17 @@ int xc_hvm_save(int xc_handle, int io_fd
   2.150  
   2.151          DPRINTF("Saving HVM domain memory pages: iter %d   0%%", iter);
   2.152  
   2.153 -        while( N < max_pfn ){
   2.154 +        if (last_iter && (max_pfn != live_shinfo->arch.max_pfn)) {
   2.155 +            DPRINTF("calculated max_pfn as %#lx, shinfo says %#lx\n",
   2.156 +                    max_pfn, live_shinfo->arch.max_pfn);
   2.157 +            ERROR("Max pfn doesn't match shared info");
   2.158 +            goto out;
   2.159 +        }
   2.160  
   2.161 -            unsigned int this_pc = (N * 100) / max_pfn;
   2.162 +        while( N < pfn_array_size ){
   2.163 +
   2.164 +            unsigned int this_pc = (N * 100) / pfn_array_size;
   2.165 +            int rc;
   2.166  
   2.167              if ((this_pc - prev_pc) >= 5) {
   2.168                  DPRINTF("\b\b\b\b%3d%%", this_pc);
   2.169 @@ -495,9 +528,9 @@ int xc_hvm_save(int xc_handle, int io_fd
   2.170  
   2.171              /* slightly wasteful to peek the whole array evey time,
   2.172                 but this is fast enough for the moment. */
   2.173 -            if (!last_iter && xc_shadow_control(
   2.174 -                    xc_handle, dom, XEN_DOMCTL_SHADOW_OP_PEEK,
   2.175 -                    to_skip, max_pfn, NULL, 0, NULL) != max_pfn) {
   2.176 +            if (!last_iter && (rc = xc_shadow_control(
   2.177 +                    xc_handle, dom, XEN_DOMCTL_SHADOW_OP_PEEK, to_skip, 
   2.178 +                    pfn_array_size, NULL, 0, NULL)) != pfn_array_size) {
   2.179                  ERROR("Error peeking HVM shadow bitmap");
   2.180                  goto out;
   2.181              }
   2.182 @@ -505,11 +538,11 @@ int xc_hvm_save(int xc_handle, int io_fd
   2.183  
   2.184              /* load pfn_batch[] with the mfn of all the pages we're doing in
   2.185                 this batch. */
   2.186 -            for (batch = 0; batch < MAX_BATCH_SIZE && N < max_pfn ; N++) {
   2.187 +            for (batch = 0; batch < MAX_BATCH_SIZE && N < pfn_array_size; N++){
   2.188  
   2.189 -                int n = permute(N, max_pfn, order_nr);
   2.190 +                int n = permute(N, pfn_array_size, order_nr);
   2.191  
   2.192 -                if (debug) {
   2.193 +                if (0&&debug) {
   2.194                      DPRINTF("%d pfn= %08lx %d \n",
   2.195                              iter, (unsigned long)n, test_bit(n, to_send));
   2.196                  }
   2.197 @@ -524,7 +557,10 @@ int xc_hvm_save(int xc_handle, int io_fd
   2.198                  /* Skip PFNs that aren't really there */
   2.199                  if ((n >= 0xa0 && n < 0xc0) /* VGA hole */
   2.200                      || (n >= (HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT)
   2.201 -                        && n < (1ULL << 32) >> PAGE_SHIFT)) /* 4G MMIO hole */
   2.202 +                        && n < (1ULL << 32) >> PAGE_SHIFT) /* 4G MMIO hole */
   2.203 +                    || n == store_pfn
   2.204 +                    || n == ioreq_pfn
   2.205 +                    || n == bufioreq_pfn)
   2.206                      continue;
   2.207  
   2.208                  /*
   2.209 @@ -589,7 +625,7 @@ int xc_hvm_save(int xc_handle, int io_fd
   2.210              print_stats( xc_handle, dom, sent_this_iter, &stats, 1);
   2.211  
   2.212              DPRINTF("Total pages sent= %ld (%.2fx)\n",
   2.213 -                    total_sent, ((float)total_sent)/max_pfn );
   2.214 +                    total_sent, ((float)total_sent)/pfn_array_size );
   2.215          }
   2.216  
   2.217          if (last_iter && debug){
   2.218 @@ -616,7 +652,7 @@ int xc_hvm_save(int xc_handle, int io_fd
   2.219                  ((sent_this_iter > sent_last_iter) && RATE_IS_MAX()) ||
   2.220                  (iter >= max_iters) ||
   2.221                  (sent_this_iter+skip_this_iter < 50) ||
   2.222 -                (total_sent > max_pfn*max_factor) ) {
   2.223 +                (total_sent > pfn_array_size*max_factor) ) {
   2.224  
   2.225                  DPRINTF("Start last iteration for HVM domain\n");
   2.226                  last_iter = 1;
   2.227 @@ -635,7 +671,8 @@ int xc_hvm_save(int xc_handle, int io_fd
   2.228  
   2.229              if (xc_shadow_control(xc_handle, dom, 
   2.230                                    XEN_DOMCTL_SHADOW_OP_CLEAN, to_send, 
   2.231 -                                  max_pfn, NULL, 0, &stats) != max_pfn) {
   2.232 +                                  pfn_array_size, NULL, 
   2.233 +                                  0, &stats) != pfn_array_size) {
   2.234                  ERROR("Error flushing shadow PT");
   2.235                  goto out;
   2.236              }
   2.237 @@ -659,20 +696,6 @@ int xc_hvm_save(int xc_handle, int io_fd
   2.238          goto out;
   2.239      }
   2.240  
   2.241 -    if ( (rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf, 
   2.242 -                                              hvm_buf_size)) == -1) {
   2.243 -        ERROR("HVM:Could not get hvm buffer");
   2.244 -        goto out;
   2.245 -    }
   2.246 -
   2.247 -    if (!write_exact(io_fd, &rec_size, sizeof(uint32_t))) {
   2.248 -        ERROR("error write hvm buffer size");
   2.249 -        goto out;
   2.250 -    }
   2.251 -
   2.252 -    if ( !write_exact(io_fd, hvm_buf, rec_size) ) {
   2.253 -        ERROR("write HVM info failed!\n");
   2.254 -    }
   2.255  
   2.256      /* save vcpu/vmcs context */
   2.257      if (!write_exact(io_fd, &nr_vcpus, sizeof(uint32_t))) {
   2.258 @@ -701,6 +724,21 @@ int xc_hvm_save(int xc_handle, int io_fd
   2.259          }
   2.260      }
   2.261  
   2.262 +    if ( (rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf, 
   2.263 +                                              hvm_buf_size)) == -1) {
   2.264 +        ERROR("HVM:Could not get hvm buffer");
   2.265 +        goto out;
   2.266 +    }
   2.267 +
   2.268 +    if (!write_exact(io_fd, &rec_size, sizeof(uint32_t))) {
   2.269 +        ERROR("error write hvm buffer size");
   2.270 +        goto out;
   2.271 +    }
   2.272 +
   2.273 +    if ( !write_exact(io_fd, hvm_buf, rec_size) ) {
   2.274 +        ERROR("write HVM info failed!\n");
   2.275 +    }
   2.276 +
   2.277      /* Shared-info pfn */
   2.278      if (!write_exact(io_fd, &(shared_info_frame), sizeof(uint32_t)) ) {
   2.279          ERROR("write shared-info pfn failed!\n");
     3.1 --- a/tools/libxc/xenguest.h	Thu Mar 08 16:38:15 2007 +0000
     3.2 +++ b/tools/libxc/xenguest.h	Thu Mar 08 16:40:35 2007 +0000
     3.3 @@ -12,6 +12,7 @@
     3.4  #define XCFLAGS_LIVE      1
     3.5  #define XCFLAGS_DEBUG     2
     3.6  #define XCFLAGS_HVM       4
     3.7 +#define XCFLAGS_STDVGA    8
     3.8  
     3.9  
    3.10  /**
     4.1 --- a/tools/python/xen/xend/XendCheckpoint.py	Thu Mar 08 16:38:15 2007 +0000
     4.2 +++ b/tools/python/xen/xend/XendCheckpoint.py	Thu Mar 08 16:40:35 2007 +0000
     4.3 @@ -74,9 +74,13 @@ def save(fd, dominfo, network, live, dst
     4.4  
     4.5          image_cfg = dominfo.info.get('image', {})
     4.6          hvm = image_cfg.has_key('hvm')
     4.7 +        stdvga = 0
     4.8  
     4.9          if hvm:
    4.10              log.info("save hvm domain")
    4.11 +            if image_cfg['hvm']['devices']['stdvga'] == 1:
    4.12 +                stdvga = 1
    4.13 +
    4.14          # xc_save takes three customization parameters: maxit, max_f, and
    4.15          # flags the last controls whether or not save is 'live', while the
    4.16          # first two further customize behaviour when 'live' save is
    4.17 @@ -84,7 +88,8 @@ def save(fd, dominfo, network, live, dst
    4.18          # libxenguest; see the comments and/or code in xc_linux_save() for
    4.19          # more information.
    4.20          cmd = [xen.util.auxbin.pathTo(XC_SAVE), str(fd),
    4.21 -               str(dominfo.getDomid()), "0", "0", str(int(live) | (int(hvm) << 2)) ]
    4.22 +               str(dominfo.getDomid()), "0", "0", 
    4.23 +               str(int(live) | (int(hvm) << 2) | (int(stdvga) << 3)) ]
    4.24          log.debug("[xc_save]: %s", string.join(cmd))
    4.25  
    4.26          def saveInputHandler(line, tochild):