ia64/xen-unstable

changeset 14471:36e6f85cd572

hvm: Do not save/restore shared_info gpfn location.

Instead of kludging a max_gpfn estimate in shared_info, add a new
XENMEM command to discover the actual maximum gpfn value as known by
the shadow code.

This needs to be more robust when we support HVM ballooning in future
anyway. One interesting point is that max_gpfn may be close to 4GB
even for small-memory HVM guests since for example SVGA LFB is mapped
into the I/O hole. We may need to special case the I/O hole somehow,
or provide some finer-grained way to find out which parts of the GPFN
space are actually used (e.g., get Xen to fill in a bitmap with 1 bit
per 1024 pages, or similar).

Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Mon Mar 19 16:48:24 2007 +0000 (2007-03-19)
parents ed1e4cc4a5b7
children 4e380c769774
files tools/libxc/xc_core_x86.c tools/libxc/xc_hvm_build.c tools/libxc/xc_hvm_restore.c tools/libxc/xc_hvm_save.c tools/libxc/xc_private.c xen/arch/x86/mm.c xen/arch/x86/mm/shadow/common.c xen/common/compat/memory.c xen/common/memory.c xen/include/asm-ia64/mm.h xen/include/asm-powerpc/mm.h xen/include/asm-x86/mm.h xen/include/public/memory.h
line diff
     1.1 --- a/tools/libxc/xc_core_x86.c	Mon Mar 19 16:28:24 2007 +0000
     1.2 +++ b/tools/libxc/xc_core_x86.c	Mon Mar 19 16:48:24 2007 +0000
     1.3 @@ -21,12 +21,15 @@
     1.4  #include "xg_private.h"
     1.5  #include "xc_core.h"
     1.6  
     1.7 +static int max_gpfn(int xc_handle, domid_t domid)
     1.8 +{
     1.9 +    return xc_memory_op(xc_handle, XENMEM_maximum_gpfn, &domid);
    1.10 +}
    1.11 +
    1.12  int
    1.13  xc_core_arch_auto_translated_physmap(const xc_dominfo_t *info)
    1.14  {
    1.15 -    if ( info->hvm )
    1.16 -        return 1;
    1.17 -    return 0;
    1.18 +    return info->hvm;
    1.19  }
    1.20  
    1.21  int
    1.22 @@ -35,14 +38,14 @@ xc_core_arch_memory_map_get(int xc_handl
    1.23                              xc_core_memory_map_t **mapp,
    1.24                              unsigned int *nr_entries)
    1.25  {
    1.26 -    unsigned long max_pfn = live_shinfo->arch.max_pfn;
    1.27 -    xc_core_memory_map_t *map = NULL;
    1.28 +    unsigned long max_pfn = max_gpfn(xc_handle, info->domid);
    1.29 +    xc_core_memory_map_t *map;
    1.30  
    1.31      map = malloc(sizeof(*map));
    1.32 -    if ( !map )
    1.33 +    if ( map == NULL )
    1.34      {
    1.35          PERROR("Could not allocate memory");
    1.36 -        goto out;
    1.37 +        return -1;
    1.38      }
    1.39  
    1.40      map->addr = 0;
    1.41 @@ -51,11 +54,6 @@ xc_core_arch_memory_map_get(int xc_handl
    1.42      *mapp = map;
    1.43      *nr_entries = 1;
    1.44      return 0;
    1.45 -
    1.46 -out:
    1.47 -    if ( map )
    1.48 -        free(map);
    1.49 -    return -1;
    1.50  }
    1.51  
    1.52  int
    1.53 @@ -67,7 +65,7 @@ xc_core_arch_map_p2m(int xc_handle, xc_d
    1.54      xen_pfn_t *live_p2m_frame_list_list = NULL;
    1.55      xen_pfn_t *live_p2m_frame_list = NULL;
    1.56      uint32_t dom = info->domid;
    1.57 -    unsigned long max_pfn = live_shinfo->arch.max_pfn;
    1.58 +    unsigned long max_pfn = max_gpfn(xc_handle, info->domid);
    1.59      int ret = -1;
    1.60      int err;
    1.61  
     2.1 --- a/tools/libxc/xc_hvm_build.c	Mon Mar 19 16:28:24 2007 +0000
     2.2 +++ b/tools/libxc/xc_hvm_build.c	Mon Mar 19 16:48:24 2007 +0000
     2.3 @@ -286,7 +286,6 @@ static int setup_guest(int xc_handle,
     2.4      /* NB. evtchn_upcall_mask is unused: leave as zero. */
     2.5      memset(&shared_info->evtchn_mask[0], 0xff,
     2.6             sizeof(shared_info->evtchn_mask));
     2.7 -    shared_info->arch.max_pfn = page_array[nr_pages - 1];
     2.8      munmap(shared_info, PAGE_SIZE);
     2.9  
    2.10      if ( v_end > HVM_BELOW_4G_RAM_END )
     3.1 --- a/tools/libxc/xc_hvm_restore.c	Mon Mar 19 16:28:24 2007 +0000
     3.2 +++ b/tools/libxc/xc_hvm_restore.c	Mon Mar 19 16:48:24 2007 +0000
     3.3 @@ -70,9 +70,6 @@ int xc_hvm_restore(int xc_handle, int io
     3.4  {
     3.5      DECLARE_DOMCTL;
     3.6  
     3.7 -    /* The new domain's shared-info frame number. */
     3.8 -    unsigned long shared_info_frame;
     3.9 -
    3.10      /* A copy of the CPU context of the guest. */
    3.11      vcpu_guest_context_t ctxt;
    3.12  
    3.13 @@ -86,8 +83,6 @@ int xc_hvm_restore(int xc_handle, int io
    3.14      uint8_t *hvm_buf = NULL;
    3.15      unsigned long long v_end, memsize;
    3.16      unsigned long shared_page_nr;
    3.17 -    shared_info_t *shared_info = NULL;
    3.18 -    xen_pfn_t arch_max_pfn;
    3.19  
    3.20      unsigned long pfn;
    3.21      unsigned int prev_pc, this_pc;
    3.22 @@ -96,8 +91,6 @@ int xc_hvm_restore(int xc_handle, int io
    3.23      /* Types of the pfns in the current region */
    3.24      unsigned long region_pfn_type[MAX_BATCH_SIZE];
    3.25  
    3.26 -    struct xen_add_to_physmap xatp;
    3.27 -
    3.28      /* Number of pages of memory the guest has.  *Not* the same as max_pfn. */
    3.29      unsigned long nr_pages;
    3.30  
    3.31 @@ -146,7 +139,6 @@ int xc_hvm_restore(int xc_handle, int io
    3.32          pfns[i] = i;
    3.33      for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < pfn_array_size; i++ )
    3.34          pfns[i] += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT;
    3.35 -    arch_max_pfn = pfns[max_pfn];/* used later */
    3.36  
    3.37      /* Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. */
    3.38      rc = xc_domain_memory_populate_physmap(
    3.39 @@ -350,29 +342,6 @@ int xc_hvm_restore(int xc_handle, int io
    3.40          goto out;
    3.41      }
    3.42  
    3.43 -    /* Shared-info pfn */
    3.44 -    if (!read_exact(io_fd, &(shared_info_frame), sizeof(uint32_t)) ) {
    3.45 -        ERROR("reading the shared-info pfn failed!\n");
    3.46 -        goto out;
    3.47 -    }
    3.48 -    /* Map the shared-info frame where it was before */
    3.49 -    xatp.domid = dom;
    3.50 -    xatp.space = XENMAPSPACE_shared_info;
    3.51 -    xatp.idx   = 0;
    3.52 -    xatp.gpfn  = shared_info_frame;
    3.53 -    if ( (rc = xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp)) != 0 ) {
    3.54 -        ERROR("setting the shared-info pfn failed!\n");
    3.55 -        goto out;
    3.56 -    }
    3.57 -    if ( (xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp) != 0) ||
    3.58 -         ((shared_info = xc_map_foreign_range(
    3.59 -             xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE,
    3.60 -             shared_info_frame)) == NULL) )
    3.61 -        goto out;
    3.62 -    /* shared_info.arch.max_pfn is used by dump-core */
    3.63 -    shared_info->arch.max_pfn = arch_max_pfn;
    3.64 -    munmap(shared_info, PAGE_SIZE);
    3.65 -
    3.66      rc = 0;
    3.67      goto out;
    3.68  
     4.1 --- a/tools/libxc/xc_hvm_save.c	Mon Mar 19 16:28:24 2007 +0000
     4.2 +++ b/tools/libxc/xc_hvm_save.c	Mon Mar 19 16:48:24 2007 +0000
     4.3 @@ -302,9 +302,6 @@ int xc_hvm_save(int xc_handle, int io_fd
     4.4      /* The size of an array big enough to contain all guest pfns */
     4.5      unsigned long pfn_array_size;
     4.6  
     4.7 -    /* The new domain's shared-info frame number. */
     4.8 -    unsigned long shared_info_frame;
     4.9 -
    4.10      /* Other magic frames: ioreqs and xenstore comms */
    4.11      unsigned long ioreq_pfn, bufioreq_pfn, store_pfn;
    4.12  
    4.13 @@ -318,9 +315,6 @@ int xc_hvm_save(int xc_handle, int io_fd
    4.14      uint32_t hvm_buf_size;
    4.15      uint8_t *hvm_buf = NULL;
    4.16  
    4.17 -    /* Live mapping of shared info structure */
    4.18 -    shared_info_t *live_shinfo = NULL;
    4.19 -
    4.20      /* base of the region in which domain memory is mapped */
    4.21      unsigned char *region_base = NULL;
    4.22  
    4.23 @@ -372,7 +366,6 @@ int xc_hvm_save(int xc_handle, int io_fd
    4.24          ERROR("HVM:Could not get vcpu context");
    4.25          goto out;
    4.26      }
    4.27 -    shared_info_frame = info.shared_info_frame;
    4.28  
    4.29      /* cheesy sanity check */
    4.30      if ((info.max_memkb >> (PAGE_SHIFT - 10)) > max_mfn) {
    4.31 @@ -381,13 +374,6 @@ int xc_hvm_save(int xc_handle, int io_fd
    4.32          goto out;
    4.33      }
    4.34  
    4.35 -    /* Map the shared info frame */
    4.36 -    if(!(live_shinfo = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
    4.37 -                                            PROT_READ, shared_info_frame))) {
    4.38 -        ERROR("HVM:Couldn't map live_shinfo");
    4.39 -        goto out;
    4.40 -    }
    4.41 -
    4.42      if ( xc_get_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, &store_pfn)
    4.43           || xc_get_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, &ioreq_pfn)
    4.44           || xc_get_hvm_param(xc_handle, dom, 
    4.45 @@ -525,13 +511,6 @@ int xc_hvm_save(int xc_handle, int io_fd
    4.46  
    4.47          DPRINTF("Saving HVM domain memory pages: iter %d   0%%", iter);
    4.48  
    4.49 -        if (last_iter && (max_pfn != live_shinfo->arch.max_pfn)) {
    4.50 -            DPRINTF("calculated max_pfn as %#lx, shinfo says %#lx\n",
    4.51 -                    max_pfn, live_shinfo->arch.max_pfn);
    4.52 -            ERROR("Max pfn doesn't match shared info");
    4.53 -            goto out;
    4.54 -        }
    4.55 -
    4.56          while( N < pfn_array_size ){
    4.57  
    4.58              unsigned int this_pc = (N * 100) / pfn_array_size;
    4.59 @@ -679,8 +658,7 @@ int xc_hvm_save(int xc_handle, int io_fd
    4.60                      goto out;
    4.61                  }
    4.62  
    4.63 -                DPRINTF("SUSPEND shinfo %08lx eip %08lx edx %08lx\n",
    4.64 -                        info.shared_info_frame,
    4.65 +                DPRINTF("SUSPEND eip %08lx edx %08lx\n",
    4.66                          (unsigned long)ctxt.user_regs.eip,
    4.67                          (unsigned long)ctxt.user_regs.edx);
    4.68              }
    4.69 @@ -768,12 +746,6 @@ int xc_hvm_save(int xc_handle, int io_fd
    4.70          ERROR("write HVM info failed!\n");
    4.71      }
    4.72  
    4.73 -    /* Shared-info pfn */
    4.74 -    if (!write_exact(io_fd, &(shared_info_frame), sizeof(uint32_t)) ) {
    4.75 -        ERROR("write shared-info pfn failed!\n");
    4.76 -        goto out;
    4.77 -    }
    4.78 - 
    4.79      /* Success! */
    4.80      rc = 0;
    4.81  
     5.1 --- a/tools/libxc/xc_private.c	Mon Mar 19 16:28:24 2007 +0000
     5.2 +++ b/tools/libxc/xc_private.c	Mon Mar 19 16:48:24 2007 +0000
     5.3 @@ -263,6 +263,15 @@ int xc_memory_op(int xc_handle,
     5.4              goto out1;
     5.5          }
     5.6          break;
     5.7 +    case XENMEM_current_reservation:
     5.8 +    case XENMEM_maximum_reservation:
     5.9 +    case XENMEM_maximum_gpfn:
    5.10 +        if ( lock_pages(arg, sizeof(domid_t)) )
    5.11 +        {
    5.12 +            PERROR("Could not lock");
    5.13 +            goto out1;
    5.14 +        }
    5.15 +        break;
    5.16      }
    5.17  
    5.18      ret = do_xen_hypercall(xc_handle, &hypercall);
    5.19 @@ -287,6 +296,11 @@ int xc_memory_op(int xc_handle,
    5.20      case XENMEM_add_to_physmap:
    5.21          unlock_pages(arg, sizeof(struct xen_add_to_physmap));
    5.22          break;
    5.23 +    case XENMEM_current_reservation:
    5.24 +    case XENMEM_maximum_reservation:
    5.25 +    case XENMEM_maximum_gpfn:
    5.26 +        unlock_pages(arg, sizeof(domid_t));
    5.27 +        break;
    5.28      }
    5.29  
    5.30   out1:
     6.1 --- a/xen/arch/x86/mm.c	Mon Mar 19 16:28:24 2007 +0000
     6.2 +++ b/xen/arch/x86/mm.c	Mon Mar 19 16:48:24 2007 +0000
     6.3 @@ -108,6 +108,7 @@
     6.4  #include <asm/x86_emulate.h>
     6.5  #include <asm/e820.h>
     6.6  #include <asm/hypercall.h>
     6.7 +#include <asm/shared.h>
     6.8  #include <public/memory.h>
     6.9  
    6.10  #define MEM_LOG(_f, _a...) gdprintk(XENLOG_WARNING , _f "\n" , ## _a)
    6.11 @@ -246,6 +247,11 @@ int memory_is_conventional_ram(paddr_t p
    6.12      return 0;
    6.13  }
    6.14  
    6.15 +unsigned long domain_get_maximum_gpfn(struct domain *d)
    6.16 +{
    6.17 +    return is_hvm_domain(d) ? d->arch.p2m.max_mapped_pfn : arch_get_max_pfn(d);
    6.18 +}
    6.19 +
    6.20  void share_xen_page_with_guest(
    6.21      struct page_info *page, struct domain *d, int readonly)
    6.22  {
     7.1 --- a/xen/arch/x86/mm/shadow/common.c	Mon Mar 19 16:28:24 2007 +0000
     7.2 +++ b/xen/arch/x86/mm/shadow/common.c	Mon Mar 19 16:48:24 2007 +0000
     7.3 @@ -36,7 +36,6 @@
     7.4  #include <asm/current.h>
     7.5  #include <asm/flushtlb.h>
     7.6  #include <asm/shadow.h>
     7.7 -#include <asm/shared.h>
     7.8  #include "private.h"
     7.9  
    7.10  
    7.11 @@ -2672,7 +2671,7 @@ sh_alloc_log_dirty_bitmap(struct domain 
    7.12  {
    7.13      ASSERT(d->arch.paging.shadow.dirty_bitmap == NULL);
    7.14      d->arch.paging.shadow.dirty_bitmap_size =
    7.15 -        (arch_get_max_pfn(d) + (BITS_PER_LONG - 1)) &
    7.16 +        (domain_get_maximum_gpfn(d) + (BITS_PER_LONG - 1)) &
    7.17          ~(BITS_PER_LONG - 1);
    7.18      d->arch.paging.shadow.dirty_bitmap =
    7.19          xmalloc_array(unsigned long,
    7.20 @@ -2682,7 +2681,8 @@ sh_alloc_log_dirty_bitmap(struct domain 
    7.21          d->arch.paging.shadow.dirty_bitmap_size = 0;
    7.22          return -ENOMEM;
    7.23      }
    7.24 -    memset(d->arch.paging.shadow.dirty_bitmap, 0, d->arch.paging.shadow.dirty_bitmap_size/8);
    7.25 +    memset(d->arch.paging.shadow.dirty_bitmap, 0,
    7.26 +           d->arch.paging.shadow.dirty_bitmap_size/8);
    7.27  
    7.28      return 0;
    7.29  }
     8.1 --- a/xen/common/compat/memory.c	Mon Mar 19 16:28:24 2007 +0000
     8.2 +++ b/xen/common/compat/memory.c	Mon Mar 19 16:48:24 2007 +0000
     8.3 @@ -170,6 +170,7 @@ int compat_memory_op(unsigned int cmd, X
     8.4  
     8.5          case XENMEM_current_reservation:
     8.6          case XENMEM_maximum_reservation:
     8.7 +        case XENMEM_maximum_gpfn:
     8.8          {
     8.9  #define xen_domid_t domid_t
    8.10  #define compat_domid_t domid_compat_t
    8.11 @@ -325,6 +326,7 @@ int compat_memory_op(unsigned int cmd, X
    8.12          case XENMEM_maximum_ram_page:
    8.13          case XENMEM_current_reservation:
    8.14          case XENMEM_maximum_reservation:
    8.15 +        case XENMEM_maximum_gpfn:
    8.16              break;
    8.17  
    8.18          case XENMEM_translate_gpfn_list:
     9.1 --- a/xen/common/memory.c	Mon Mar 19 16:28:24 2007 +0000
     9.2 +++ b/xen/common/memory.c	Mon Mar 19 16:48:24 2007 +0000
     9.3 @@ -584,6 +584,7 @@ long do_memory_op(unsigned long cmd, XEN
     9.4  
     9.5      case XENMEM_current_reservation:
     9.6      case XENMEM_maximum_reservation:
     9.7 +    case XENMEM_maximum_gpfn:
     9.8          if ( copy_from_guest(&domid, arg, 1) )
     9.9              return -EFAULT;
    9.10  
    9.11 @@ -594,7 +595,19 @@ long do_memory_op(unsigned long cmd, XEN
    9.12          else if ( (d = rcu_lock_domain_by_id(domid)) == NULL )
    9.13              return -ESRCH;
    9.14  
    9.15 -        rc = (op == XENMEM_current_reservation) ? d->tot_pages : d->max_pages;
    9.16 +        switch ( op )
    9.17 +        {
    9.18 +        case XENMEM_current_reservation:
    9.19 +            rc = d->tot_pages;
    9.20 +            break;
    9.21 +        case XENMEM_maximum_reservation:
    9.22 +            rc = d->max_pages;
    9.23 +            break;
    9.24 +        default:
    9.25 +            ASSERT(op == XENMEM_maximum_gpfn);
    9.26 +            rc = domain_get_maximum_gpfn(d);
    9.27 +            break;
    9.28 +        }
    9.29  
    9.30          if ( unlikely(domid != DOMID_SELF) )
    9.31              rcu_unlock_domain(d);
    10.1 --- a/xen/include/asm-ia64/mm.h	Mon Mar 19 16:28:24 2007 +0000
    10.2 +++ b/xen/include/asm-ia64/mm.h	Mon Mar 19 16:48:24 2007 +0000
    10.3 @@ -511,4 +511,6 @@ int steal_page(
    10.4  
    10.5  #define domain_clamp_alloc_bitsize(d, b) (b)
    10.6  
    10.7 +#define domain_get_maximum_gpfn(d) (-ENOSYS)
    10.8 +
    10.9  #endif /* __ASM_IA64_MM_H__ */
    11.1 --- a/xen/include/asm-powerpc/mm.h	Mon Mar 19 16:28:24 2007 +0000
    11.2 +++ b/xen/include/asm-powerpc/mm.h	Mon Mar 19 16:48:24 2007 +0000
    11.3 @@ -278,4 +278,6 @@ extern int steal_page(struct domain *d, 
    11.4  
    11.5  #define domain_clamp_alloc_bitsize(d, b) (b)
    11.6  
    11.7 +#define domain_get_maximum_gpfn(d) (-ENOSYS)
    11.8 +
    11.9  #endif
    12.1 --- a/xen/include/asm-x86/mm.h	Mon Mar 19 16:28:24 2007 +0000
    12.2 +++ b/xen/include/asm-x86/mm.h	Mon Mar 19 16:48:24 2007 +0000
    12.3 @@ -404,5 +404,6 @@ unsigned int domain_clamp_alloc_bitsize(
    12.4  # define domain_clamp_alloc_bitsize(d, b) (b)
    12.5  #endif
    12.6  
    12.7 +unsigned long domain_get_maximum_gpfn(struct domain *d);
    12.8  
    12.9  #endif /* __ASM_X86_MM_H__ */
    13.1 --- a/xen/include/public/memory.h	Mon Mar 19 16:28:24 2007 +0000
    13.2 +++ b/xen/include/public/memory.h	Mon Mar 19 16:48:24 2007 +0000
    13.3 @@ -129,6 +129,11 @@ DEFINE_XEN_GUEST_HANDLE(xen_memory_excha
    13.4  #define XENMEM_maximum_reservation  4
    13.5  
    13.6  /*
    13.7 + * Returns the maximum GPFN in use by the guest, or -ve errcode on failure.
    13.8 + */
    13.9 +#define XENMEM_maximum_gpfn         14
   13.10 +
   13.11 +/*
   13.12   * Returns a list of MFN bases of 2MB extents comprising the machine_to_phys
   13.13   * mapping table. Architectures which do not have a m2p table do not implement
   13.14   * this command.