ia64/xen-unstable

changeset 18580:e02974a95872

[IA64] libxc: make xc_ia64_copy_memmap use DOM0VP_get_memmap.

Guest domain's memory map may be updated concurrently so that
it is protected sequence lock.
This patch makes xc_ia64_copy_memmap() use DOM0VP_get_memmap
hypercall to avoid the race.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Isaku Yamahata <yamahata@valinux.co.jp>
date Fri Oct 03 12:50:28 2008 +0900 (2008-10-03)
parents 89ef37e0f4b8
children a311996570f4
files tools/libxc/ia64/xc_ia64_stubs.c
line diff
     1.1 --- a/tools/libxc/ia64/xc_ia64_stubs.c	Fri Oct 03 12:49:55 2008 +0900
     1.2 +++ b/tools/libxc/ia64/xc_ia64_stubs.c	Fri Oct 03 12:50:28 2008 +0900
     1.3 @@ -60,46 +60,89 @@ xc_get_max_pages(int xc_handle, uint32_t
     1.4              ? -1 : domctl.u.getdomaininfo.max_pages);
     1.5  }
     1.6  
     1.7 +/* It is possible to get memmap_info and memmap by
     1.8 +   foreign domain page mapping. But it's racy. Use hypercall to avoid race. */
     1.9 +static int
    1.10 +xc_ia64_get_memmap(int xc_handle,
    1.11 +                   uint32_t domid, char *buf, unsigned long bufsize)
    1.12 +{
    1.13 +    privcmd_hypercall_t hypercall;
    1.14 +    int ret;
    1.15 +
    1.16 +    hypercall.op = __HYPERVISOR_ia64_dom0vp_op;
    1.17 +    hypercall.arg[0] = IA64_DOM0VP_get_memmap;
    1.18 +    hypercall.arg[1] = domid;
    1.19 +    hypercall.arg[2] = (unsigned long)buf;
    1.20 +    hypercall.arg[3] = bufsize;
    1.21 +    hypercall.arg[4] = 0;
    1.22 +
    1.23 +    if (lock_pages(buf, bufsize) != 0)
    1.24 +        return -1;
    1.25 +    ret = do_xen_hypercall(xc_handle, &hypercall);
    1.26 +    unlock_pages(buf, bufsize);
    1.27 +    return ret;
    1.28 +}
    1.29 +
    1.30  int
    1.31  xc_ia64_copy_memmap(int xc_handle, uint32_t domid, shared_info_t *live_shinfo,
    1.32                      xen_ia64_memmap_info_t **memmap_info_p,
    1.33                      unsigned long *memmap_info_num_pages_p)
    1.34  {
    1.35 -    unsigned int memmap_info_num_pages;
    1.36 -    unsigned long memmap_info_pfn;
    1.37 +    unsigned long gpfn_max_prev;
    1.38 +    unsigned long gpfn_max_post;
    1.39 +
    1.40 +    unsigned long num_pages;
    1.41 +    unsigned long num_pages_post;
    1.42      unsigned long memmap_size;
    1.43 -
    1.44 -    xen_ia64_memmap_info_t *memmap_info_live;
    1.45      xen_ia64_memmap_info_t *memmap_info;
    1.46  
    1.47 -    /* copy before use in case someone updating them */
    1.48 -    memmap_info_num_pages = live_shinfo->arch.memmap_info_num_pages;
    1.49 -    memmap_info_pfn = live_shinfo->arch.memmap_info_pfn;
    1.50 -    if (memmap_info_num_pages == 0 || memmap_info_pfn == 0) {
    1.51 -        ERROR("memmap_info_num_pages 0x%x memmap_info_pfn 0x%lx",
    1.52 -              memmap_info_num_pages, memmap_info_pfn);
    1.53 +    int ret;
    1.54 +
    1.55 +    gpfn_max_prev = xc_memory_op(xc_handle, XENMEM_maximum_gpfn, &domid);
    1.56 +    if (gpfn_max_prev < 0)
    1.57 +        return -1;
    1.58 +
    1.59 + again:
    1.60 +    num_pages = live_shinfo->arch.memmap_info_num_pages;
    1.61 +    if (num_pages == 0) {
    1.62 +        ERROR("num_pages 0x%x", num_pages);
    1.63          return -1;
    1.64      }
    1.65  
    1.66 -    memmap_size = memmap_info_num_pages << PAGE_SHIFT;
    1.67 -    memmap_info_live = xc_map_foreign_range(xc_handle, domid, memmap_size,
    1.68 -                                            PROT_READ, memmap_info_pfn);
    1.69 -    if (memmap_info_live == NULL) {
    1.70 -        PERROR("Could not map memmap info.");
    1.71 +    memmap_size = num_pages << PAGE_SHIFT;
    1.72 +    memmap_info = malloc(memmap_size);
    1.73 +    if (memmap_info == NULL)
    1.74 +        return -1;
    1.75 +    ret = xc_ia64_get_memmap(xc_handle,
    1.76 +                             domid, (char*)memmap_info, memmap_size);
    1.77 +    if (ret != 0) {
    1.78 +        free(memmap_info);
    1.79          return -1;
    1.80      }
    1.81 -    memmap_info = malloc(memmap_size);
    1.82 -    if (memmap_info == NULL) {
    1.83 -        munmap(memmap_info_live, memmap_size);
    1.84 +    xen_rmb();
    1.85 +    num_pages_post = live_shinfo->arch.memmap_info_num_pages;
    1.86 +    if (num_pages != num_pages_post) {
    1.87 +        free(memmap_info);
    1.88 +        num_pages = num_pages_post;
    1.89 +        goto again;
    1.90 +    }
    1.91 +
    1.92 +    gpfn_max_post = xc_memory_op(xc_handle, XENMEM_maximum_gpfn, &domid);
    1.93 +    if (gpfn_max_prev < 0) {
    1.94 +        free(memmap_info);
    1.95          return -1;
    1.96      }
    1.97 -    memcpy(memmap_info, memmap_info_live, memmap_size); /* copy before use */
    1.98 -    munmap(memmap_info_live, memmap_size);
    1.99 +    if (gpfn_max_post > gpfn_max_prev) {
   1.100 +        free(memmap_info);
   1.101 +        gpfn_max_prev = gpfn_max_post;
   1.102 +        goto again;
   1.103 +    }
   1.104  
   1.105      /* reject unknown memmap */
   1.106      if (memmap_info->efi_memdesc_size != sizeof(efi_memory_desc_t) ||
   1.107          (memmap_info->efi_memmap_size / memmap_info->efi_memdesc_size) == 0 ||
   1.108 -        memmap_info->efi_memmap_size > memmap_size - sizeof(memmap_info) ||
   1.109 +        memmap_info->efi_memmap_size >
   1.110 +        (num_pages << PAGE_SHIFT) - sizeof(memmap_info) ||
   1.111          memmap_info->efi_memdesc_version != EFI_MEMORY_DESCRIPTOR_VERSION) {
   1.112          PERROR("unknown memmap header. defaulting to compat mode.");
   1.113          free(memmap_info);
   1.114 @@ -108,7 +151,7 @@ xc_ia64_copy_memmap(int xc_handle, uint3
   1.115  
   1.116      *memmap_info_p = memmap_info;
   1.117      if (memmap_info_num_pages_p != NULL)
   1.118 -        *memmap_info_num_pages_p = memmap_info_num_pages;
   1.119 +        *memmap_info_num_pages_p = num_pages;
   1.120  
   1.121      return 0;
   1.122  }