ia64/xen-unstable

changeset 15846:e7c143aafbc1

[IA64] Foreign p2m: rewrite save/restore with foreign p2m

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Alex Williamson <alex.williamson@hp.com>
date Thu Sep 06 15:36:13 2007 -0600 (2007-09-06)
parents de247793f7b5
children 192f2df46e67
files tools/libxc/ia64/xc_ia64_linux_restore.c tools/libxc/ia64/xc_ia64_linux_save.c tools/libxc/ia64/xc_ia64_save_restore.h
line diff
     1.1 --- a/tools/libxc/ia64/xc_ia64_linux_restore.c	Thu Sep 06 15:32:54 2007 -0600
     1.2 +++ b/tools/libxc/ia64/xc_ia64_linux_restore.c	Thu Sep 06 15:36:13 2007 -0600
     1.3 @@ -5,12 +5,18 @@
     1.4   *
     1.5   * Copyright (c) 2003, K A Fraser.
     1.6   *  Rewritten for ia64 by Tristan Gingold <tristan.gingold@bull.net>
     1.7 + *
     1.8 + * Copyright (c) 2007 Isaku Yamahata <yamahata@valinux.co.jp>
     1.9 + *   Use foreign p2m exposure.
    1.10   */
    1.11  
    1.12  #include <stdlib.h>
    1.13  #include <unistd.h>
    1.14  
    1.15  #include "xg_private.h"
    1.16 +#include "xc_ia64_save_restore.h"
    1.17 +#include "xc_ia64.h"
    1.18 +#include "xc_efi.h"
    1.19  
    1.20  #define PFN_TO_KB(_pfn) ((_pfn) << (PAGE_SHIFT - 10))
    1.21  
    1.22 @@ -40,6 +46,16 @@ read_exact(int fd, void *buf, size_t cou
    1.23  }
    1.24  
    1.25  static int
    1.26 +populate_page_if_necessary(int xc_handle, uint32_t dom, unsigned long gmfn,
    1.27 +                           struct xen_ia64_p2m_table *p2m_table)
    1.28 +{
    1.29 +    if (xc_ia64_p2m_present(p2m_table, gmfn))
    1.30 +        return 0;
    1.31 +
    1.32 +    return xc_domain_memory_populate_physmap(xc_handle, dom, 1, 0, 0, &gmfn);
    1.33 +}
    1.34 +
    1.35 +static int
    1.36  read_page(int xc_handle, int io_fd, uint32_t dom, unsigned long pfn)
    1.37  {
    1.38      void *mem;
    1.39 @@ -66,7 +82,8 @@ xc_domain_restore(int xc_handle, int io_
    1.40                   unsigned int hvm, unsigned int pae)
    1.41  {
    1.42      DECLARE_DOMCTL;
    1.43 -    int rc = 1, i;
    1.44 +    int rc = 1;
    1.45 +    unsigned int i;
    1.46      unsigned long gmfn;
    1.47      unsigned long ver;
    1.48  
    1.49 @@ -78,11 +95,12 @@ xc_domain_restore(int xc_handle, int io_
    1.50      /* A copy of the CPU context of the guest. */
    1.51      vcpu_guest_context_t ctxt;
    1.52  
    1.53 -    unsigned long *page_array = NULL;
    1.54 -
    1.55      /* A temporary mapping of the guest's start_info page. */
    1.56      start_info_t *start_info;
    1.57  
    1.58 +    struct xen_ia64_p2m_table p2m_table;
    1.59 +    xc_ia64_p2m_init(&p2m_table);
    1.60 +
    1.61      if (hvm) {
    1.62          ERROR("HVM Restore is unsupported");
    1.63          goto out;
    1.64 @@ -102,7 +120,7 @@ xc_domain_restore(int xc_handle, int io_
    1.65          ERROR("Error when reading version");
    1.66          goto out;
    1.67      }
    1.68 -    if (ver != 1) {
    1.69 +    if (ver != XC_IA64_SR_FORMAT_VER_ONE && ver != XC_IA64_SR_FORMAT_VER_TWO) {
    1.70          ERROR("version of save doesn't match");
    1.71          goto out;
    1.72      }
    1.73 @@ -113,25 +131,6 @@ xc_domain_restore(int xc_handle, int io_
    1.74          return 1;
    1.75      }
    1.76  
    1.77 -    /* Get pages.  */
    1.78 -    page_array = malloc(p2m_size * sizeof(unsigned long));
    1.79 -    if (page_array == NULL) {
    1.80 -        ERROR("Could not allocate memory");
    1.81 -        goto out;
    1.82 -    }
    1.83 -
    1.84 -    for ( i = 0; i < p2m_size; i++ )
    1.85 -        page_array[i] = i;
    1.86 -
    1.87 -    if ( xc_domain_memory_populate_physmap(xc_handle, dom, p2m_size,
    1.88 -                                           0, 0, page_array) )
    1.89 -    {
    1.90 -        ERROR("Failed to allocate memory for %ld KB to dom %d.\n",
    1.91 -              PFN_TO_KB(p2m_size), dom);
    1.92 -        goto out;
    1.93 -    }
    1.94 -    DPRINTF("Allocated memory by %ld KB\n", PFN_TO_KB(p2m_size));
    1.95 -
    1.96      if (!read_exact(io_fd, &domctl.u.arch_setup, sizeof(domctl.u.arch_setup))) {
    1.97          ERROR("read: domain setup");
    1.98          goto out;
    1.99 @@ -155,6 +154,61 @@ xc_domain_restore(int xc_handle, int io_
   1.100      }
   1.101      shared_info_frame = domctl.u.getdomaininfo.shared_info_frame;
   1.102  
   1.103 +    if (ver == XC_IA64_SR_FORMAT_VER_TWO) {
   1.104 +        unsigned int memmap_info_num_pages;
   1.105 +        unsigned long memmap_size;
   1.106 +        xen_ia64_memmap_info_t *memmap_info;
   1.107 +
   1.108 +        if (!read_exact(io_fd, &memmap_info_num_pages,
   1.109 +                        sizeof(memmap_info_num_pages))) {
   1.110 +            ERROR("read: memmap_info_num_pages");
   1.111 +            goto out;
   1.112 +        }
   1.113 +        memmap_size = memmap_info_num_pages * PAGE_SIZE;
   1.114 +        memmap_info = malloc(memmap_size);
   1.115 +        if (memmap_info == NULL) {
   1.116 +            ERROR("Could not allocate memory for memmap_info");
   1.117 +            goto out;
   1.118 +        }
   1.119 +        if (!read_exact(io_fd, memmap_info, memmap_size)) {
   1.120 +            ERROR("read: memmap_info");
   1.121 +            goto out;
   1.122 +        }
   1.123 +        if (xc_ia64_p2m_map(&p2m_table, xc_handle,
   1.124 +                            dom, memmap_info, IA64_DOM0VP_EFP_ALLOC_PTE)) {
   1.125 +            ERROR("p2m mapping");
   1.126 +            goto out;
   1.127 +        }
   1.128 +        free(memmap_info);
   1.129 +    } else if (ver == XC_IA64_SR_FORMAT_VER_ONE) {
   1.130 +        xen_ia64_memmap_info_t *memmap_info;
   1.131 +        efi_memory_desc_t *memdesc;
   1.132 +        uint64_t buffer[(sizeof(*memmap_info) + sizeof(*memdesc) +
   1.133 +                         sizeof(uint64_t) - 1) / sizeof(uint64_t)];
   1.134 +
   1.135 +        memset(buffer, 0, sizeof(buffer));
   1.136 +        memmap_info = (xen_ia64_memmap_info_t *)buffer;
   1.137 +        memdesc = (efi_memory_desc_t*)&memmap_info->memdesc[0];
   1.138 +        memmap_info->efi_memmap_size = sizeof(*memmap_info) + sizeof(*memdesc);
   1.139 +        memmap_info->efi_memdesc_size = sizeof(*memdesc);
   1.140 +        memmap_info->efi_memdesc_version = EFI_MEMORY_DESCRIPTOR_VERSION;
   1.141 +
   1.142 +        memdesc->type = EFI_MEMORY_DESCRIPTOR_VERSION;
   1.143 +        memdesc->phys_addr = 0;
   1.144 +        memdesc->virt_addr = 0;
   1.145 +        memdesc->num_pages = nr_pfns << (PAGE_SHIFT - EFI_PAGE_SHIFT);
   1.146 +        memdesc->attribute = EFI_MEMORY_WB;
   1.147 +
   1.148 +        if (xc_ia64_p2m_map(&p2m_table, xc_handle,
   1.149 +                            dom, memmap_info, IA64_DOM0VP_EFP_ALLOC_PTE)) {
   1.150 +            ERROR("p2m mapping");
   1.151 +            goto out;
   1.152 +        }
   1.153 +    } else {
   1.154 +        ERROR("unknown version");
   1.155 +        goto out;
   1.156 +    }
   1.157 +
   1.158      DPRINTF("Reloading memory pages:   0%%\n");
   1.159  
   1.160      while (1) {
   1.161 @@ -165,17 +219,26 @@ xc_domain_restore(int xc_handle, int io_
   1.162          if (gmfn == INVALID_MFN)
   1.163              break;
   1.164  
   1.165 +        if (populate_page_if_necessary(xc_handle, dom, gmfn, &p2m_table) < 0) {
   1.166 +            ERROR("can not populate page 0x%lx", gmfn);
   1.167 +            goto out;
   1.168 +        }
   1.169          if (read_page(xc_handle, io_fd, dom, gmfn) < 0)
   1.170              goto out;
   1.171      }
   1.172  
   1.173      DPRINTF("Received all pages\n");
   1.174  
   1.175 -    /* Get the list of PFNs that are not in the psuedo-phys map */
   1.176 +    /*
   1.177 +     * Get the list of PFNs that are not in the psuedo-phys map.
   1.178 +     * Although we allocate pages on demand, balloon driver may 
   1.179 +     * decreased simaltenously. So we have to free the freed
   1.180 +     * pages here.
   1.181 +     */
   1.182      {
   1.183          unsigned int count;
   1.184          unsigned long *pfntab;
   1.185 -        int rc;
   1.186 +        unsigned int nr_frees;
   1.187  
   1.188          if (!read_exact(io_fd, &count, sizeof(count))) {
   1.189              ERROR("Error when reading pfn count");
   1.190 @@ -190,36 +253,31 @@ xc_domain_restore(int xc_handle, int io_
   1.191  
   1.192          if (!read_exact(io_fd, pfntab, sizeof(unsigned long)*count)) {
   1.193              ERROR("Error when reading pfntab");
   1.194 +            free(pfntab);
   1.195              goto out;
   1.196          }
   1.197  
   1.198 -        DPRINTF ("Try to free %u pages\n", count);
   1.199 -
   1.200 +        nr_frees = 0;
   1.201          for (i = 0; i < count; i++) {
   1.202 -
   1.203 -            volatile unsigned long pfn;
   1.204 -
   1.205 -            struct xen_memory_reservation reservation = {
   1.206 -                .nr_extents   = 1,
   1.207 -                .extent_order = 0,
   1.208 -                .domid        = dom
   1.209 -            };
   1.210 -            set_xen_guest_handle(reservation.extent_start,
   1.211 -                                 (unsigned long *)&pfn);
   1.212 -
   1.213 -            pfn = pfntab[i];
   1.214 -            rc = xc_memory_op(xc_handle, XENMEM_decrease_reservation,
   1.215 -                              &reservation);
   1.216 -            if (rc != 1) {
   1.217 +            if (xc_ia64_p2m_allocated(&p2m_table, pfntab[i])) {
   1.218 +                pfntab[nr_frees] = pfntab[i];
   1.219 +                nr_frees++;
   1.220 +            }
   1.221 +        }
   1.222 +        if (nr_frees > 0) {
   1.223 +            if (xc_domain_memory_decrease_reservation(xc_handle, dom, nr_frees,
   1.224 +                                                      0, pfntab) < 0) {
   1.225                  ERROR("Could not decrease reservation : %d", rc);
   1.226 +                free(pfntab);
   1.227                  goto out;
   1.228              }
   1.229 +            else
   1.230 +                DPRINTF("Decreased reservation by %d / %d pages\n",
   1.231 +                        nr_frees, count);
   1.232          }
   1.233 -
   1.234 -        DPRINTF("Decreased reservation by %d pages\n", count);
   1.235 +        free(pfntab);
   1.236      }
   1.237  
   1.238 -
   1.239      if (!read_exact(io_fd, &ctxt, sizeof(ctxt))) {
   1.240          ERROR("Error when reading ctxt");
   1.241          goto out;
   1.242 @@ -274,6 +332,10 @@ xc_domain_restore(int xc_handle, int io_
   1.243      munmap (shared_info, PAGE_SIZE);
   1.244  
   1.245      /* Uncanonicalise the suspend-record frame number and poke resume rec. */
   1.246 +    if (populate_page_if_necessary(xc_handle, dom, gmfn, &p2m_table)) {
   1.247 +        ERROR("cannot populate page 0x%lx", gmfn);
   1.248 +        goto out;
   1.249 +    }
   1.250      start_info = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
   1.251                                        PROT_READ | PROT_WRITE, gmfn);
   1.252      if (start_info == NULL) {
   1.253 @@ -309,8 +371,7 @@ xc_domain_restore(int xc_handle, int io_
   1.254      if ((rc != 0) && (dom != 0))
   1.255          xc_domain_destroy(xc_handle, dom);
   1.256  
   1.257 -    if (page_array != NULL)
   1.258 -        free(page_array);
   1.259 +    xc_ia64_p2m_unmap(&p2m_table);
   1.260  
   1.261      unlock_pages(&ctxt, sizeof(ctxt));
   1.262  
     2.1 --- a/tools/libxc/ia64/xc_ia64_linux_save.c	Thu Sep 06 15:32:54 2007 -0600
     2.2 +++ b/tools/libxc/ia64/xc_ia64_linux_save.c	Thu Sep 06 15:36:13 2007 -0600
     2.3 @@ -5,6 +5,9 @@
     2.4   *
     2.5   * Copyright (c) 2003, K A Fraser.
     2.6   *  Rewritten for ia64 by Tristan Gingold <tristan.gingold@bull.net>
     2.7 + *
     2.8 + * Copyright (c) 2007 Isaku Yamahata <yamahata@valinux.co.jp>
     2.9 + *   Use foreign p2m exposure.
    2.10   */
    2.11  
    2.12  #include <inttypes.h>
    2.13 @@ -14,6 +17,9 @@
    2.14  #include <sys/time.h>
    2.15  
    2.16  #include "xg_private.h"
    2.17 +#include "xc_ia64.h"
    2.18 +#include "xc_ia64_save_restore.h"
    2.19 +#include "xc_efi.h"
    2.20  
    2.21  /*
    2.22  ** Default values for important tuning parameters. Can override by passing
    2.23 @@ -151,8 +157,6 @@ xc_domain_save(int xc_handle, int io_fd,
    2.24      /* A copy of the CPU context of the guest. */
    2.25      vcpu_guest_context_t ctxt;
    2.26  
    2.27 -    unsigned long *page_array = NULL;
    2.28 -
    2.29      /* Live mapping of shared info structure */
    2.30      shared_info_t *live_shinfo = NULL;
    2.31  
    2.32 @@ -181,6 +185,17 @@ xc_domain_save(int xc_handle, int io_fd,
    2.33  
    2.34      char *mem;
    2.35  
    2.36 +    unsigned int memmap_info_num_pages;
    2.37 +    unsigned long memmap_size = 0;
    2.38 +    xen_ia64_memmap_info_t *memmap_info_live = NULL;
    2.39 +    xen_ia64_memmap_info_t *memmap_info = NULL;
    2.40 +    void *memmap_desc_start;
    2.41 +    void *memmap_desc_end;
    2.42 +    void *p;
    2.43 +    efi_memory_desc_t *md;
    2.44 +    struct xen_ia64_p2m_table p2m_table;
    2.45 +    xc_ia64_p2m_init(&p2m_table);
    2.46 +
    2.47      if (debug)
    2.48          fprintf(stderr, "xc_linux_save (ia64): started dom=%d\n", dom);
    2.49  
    2.50 @@ -218,12 +233,6 @@ xc_domain_save(int xc_handle, int io_fd,
    2.51  
    2.52      p2m_size = xc_memory_op(xc_handle, XENMEM_maximum_gpfn, &dom);
    2.53  
    2.54 -    page_array = malloc(p2m_size * sizeof(unsigned long));
    2.55 -    if (page_array == NULL) {
    2.56 -        ERROR("Could not allocate memory");
    2.57 -        goto out;
    2.58 -    }
    2.59 -
    2.60      /* This is expected by xm restore.  */
    2.61      if (!write_exact(io_fd, &p2m_size, sizeof(unsigned long))) {
    2.62          ERROR("write: p2m_size");
    2.63 @@ -236,7 +245,7 @@ xc_domain_save(int xc_handle, int io_fd,
    2.64         The version is hard-coded, don't forget to change the restore code
    2.65         too!  */
    2.66      {
    2.67 -        unsigned long version = 1;
    2.68 +        unsigned long version = XC_IA64_SR_FORMAT_VER_CURRENT;
    2.69  
    2.70          if (!write_exact(io_fd, &version, sizeof(unsigned long))) {
    2.71              ERROR("write: version");
    2.72 @@ -304,6 +313,38 @@ xc_domain_save(int xc_handle, int io_fd,
    2.73  
    2.74      }
    2.75  
    2.76 +    memmap_info_num_pages = live_shinfo->arch.memmap_info_num_pages;
    2.77 +    memmap_size = PAGE_SIZE * memmap_info_num_pages;
    2.78 +    memmap_info_live = xc_map_foreign_range(xc_handle, info.domid,
    2.79 +                                       memmap_size, PROT_READ,
    2.80 +                                            live_shinfo->arch.memmap_info_pfn);
    2.81 +    if (memmap_info_live == NULL) {
    2.82 +        PERROR("Could not map memmap info.");
    2.83 +        goto out;
    2.84 +    }
    2.85 +    memmap_info = malloc(memmap_size);
    2.86 +    if (memmap_info == NULL) {
    2.87 +        PERROR("Could not allocate memmap info memory");
    2.88 +        goto out;
    2.89 +    }
    2.90 +    memcpy(memmap_info, memmap_info_live, memmap_size);
    2.91 +    munmap(memmap_info_live, memmap_size);
    2.92 +    memmap_info_live = NULL;
    2.93 +    
    2.94 +    if (xc_ia64_p2m_map(&p2m_table, xc_handle, dom, memmap_info, 0) < 0) {
    2.95 +        PERROR("xc_ia64_p2m_map");
    2.96 +        goto out;
    2.97 +    }
    2.98 +    if (!write_exact(io_fd,
    2.99 +                     &memmap_info_num_pages, sizeof(memmap_info_num_pages))) {
   2.100 +        PERROR("write: arch.memmap_info_num_pages");
   2.101 +        goto out;
   2.102 +    }
   2.103 +    if (!write_exact(io_fd, memmap_info, memmap_size)) {
   2.104 +        PERROR("write: memmap_info");
   2.105 +        goto out;
   2.106 +    }
   2.107 +
   2.108      sent_last_iter = p2m_size;
   2.109      total_sent = 0;
   2.110  
   2.111 @@ -314,13 +355,6 @@ xc_domain_save(int xc_handle, int io_fd,
   2.112          sent_this_iter = 0;
   2.113          skip_this_iter = 0;
   2.114  
   2.115 -        /* Get the pfn list, as it may change.  */
   2.116 -        if (xc_ia64_get_pfn_list(xc_handle, dom, page_array,
   2.117 -                                 0, p2m_size) != p2m_size) {
   2.118 -            ERROR("Could not get the page frame list");
   2.119 -            goto out;
   2.120 -        }
   2.121 -
   2.122          /* Dirtied pages won't be saved.
   2.123             slightly wasteful to peek the whole array evey time,
   2.124             but this is fast enough for the moment. */
   2.125 @@ -334,45 +368,64 @@ xc_domain_save(int xc_handle, int io_fd,
   2.126          }
   2.127  
   2.128          /* Start writing out the saved-domain record. */
   2.129 -        for (N = 0; N < p2m_size; N++) {
   2.130 -            if (page_array[N] == INVALID_MFN)
   2.131 +        memmap_desc_start = &memmap_info->memdesc;
   2.132 +        memmap_desc_end = memmap_desc_start + memmap_info->efi_memmap_size;
   2.133 +        for (p = memmap_desc_start;
   2.134 +             p < memmap_desc_end;
   2.135 +             p += memmap_info->efi_memdesc_size) {
   2.136 +            md = p;
   2.137 +            if (md->type != EFI_CONVENTIONAL_MEMORY ||
   2.138 +                md->attribute != EFI_MEMORY_WB ||
   2.139 +                md->num_pages == 0)
   2.140                  continue;
   2.141 -            if (!last_iter) {
   2.142 -                if (test_bit(N, to_skip) && test_bit(N, to_send))
   2.143 -                    skip_this_iter++;
   2.144 -                if (test_bit(N, to_skip) || !test_bit(N, to_send))
   2.145 +            
   2.146 +            for (N = md->phys_addr >> PAGE_SHIFT;
   2.147 +                 N < (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >>
   2.148 +                     PAGE_SHIFT;
   2.149 +                 N++) {
   2.150 +
   2.151 +                if (!xc_ia64_p2m_allocated(&p2m_table, N))
   2.152                      continue;
   2.153 -            }
   2.154  
   2.155 -            if (debug)
   2.156 -                fprintf(stderr, "xc_linux_save: page %lx (%lu/%lu)\n",
   2.157 -                        page_array[N], N, p2m_size);
   2.158 +                if (!last_iter) {
   2.159 +                    if (test_bit(N, to_skip) && test_bit(N, to_send))
   2.160 +                        skip_this_iter++;
   2.161 +                    if (test_bit(N, to_skip) || !test_bit(N, to_send))
   2.162 +                        continue;
   2.163 +                }
   2.164  
   2.165 -            mem = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
   2.166 -                                       PROT_READ|PROT_WRITE, N);
   2.167 -            if (mem == NULL) {
   2.168 -                /* The page may have move.
   2.169 -                   It will be remarked dirty.
   2.170 -                   FIXME: to be tracked.  */
   2.171 -                fprintf(stderr, "cannot map mfn page %lx gpfn %lx: %s\n",
   2.172 -                        page_array[N], N, safe_strerror(errno));
   2.173 -                continue;
   2.174 -            }
   2.175 +                if (debug)
   2.176 +                    fprintf(stderr, "xc_linux_save: page %lx (%lu/%lu)\n",
   2.177 +                            xc_ia64_p2m_mfn(&p2m_table, N),
   2.178 +                            N, p2m_size);
   2.179  
   2.180 -            if (!write_exact(io_fd, &N, sizeof(N))) {
   2.181 -                ERROR("write: p2m_size");
   2.182 -                munmap(mem, PAGE_SIZE);
   2.183 -                goto out;
   2.184 -            }
   2.185 +                mem = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
   2.186 +                                           PROT_READ|PROT_WRITE, N);
   2.187 +                if (mem == NULL) {
   2.188 +                    /* The page may have move.
   2.189 +                       It will be remarked dirty.
   2.190 +                       FIXME: to be tracked.  */
   2.191 +                    fprintf(stderr, "cannot map mfn page %lx gpfn %lx: %s\n",
   2.192 +                            xc_ia64_p2m_mfn(&p2m_table, N),
   2.193 +                            N, safe_strerror(errno));
   2.194 +                    continue;
   2.195 +                }
   2.196  
   2.197 -            if (write(io_fd, mem, PAGE_SIZE) != PAGE_SIZE) {
   2.198 -                ERROR("Error when writing to state file (5)");
   2.199 +                if (!write_exact(io_fd, &N, sizeof(N))) {
   2.200 +                    ERROR("write: p2m_size");
   2.201 +                    munmap(mem, PAGE_SIZE);
   2.202 +                    goto out;
   2.203 +                }
   2.204 +
   2.205 +                if (write(io_fd, mem, PAGE_SIZE) != PAGE_SIZE) {
   2.206 +                    ERROR("Error when writing to state file (5)");
   2.207 +                    munmap(mem, PAGE_SIZE);
   2.208 +                    goto out;
   2.209 +                }
   2.210                  munmap(mem, PAGE_SIZE);
   2.211 -                goto out;
   2.212 +                sent_this_iter++;
   2.213 +                total_sent++;
   2.214              }
   2.215 -            munmap(mem, PAGE_SIZE);
   2.216 -            sent_this_iter++;
   2.217 -            total_sent++;
   2.218          }
   2.219  
   2.220          if (last_iter)
   2.221 @@ -420,36 +473,69 @@ xc_domain_save(int xc_handle, int io_fd,
   2.222          }
   2.223      }
   2.224  
   2.225 -    /* Send through a list of all the PFNs that were not in map at the close */
   2.226 +    /*
   2.227 +     * Send through a list of all the PFNs that were not in map at the close.
   2.228 +     * We send pages which was allocated. However balloon driver may 
   2.229 +     * decreased after sending page. So we have to check the freed
   2.230 +     * page after pausing the domain.
   2.231 +     */
   2.232      {
   2.233 -        unsigned int i,j;
   2.234 +        unsigned long N;
   2.235          unsigned long pfntab[1024];
   2.236 +        unsigned int j;
   2.237  
   2.238 -        for (i = 0, j = 0; i < p2m_size; i++) {
   2.239 -            if (page_array[i] == INVALID_MFN)
   2.240 -                j++;
   2.241 +        j = 0;
   2.242 +        for (p = memmap_desc_start;
   2.243 +             p < memmap_desc_end;
   2.244 +             p += memmap_info->efi_memdesc_size) {
   2.245 +            md = p;
   2.246 +            if (md->type != EFI_CONVENTIONAL_MEMORY ||
   2.247 +                md->attribute != EFI_MEMORY_WB ||
   2.248 +                md->num_pages == 0)
   2.249 +                continue;
   2.250 +            for (N = md->phys_addr >> PAGE_SHIFT;
   2.251 +                 N < (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >>
   2.252 +                     PAGE_SHIFT;
   2.253 +                 N++) {
   2.254 +                if (!xc_ia64_p2m_allocated(&p2m_table, N))
   2.255 +                    j++;
   2.256 +            }
   2.257          }
   2.258 -
   2.259          if (!write_exact(io_fd, &j, sizeof(unsigned int))) {
   2.260              ERROR("Error when writing to state file (6a)");
   2.261              goto out;
   2.262          }
   2.263 -
   2.264 -        for (i = 0, j = 0; i < p2m_size; ) {
   2.265 -
   2.266 -            if (page_array[i] == INVALID_MFN)
   2.267 -                pfntab[j++] = i;
   2.268 -
   2.269 -            i++;
   2.270 -            if (j == 1024 || i == p2m_size) {
   2.271 -                if (!write_exact(io_fd, &pfntab, sizeof(unsigned long)*j)) {
   2.272 -                    ERROR("Error when writing to state file (6b)");
   2.273 -                    goto out;
   2.274 +        
   2.275 +        j = 0;
   2.276 +        for (p = memmap_desc_start;
   2.277 +             p < memmap_desc_end;
   2.278 +             p += memmap_info->efi_memdesc_size) {
   2.279 +            md = p;
   2.280 +            if (md->type != EFI_CONVENTIONAL_MEMORY ||
   2.281 +                md->attribute != EFI_MEMORY_WB ||
   2.282 +                md->num_pages == 0)
   2.283 +                continue;
   2.284 +            for (N = md->phys_addr >> PAGE_SHIFT;
   2.285 +                 N < (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >>
   2.286 +                     PAGE_SHIFT;
   2.287 +                 N++) {
   2.288 +                if (!xc_ia64_p2m_allocated(&p2m_table, N))
   2.289 +                    pfntab[j++] = N;
   2.290 +                if (j == sizeof(pfntab)/sizeof(pfntab[0])) {
   2.291 +                    if (!write_exact(io_fd, &pfntab, sizeof(pfntab[0]) * j)) {
   2.292 +                        ERROR("Error when writing to state file (6b)");
   2.293 +                        goto out;
   2.294 +                    }
   2.295 +                    j = 0;
   2.296                  }
   2.297 -                j = 0;
   2.298              }
   2.299          }
   2.300 -
   2.301 +        if (j > 0) {
   2.302 +            if (!write_exact(io_fd, &pfntab, sizeof(pfntab[0]) * j)) {
   2.303 +                ERROR("Error when writing to state file (6b)");
   2.304 +                goto out;
   2.305 +            }
   2.306 +        }
   2.307      }
   2.308  
   2.309      if (xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt)) {
   2.310 @@ -494,13 +580,17 @@ xc_domain_save(int xc_handle, int io_fd,
   2.311          }
   2.312      }
   2.313  
   2.314 -    free(page_array);
   2.315      unlock_pages(to_send, bitmap_size);
   2.316      free(to_send);
   2.317      unlock_pages(to_skip, bitmap_size);
   2.318      free(to_skip);
   2.319      if (live_shinfo)
   2.320          munmap(live_shinfo, PAGE_SIZE);
   2.321 +    if (memmap_info_live)
   2.322 +        munmap(memmap_info_live, memmap_size);
   2.323 +    if (memmap_info)
   2.324 +        free(memmap_info);
   2.325 +    xc_ia64_p2m_unmap(&p2m_table);
   2.326  
   2.327      fprintf(stderr,"Save exit rc=%d\n",rc);
   2.328  
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/libxc/ia64/xc_ia64_save_restore.h	Thu Sep 06 15:36:13 2007 -0600
     3.3 @@ -0,0 +1,44 @@
     3.4 +/******************************************************************************
     3.5 + * xc_ia64_save_restore.h
     3.6 + *
     3.7 + * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
     3.8 + *                    VA Linux Systems Japan K.K.
     3.9 + *
    3.10 + * This program is free software; you can redistribute it and/or modify
    3.11 + * it under the terms of the GNU General Public License as published by
    3.12 + * the Free Software Foundation; either version 2 of the License, or
    3.13 + * (at your option) any later version.
    3.14 + *
    3.15 + * This program is distributed in the hope that it will be useful,
    3.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.18 + * GNU General Public License for more details.
    3.19 + *
    3.20 + * You should have received a copy of the GNU General Public License
    3.21 + * along with this program; if not, write to the Free Software
    3.22 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    3.23 + *
    3.24 + */
    3.25 +
    3.26 +#ifndef XC_IA64_SAVE_RESTORE_H
    3.27 +#define XC_IA64_SR_H
    3.28 +
    3.29 +        /* introduced changeset 10692:306d7857928c of xen-ia64-unstable.ht */
    3.30 +#define XC_IA64_SR_FORMAT_VER_ONE       1UL
    3.31 +        /* using foreign p2m exposure version */
    3.32 +#define XC_IA64_SR_FORMAT_VER_TWO       2UL
    3.33 +#define XC_IA64_SR_FORMAT_VER_MAX       2UL
    3.34 +
    3.35 +#define XC_IA64_SR_FORMAT_VER_CURRENT   XC_IA64_SR_FORMAT_VER_TWO
    3.36 +
    3.37 +#endif /* XC_IA64_SAVE_RESTORE_H */
    3.38 +
    3.39 +/*
    3.40 + * Local variables:
    3.41 + * mode: C
    3.42 + * c-set-style: "BSD"
    3.43 + * c-basic-offset: 4
    3.44 + * tab-width: 4
    3.45 + * indent-tabs-mode: nil
    3.46 + * End:
    3.47 + */