PoD memory 8/9: libxc interface
authorKeir Fraser <keir.fraser@citrix.com>
Mon, 5 Jan 2009 10:46:37 +0000 (10:46 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Mon, 5 Jan 2009 10:46:37 +0000 (10:46 +0000)
Implement libxc interface to PoD functionality:
* Add xc_hvm_build_target_mem(), which takes both memsize and target.
Memsize is the total memory, allocated in PoD pages and reported in
the e820; target is the size of the cache.  If these are the same, the
normal funcitonality is called.  (So you can use the same function to
build always, and it will decide whether to use PoD or not.)
* Add xc_domain_memory_[gs]et_pod_target(), which sets and/or returns
information about the PoD cache and p2m entries.

Signed-off-by: George Dunlap <george.dunlap@eu.citrix.com>
tools/libxc/xc_domain.c
tools/libxc/xc_hvm_build.c
tools/libxc/xc_private.c
tools/libxc/xenctrl.h
tools/libxc/xenguest.h

index afffd68d1a1c06ec44b113d63e42dcee3df97973..b508149b3f4f92096c32e27a1c40f7d357ab1155 100644 (file)
@@ -564,6 +564,76 @@ int xc_domain_memory_translate_gpfn_list(int xc_handle,
     return err;
 }
 
+static int xc_domain_memory_pod_target(int xc_handle,
+                                       int op,
+                                       uint32_t domid,
+                                       uint64_t target_pages,
+                                       uint64_t *tot_pages,
+                                       uint64_t *pod_cache_pages,
+                                       uint64_t *pod_entries)
+{
+    int err;
+
+    struct xen_pod_target pod_target = {
+        .domid = domid,
+        .target_pages = target_pages
+    };
+
+    err = xc_memory_op(xc_handle, op, &pod_target);
+
+    if ( err < 0 )
+    {
+        DPRINTF("Failed %s_memory_target dom %d\n",
+                (op==XENMEM_set_pod_target)?"set":"get",
+                domid);
+        errno = -err;
+        err = -1;
+    }
+    else
+        err = 0;
+
+    if ( tot_pages )
+        *tot_pages = pod_target.tot_pages;
+    if ( pod_cache_pages )
+        *pod_cache_pages = pod_target.pod_cache_pages;
+    if ( pod_entries )
+        *pod_entries = pod_target.pod_entries;
+
+    return err;
+}
+                                       
+
+int xc_domain_memory_set_pod_target(int xc_handle,
+                                    uint32_t domid,
+                                    uint64_t target_pages,
+                                    uint64_t *tot_pages,
+                                    uint64_t *pod_cache_pages,
+                                    uint64_t *pod_entries)
+{
+    return xc_domain_memory_pod_target(xc_handle,
+                                       XENMEM_set_pod_target,
+                                       domid,
+                                       target_pages,
+                                       tot_pages,
+                                       pod_cache_pages,
+                                       pod_entries);
+}
+
+int xc_domain_memory_get_pod_target(int xc_handle,
+                                    uint32_t domid,
+                                    uint64_t *tot_pages,
+                                    uint64_t *pod_cache_pages,
+                                    uint64_t *pod_entries)
+{
+    return xc_domain_memory_pod_target(xc_handle,
+                                       XENMEM_get_pod_target,
+                                       domid,
+                                       -1,
+                                       tot_pages,
+                                       pod_cache_pages,
+                                       pod_entries);
+}
+
 int xc_domain_max_vcpus(int xc_handle, uint32_t domid, unsigned int max)
 {
     DECLARE_DOMCTL;
index 752c4e76dcd2f3f4bdb209d73ce4a9af60dd49a4..e0e75aac21460ba14bfd9a0646ab0c3b71cabf8f 100644 (file)
@@ -146,11 +146,13 @@ static int loadelfimage(
 }
 
 static int setup_guest(int xc_handle,
-                       uint32_t dom, int memsize,
+                       uint32_t dom, int memsize, int target,
                        char *image, unsigned long image_size)
 {
     xen_pfn_t *page_array = NULL;
     unsigned long i, nr_pages = (unsigned long)memsize << (20 - PAGE_SHIFT);
+    unsigned long target_pages = (unsigned long)target << (20 - PAGE_SHIFT);
+    unsigned long pod_pages = 0;
     unsigned long special_page_nr, entry_eip, cur_pages;
     struct xen_add_to_physmap xatp;
     struct shared_info *shared_info;
@@ -160,11 +162,16 @@ static int setup_guest(int xc_handle,
     uint64_t v_start, v_end;
     int rc;
     xen_capabilities_info_t caps;
+    int pod_mode = 0;
+    
 
     /* An HVM guest must be initialised with at least 2MB memory. */
-    if ( memsize < 2 )
+    if ( memsize < 2 || target < 2 )
         goto error_out;
 
+    if ( memsize > target )
+        pod_mode = 1;
+
     if ( elf_init(&elf, image, image_size) != 0 )
         goto error_out;
     elf_parse_binary(&elf);
@@ -235,6 +242,10 @@ static int setup_guest(int xc_handle,
                 .extent_order = SUPERPAGE_PFN_SHIFT,
                 .domid        = dom
             };
+
+            if ( pod_mode )
+                sp_req.mem_flags = XENMEMF_populate_on_demand;
+
             set_xen_guest_handle(sp_req.extent_start, sp_extents);
             for ( i = 0; i < sp_req.nr_extents; i++ )
                 sp_extents[i] = page_array[cur_pages+(i<<SUPERPAGE_PFN_SHIFT)];
@@ -242,6 +253,11 @@ static int setup_guest(int xc_handle,
             if ( done > 0 )
             {
                 done <<= SUPERPAGE_PFN_SHIFT;
+                if ( pod_mode && target_pages > cur_pages )
+                {
+                    int d = target_pages - cur_pages;
+                    pod_pages += ( done < d ) ? done : d;
+                }
                 cur_pages += done;
                 count -= done;
             }
@@ -253,9 +269,17 @@ static int setup_guest(int xc_handle,
             rc = xc_domain_memory_populate_physmap(
                 xc_handle, dom, count, 0, 0, &page_array[cur_pages]);
             cur_pages += count;
+            if ( pod_mode )
+                pod_pages -= count;
         }
     }
 
+    if ( pod_mode )
+        rc = xc_domain_memory_set_pod_target(xc_handle,
+                                             dom,
+                                             pod_pages,
+                                             NULL, NULL, NULL);
+
     if ( rc != 0 )
     {
         PERROR("Could not allocate memory for HVM guest.\n");
@@ -354,6 +378,7 @@ static int setup_guest(int xc_handle,
 static int xc_hvm_build_internal(int xc_handle,
                                  uint32_t domid,
                                  int memsize,
+                                 int target,
                                  char *image,
                                  unsigned long image_size)
 {
@@ -363,7 +388,7 @@ static int xc_hvm_build_internal(int xc_handle,
         return -1;
     }
 
-    return setup_guest(xc_handle, domid, memsize, image, image_size);
+    return setup_guest(xc_handle, domid, memsize, target, image, image_size);
 }
 
 static inline int is_loadable_phdr(Elf32_Phdr *phdr)
@@ -388,7 +413,34 @@ int xc_hvm_build(int xc_handle,
          ((image = xc_read_image(image_name, &image_size)) == NULL) )
         return -1;
 
-    sts = xc_hvm_build_internal(xc_handle, domid, memsize, image, image_size);
+    sts = xc_hvm_build_internal(xc_handle, domid, memsize, memsize, image, image_size);
+
+    free(image);
+
+    return sts;
+}
+
+/* xc_hvm_build_target_mem: 
+ * Create a domain for a pre-ballooned virtualized Linux, using
+ * files/filenames.  If target < memsize, domain is created with
+ * memsize pages marked populate-on-demand, and with a PoD cache size
+ * of target.  If target == memsize, pages are populated normally.
+ */
+int xc_hvm_build_target_mem(int xc_handle,
+                           uint32_t domid,
+                           int memsize,
+                           int target,
+                           const char *image_name)
+{
+    char *image;
+    int  sts;
+    unsigned long image_size;
+
+    if ( (image_name == NULL) ||
+         ((image = xc_read_image(image_name, &image_size)) == NULL) )
+        return -1;
+
+    sts = xc_hvm_build_internal(xc_handle, domid, memsize, target, image, image_size);
 
     free(image);
 
@@ -423,7 +475,7 @@ int xc_hvm_build_mem(int xc_handle,
         return -1;
     }
 
-    sts = xc_hvm_build_internal(xc_handle, domid, memsize,
+    sts = xc_hvm_build_internal(xc_handle, domid, memsize, memsize,
                                 img, img_len);
 
     /* xc_inflate_buffer may return the original buffer pointer (for
index b37978afe8120bd9e51107c2f4c3aa82d6e1beee..5990415d9e52c4dd5162ff1ae6f5f4bc9898d227 100644 (file)
@@ -323,6 +323,14 @@ int xc_memory_op(int xc_handle,
             goto out1;
         }
         break;
+    case XENMEM_set_pod_target:
+    case XENMEM_get_pod_target:
+        if ( lock_pages(arg, sizeof(struct xen_pod_target)) )
+        {
+            PERROR("Could not lock");
+            goto out1;
+        }
+        break;
     }
 
     ret = do_xen_hypercall(xc_handle, &hypercall);
@@ -355,6 +363,10 @@ int xc_memory_op(int xc_handle,
     case XENMEM_maximum_gpfn:
         unlock_pages(arg, sizeof(domid_t));
         break;
+    case XENMEM_set_pod_target:
+    case XENMEM_get_pod_target:
+        unlock_pages(arg, sizeof(struct xen_pod_target));
+        break;
     }
 
  out1:
index b915ccaff2a5a8d9ea3fbe9562d7bdb4cf99e3e1..8c6761b0bd0234bdf74a83bee1a336a8c34fccf0 100644 (file)
@@ -634,6 +634,19 @@ int xc_domain_memory_translate_gpfn_list(int xc_handle,
                                          xen_pfn_t *gpfn_list,
                                          xen_pfn_t *mfn_list);
 
+int xc_domain_memory_set_pod_target(int xc_handle,
+                                    uint32_t domid,
+                                    uint64_t target_pages,
+                                    uint64_t *tot_pages,
+                                    uint64_t *pod_cache_pages,
+                                    uint64_t *pod_entries);
+
+int xc_domain_memory_get_pod_target(int xc_handle,
+                                    uint32_t domid,
+                                    uint64_t *tot_pages,
+                                    uint64_t *pod_cache_pages,
+                                    uint64_t *pod_entries);
+
 int xc_domain_ioport_permission(int xc_handle,
                                 uint32_t domid,
                                 uint32_t first_port,
index ba60326a47847c583eabb25d0cc68bec651010a4..7261e391ac4ce83de54063608b99685fe4ee768a 100644 (file)
@@ -130,6 +130,12 @@ int xc_hvm_build(int xc_handle,
                  int memsize,
                  const char *image_name);
 
+int xc_hvm_build_target_mem(int xc_handle,
+                            uint32_t domid,
+                            int memsize,
+                            int target,
+                            const char *image_name);
+
 int xc_hvm_build_mem(int xc_handle,
                      uint32_t domid,
                      int memsize,