All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv6 0/8] tools: rework VM Generation ID
@ 2014-06-18 16:12 David Vrabel
  2014-06-18 16:12 ` [PATCH 1/8] libxc: add xc_hvm_param_get/set() to get/set 64-bit values David Vrabel
                   ` (8 more replies)
  0 siblings, 9 replies; 19+ messages in thread
From: David Vrabel @ 2014-06-18 16:12 UTC (permalink / raw)
  To: xen-devel; +Cc: Ian Jackson, Ian Campbell, Stefano Stabellini

This series reworks the VM Generation ID to a) conform to the
published spec from Microsoft; b) simplify the save/restore code; and
c) extend the libxl API to allow toolstacks to use this feature.

The VM Generation ID must be regenerated with a new random ID after
certain VM operations. Since xl lacks infrastructure for tracking the
life-cycle of snapshots and clones (etc), the safe option of always
using a new generation ID is used.

You can download the spec from:

  http://www.microsoft.com/en-us/download/details.aspx?id=30707

Patch status ([A]cked, [M]odified, [N]ew):

M libxc: add xc_hvm_param_get/set() to get/set 64-bit
A libxl: add libxl__random_bytes() which fills a buffer
A hvmloader: add helper functions to get/set HVM params
A hvm: add HVM_PARAM_VM_GENERATION_ID_ADDR
A libxc,libxl,hvmloader: strip out outdated VM generation
M libxl: allow a generation ID to be specified at domain
M xl: generate a new random VM generation ID if requested
A docs: update docs for the ~/platform/generation-id key

Changes in v6:

- Add xc_hvm_param_get/set() instead of changing existing functions.
- Use new libxl_ms_vm_genid type.
- xl.cfg option is now 'ms_vm_genid = "generate"|"none"'.

Changes in v5:

- Rebase on staging to fix some conflicts.
- Add libxl__random_bytes()
- Rename field to ms_vm_genid.
- Toolstacks can generate a fully random generation ID with
  libxl_ms_vm_genid_generate().

Changes in v4:

- Allow xc_get/get_hvm_params() to get/set 64-bit values.
- Const-ify libxl_uuid_*() calls.
- Minor tweaks to libxl internals (gc as param, use GCSPRINTF()).

Changes in v3:

- Specify generation ID in libxl_domain_build_info instead of having
  to call a function to set it.
- Improve docs.

Changes in v2:

- Use libxl_uuid for the generation ID.
- Add "generation_id" option to xl domain configuration file and use
  this to set a random generation ID every time.

David

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 1/8] libxc: add xc_hvm_param_get/set() to get/set 64-bit values
  2014-06-18 16:12 [PATCHv6 0/8] tools: rework VM Generation ID David Vrabel
@ 2014-06-18 16:12 ` David Vrabel
  2014-06-18 16:12 ` [PATCH 2/8] libxl: add libxl__random_bytes() which fills a buffer with random bytes David Vrabel
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 19+ messages in thread
From: David Vrabel @ 2014-06-18 16:12 UTC (permalink / raw)
  To: xen-devel; +Cc: David Vrabel, Ian Jackson, Ian Campbell, Stefano Stabellini

HVMOP_get_param and HVMOP_set_param take a uint32_t for the parameter
index and a uint64_t for the value.  So add xc_hvm_param_get() and
xc_hvm_param_set() that take the same types.

The existing xc_get_hvm_param() and xc_set_hvm_param() are retained
for compatibility but are deprecated.

Signed-off-by: David Vrabel <david.vrabel@citrix.com>
---
 tools/libxc/xc_cpuid_x86.c          |   11 +++++-----
 tools/libxc/xc_dom_arm.c            |    8 +++----
 tools/libxc/xc_domain.c             |   21 +++++++++++++++++--
 tools/libxc/xc_domain_restore.c     |   30 +++++++++++++--------------
 tools/libxc/xc_domain_save.c        |   39 ++++++++++++-----------------------
 tools/libxc/xc_hvm_build_x86.c      |   20 +++++++++---------
 tools/libxc/xc_resume.c             |    4 ++--
 tools/libxc/xenctrl.h               |    3 +++
 tools/libxl/libxl.c                 |    6 +++---
 tools/libxl/libxl_dom.c             |   30 +++++++++++++++------------
 tools/python/xen/lowlevel/xc/xc.c   |   16 +++++++-------
 tools/tests/xen-access/xen-access.c |   13 ++++++------
 tools/xenpaging/xenpaging.c         |    2 +-
 13 files changed, 107 insertions(+), 96 deletions(-)

diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c
index 4772ca7..8acb9fb 100644
--- a/tools/libxc/xc_cpuid_x86.c
+++ b/tools/libxc/xc_cpuid_x86.c
@@ -276,13 +276,12 @@ static void xc_cpuid_hvm_policy(
 {
     DECLARE_DOMCTL;
     char brand[13];
-    unsigned long nestedhvm;
-    unsigned long pae;
+    uint64_t val;
     int is_pae, is_nestedhvm;
     uint64_t xfeature_mask;
 
-    xc_get_hvm_param(xch, domid, HVM_PARAM_PAE_ENABLED, &pae);
-    is_pae = !!pae;
+    xc_hvm_param_get(xch, domid, HVM_PARAM_PAE_ENABLED, &val);
+    is_pae = !!val;
 
     /* Detecting Xen's atitude towards XSAVE */
     memset(&domctl, 0, sizeof(domctl));
@@ -291,8 +290,8 @@ static void xc_cpuid_hvm_policy(
     do_domctl(xch, &domctl);
     xfeature_mask = domctl.u.vcpuextstate.xfeature_mask;
 
-    xc_get_hvm_param(xch, domid, HVM_PARAM_NESTEDHVM, &nestedhvm);
-    is_nestedhvm = !!nestedhvm;
+    xc_hvm_param_get(xch, domid, HVM_PARAM_NESTEDHVM, &val);
+    is_nestedhvm = !!val;
 
     switch ( input[0] )
     {
diff --git a/tools/libxc/xc_dom_arm.c b/tools/libxc/xc_dom_arm.c
index cc64363..10f6bcb 100644
--- a/tools/libxc/xc_dom_arm.c
+++ b/tools/libxc/xc_dom_arm.c
@@ -80,14 +80,14 @@ static int alloc_magic_pages(struct xc_dom_image *dom)
 
     xc_clear_domain_page(dom->xch, dom->guest_domid, dom->console_pfn);
     xc_clear_domain_page(dom->xch, dom->guest_domid, dom->xenstore_pfn);
-    xc_set_hvm_param(dom->xch, dom->guest_domid, HVM_PARAM_CONSOLE_PFN,
+    xc_hvm_param_set(dom->xch, dom->guest_domid, HVM_PARAM_CONSOLE_PFN,
             dom->console_pfn);
-    xc_set_hvm_param(dom->xch, dom->guest_domid, HVM_PARAM_STORE_PFN,
+    xc_hvm_param_set(dom->xch, dom->guest_domid, HVM_PARAM_STORE_PFN,
             dom->xenstore_pfn);
     /* allocated by toolstack */
-    xc_set_hvm_param(dom->xch, dom->guest_domid, HVM_PARAM_CONSOLE_EVTCHN,
+    xc_hvm_param_set(dom->xch, dom->guest_domid, HVM_PARAM_CONSOLE_EVTCHN,
             dom->console_evtchn);
-    xc_set_hvm_param(dom->xch, dom->guest_domid, HVM_PARAM_STORE_EVTCHN,
+    xc_hvm_param_set(dom->xch, dom->guest_domid, HVM_PARAM_STORE_EVTCHN,
             dom->xenstore_evtchn);
 
     return 0;
diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
index 26edbaf..09d4a83 100644
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -1244,7 +1244,7 @@ int xc_domain_send_trigger(xc_interface *xch,
     return do_domctl(xch, &domctl);
 }
 
-int xc_set_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned long value)
+int xc_hvm_param_set(xc_interface *handle, domid_t dom, uint32_t param, uint64_t value)
 {
     DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_param_t, arg);
@@ -1265,7 +1265,7 @@ int xc_set_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned long
     return rc;
 }
 
-int xc_get_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned long *value)
+int xc_hvm_param_get(xc_interface *handle, domid_t dom, uint32_t param, uint64_t *value)
 {
     DECLARE_HYPERCALL;
     DECLARE_HYPERCALL_BUFFER(xen_hvm_param_t, arg);
@@ -1286,6 +1286,23 @@ int xc_get_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned long
     return rc;
 }
 
+int xc_set_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned long value)
+{
+    return xc_hvm_param_set(handle, dom, param, value);
+}
+
+int xc_get_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned long *value)
+{
+    uint64_t v;
+    int ret;
+
+    ret = xc_hvm_param_get(handle, dom, param, &v);
+    if (ret < 0)
+        return ret;
+    *value = v;
+    return 0;
+}
+
 int xc_hvm_create_ioreq_server(xc_interface *xch,
                                domid_t domid,
                                int handle_bufioreq,
diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
index b80f867..6849712 100644
--- a/tools/libxc/xc_domain_restore.c
+++ b/tools/libxc/xc_domain_restore.c
@@ -1646,15 +1646,15 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
             }
             /* should this be deferred? does it change? */
             if ( pagebuf.identpt )
-                xc_set_hvm_param(xch, dom, HVM_PARAM_IDENT_PT, pagebuf.identpt);
+                xc_hvm_param_set(xch, dom, HVM_PARAM_IDENT_PT, pagebuf.identpt);
             if ( pagebuf.paging_ring_pfn )
-                xc_set_hvm_param(xch, dom, HVM_PARAM_PAGING_RING_PFN, pagebuf.paging_ring_pfn);
+                xc_hvm_param_set(xch, dom, HVM_PARAM_PAGING_RING_PFN, pagebuf.paging_ring_pfn);
             if ( pagebuf.access_ring_pfn )
-                xc_set_hvm_param(xch, dom, HVM_PARAM_ACCESS_RING_PFN, pagebuf.access_ring_pfn);
+                xc_hvm_param_set(xch, dom, HVM_PARAM_ACCESS_RING_PFN, pagebuf.access_ring_pfn);
             if ( pagebuf.sharing_ring_pfn )
-                xc_set_hvm_param(xch, dom, HVM_PARAM_SHARING_RING_PFN, pagebuf.sharing_ring_pfn);
+                xc_hvm_param_set(xch, dom, HVM_PARAM_SHARING_RING_PFN, pagebuf.sharing_ring_pfn);
             if ( pagebuf.vm86_tss )
-                xc_set_hvm_param(xch, dom, HVM_PARAM_VM86_TSS, pagebuf.vm86_tss);
+                xc_hvm_param_set(xch, dom, HVM_PARAM_VM86_TSS, pagebuf.vm86_tss);
             if ( pagebuf.console_pfn )
                 console_pfn = pagebuf.console_pfn;
             if ( pagebuf.vm_generationid_addr ) {
@@ -1769,7 +1769,7 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
     }
 
     if (pagebuf.viridian != 0)
-        xc_set_hvm_param(xch, dom, HVM_PARAM_VIRIDIAN, 1);
+        xc_hvm_param_set(xch, dom, HVM_PARAM_VIRIDIAN, 1);
 
     /*
      * If we are migrating in from a host that does not support
@@ -1789,16 +1789,16 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
     } else {
         if (pagebuf.nr_ioreq_server_pages != 0 &&
             pagebuf.ioreq_server_pfn != 0) {
-            xc_set_hvm_param(xch, dom, HVM_PARAM_NR_IOREQ_SERVER_PAGES, 
+            xc_hvm_param_set(xch, dom, HVM_PARAM_NR_IOREQ_SERVER_PAGES, 
                              pagebuf.nr_ioreq_server_pages);
-            xc_set_hvm_param(xch, dom, HVM_PARAM_IOREQ_SERVER_PFN,
+            xc_hvm_param_set(xch, dom, HVM_PARAM_IOREQ_SERVER_PFN,
                              pagebuf.ioreq_server_pfn);
         }
     }
 
     if (pagebuf.acpi_ioport_location == 1) {
         DBGPRINTF("Use new firmware ioport from the checkpoint\n");
-        xc_set_hvm_param(xch, dom, HVM_PARAM_ACPI_IOPORTS_LOCATION, 1);
+        xc_hvm_param_set(xch, dom, HVM_PARAM_ACPI_IOPORTS_LOCATION, 1);
     } else if (pagebuf.acpi_ioport_location == 0) {
         DBGPRINTF("Use old firmware ioport from the checkpoint\n");
     } else {
@@ -2329,15 +2329,15 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
         goto out;
     }
 
-    if ( (frc = xc_set_hvm_param(xch, dom,
+    if ( (frc = xc_hvm_param_set(xch, dom,
                                  HVM_PARAM_IOREQ_PFN, tailbuf.u.hvm.magicpfns[0]))
-         || (frc = xc_set_hvm_param(xch, dom,
+         || (frc = xc_hvm_param_set(xch, dom,
                                     HVM_PARAM_BUFIOREQ_PFN, tailbuf.u.hvm.magicpfns[1]))
-         || (frc = xc_set_hvm_param(xch, dom,
+         || (frc = xc_hvm_param_set(xch, dom,
                                     HVM_PARAM_STORE_PFN, tailbuf.u.hvm.magicpfns[2]))
-         || (frc = xc_set_hvm_param(xch, dom,
+         || (frc = xc_hvm_param_set(xch, dom,
                                     HVM_PARAM_PAE_ENABLED, pae))
-         || (frc = xc_set_hvm_param(xch, dom,
+         || (frc = xc_hvm_param_set(xch, dom,
                                     HVM_PARAM_STORE_EVTCHN,
                                     store_evtchn)) )
     {
@@ -2351,7 +2351,7 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
             PERROR("error zeroing console page");
             goto out;
         }
-        if ( (frc = xc_set_hvm_param(xch, dom, 
+        if ( (frc = xc_hvm_param_set(xch, dom, 
                                     HVM_PARAM_CONSOLE_PFN, console_pfn)) ) {
             PERROR("error setting HVM param: %i", frc);
             goto out;
diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c
index 778cbde..14502c1 100644
--- a/tools/libxc/xc_domain_save.c
+++ b/tools/libxc/xc_domain_save.c
@@ -1645,8 +1645,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
 
         chunk.id = XC_SAVE_ID_HVM_IDENT_PT;
         chunk.data = 0;
-        xc_get_hvm_param(xch, dom, HVM_PARAM_IDENT_PT,
-                         (unsigned long *)&chunk.data);
+        xc_hvm_param_get(xch, dom, HVM_PARAM_IDENT_PT, &chunk.data);
 
         if ( (chunk.data != 0) &&
              wrexact(io_fd, &chunk, sizeof(chunk)) )
@@ -1657,8 +1656,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
 
         chunk.id = XC_SAVE_ID_HVM_PAGING_RING_PFN;
         chunk.data = 0;
-        xc_get_hvm_param(xch, dom, HVM_PARAM_PAGING_RING_PFN,
-                         (unsigned long *)&chunk.data);
+        xc_hvm_param_get(xch, dom, HVM_PARAM_PAGING_RING_PFN, &chunk.data);
 
         if ( (chunk.data != 0) &&
              wrexact(io_fd, &chunk, sizeof(chunk)) )
@@ -1669,8 +1667,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
 
         chunk.id = XC_SAVE_ID_HVM_ACCESS_RING_PFN;
         chunk.data = 0;
-        xc_get_hvm_param(xch, dom, HVM_PARAM_ACCESS_RING_PFN,
-                         (unsigned long *)&chunk.data);
+        xc_hvm_param_get(xch, dom, HVM_PARAM_ACCESS_RING_PFN, &chunk.data);
 
         if ( (chunk.data != 0) &&
              wrexact(io_fd, &chunk, sizeof(chunk)) )
@@ -1681,8 +1678,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
 
         chunk.id = XC_SAVE_ID_HVM_SHARING_RING_PFN;
         chunk.data = 0;
-        xc_get_hvm_param(xch, dom, HVM_PARAM_SHARING_RING_PFN,
-                         (unsigned long *)&chunk.data);
+        xc_hvm_param_get(xch, dom, HVM_PARAM_SHARING_RING_PFN, &chunk.data);
 
         if ( (chunk.data != 0) &&
              wrexact(io_fd, &chunk, sizeof(chunk)) )
@@ -1693,8 +1689,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
 
         chunk.id = XC_SAVE_ID_HVM_VM86_TSS;
         chunk.data = 0;
-        xc_get_hvm_param(xch, dom, HVM_PARAM_VM86_TSS,
-                         (unsigned long *)&chunk.data);
+        xc_hvm_param_get(xch, dom, HVM_PARAM_VM86_TSS, &chunk.data);
 
         if ( (chunk.data != 0) &&
              wrexact(io_fd, &chunk, sizeof(chunk)) )
@@ -1705,8 +1700,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
 
         chunk.id = XC_SAVE_ID_HVM_CONSOLE_PFN;
         chunk.data = 0;
-        xc_get_hvm_param(xch, dom, HVM_PARAM_CONSOLE_PFN,
-                         (unsigned long *)&chunk.data);
+        xc_hvm_param_get(xch, dom, HVM_PARAM_CONSOLE_PFN, &chunk.data);
 
         if ( (chunk.data != 0) &&
              wrexact(io_fd, &chunk, sizeof(chunk)) )
@@ -1717,8 +1711,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
 
         chunk.id = XC_SAVE_ID_HVM_ACPI_IOPORTS_LOCATION;
         chunk.data = 0;
-        xc_get_hvm_param(xch, dom, HVM_PARAM_ACPI_IOPORTS_LOCATION,
-                         (unsigned long *)&chunk.data);
+        xc_hvm_param_get(xch, dom, HVM_PARAM_ACPI_IOPORTS_LOCATION, &chunk.data);
 
         if ((chunk.data != 0) && wrexact(io_fd, &chunk, sizeof(chunk)))
         {
@@ -1728,8 +1721,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
 
         chunk.id = XC_SAVE_ID_HVM_VIRIDIAN;
         chunk.data = 0;
-        xc_get_hvm_param(xch, dom, HVM_PARAM_VIRIDIAN,
-                         (unsigned long *)&chunk.data);
+        xc_hvm_param_get(xch, dom, HVM_PARAM_VIRIDIAN, &chunk.data);
 
         if ( (chunk.data != 0) &&
              wrexact(io_fd, &chunk, sizeof(chunk)) )
@@ -1740,8 +1732,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
 
         chunk.id = XC_SAVE_ID_HVM_IOREQ_SERVER_PFN;
         chunk.data = 0;
-        xc_get_hvm_param(xch, dom, HVM_PARAM_IOREQ_SERVER_PFN,
-                         (unsigned long *)&chunk.data);
+        xc_hvm_param_get(xch, dom, HVM_PARAM_IOREQ_SERVER_PFN, &chunk.data);
 
         if ( (chunk.data != 0) &&
              wrexact(io_fd, &chunk, sizeof(chunk)) )
@@ -1752,8 +1743,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
 
         chunk.id = XC_SAVE_ID_HVM_NR_IOREQ_SERVER_PAGES;
         chunk.data = 0;
-        xc_get_hvm_param(xch, dom, HVM_PARAM_NR_IOREQ_SERVER_PAGES,
-                         (unsigned long *)&chunk.data);
+        xc_hvm_param_get(xch, dom, HVM_PARAM_NR_IOREQ_SERVER_PAGES, &chunk.data);
 
         if ( (chunk.data != 0) &&
              wrexact(io_fd, &chunk, sizeof(chunk)) )
@@ -1827,12 +1817,9 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
 
         /* Save magic-page locations. */
         memset(magic_pfns, 0, sizeof(magic_pfns));
-        xc_get_hvm_param(xch, dom, HVM_PARAM_IOREQ_PFN,
-                         (unsigned long *)&magic_pfns[0]);
-        xc_get_hvm_param(xch, dom, HVM_PARAM_BUFIOREQ_PFN,
-                         (unsigned long *)&magic_pfns[1]);
-        xc_get_hvm_param(xch, dom, HVM_PARAM_STORE_PFN,
-                         (unsigned long *)&magic_pfns[2]);
+        xc_hvm_param_get(xch, dom, HVM_PARAM_IOREQ_PFN, &magic_pfns[0]);
+        xc_hvm_param_get(xch, dom, HVM_PARAM_BUFIOREQ_PFN, &magic_pfns[1]);
+        xc_hvm_param_get(xch, dom, HVM_PARAM_STORE_PFN, &magic_pfns[2]);
         if ( wrexact(io_fd, magic_pfns, sizeof(magic_pfns)) )
         {
             PERROR("Error when writing to state file (7)");
diff --git a/tools/libxc/xc_hvm_build_x86.c b/tools/libxc/xc_hvm_build_x86.c
index ed1069b..c81a25b 100644
--- a/tools/libxc/xc_hvm_build_x86.c
+++ b/tools/libxc/xc_hvm_build_x86.c
@@ -487,19 +487,19 @@ static int setup_guest(xc_interface *xch,
     if ( xc_clear_domain_pages(xch, dom, special_pfn(0), NR_SPECIAL_PAGES) )
             goto error_out;
 
-    xc_set_hvm_param(xch, dom, HVM_PARAM_STORE_PFN,
+    xc_hvm_param_set(xch, dom, HVM_PARAM_STORE_PFN,
                      special_pfn(SPECIALPAGE_XENSTORE));
-    xc_set_hvm_param(xch, dom, HVM_PARAM_BUFIOREQ_PFN,
+    xc_hvm_param_set(xch, dom, HVM_PARAM_BUFIOREQ_PFN,
                      special_pfn(SPECIALPAGE_BUFIOREQ));
-    xc_set_hvm_param(xch, dom, HVM_PARAM_IOREQ_PFN,
+    xc_hvm_param_set(xch, dom, HVM_PARAM_IOREQ_PFN,
                      special_pfn(SPECIALPAGE_IOREQ));
-    xc_set_hvm_param(xch, dom, HVM_PARAM_CONSOLE_PFN,
+    xc_hvm_param_set(xch, dom, HVM_PARAM_CONSOLE_PFN,
                      special_pfn(SPECIALPAGE_CONSOLE));
-    xc_set_hvm_param(xch, dom, HVM_PARAM_PAGING_RING_PFN,
+    xc_hvm_param_set(xch, dom, HVM_PARAM_PAGING_RING_PFN,
                      special_pfn(SPECIALPAGE_PAGING));
-    xc_set_hvm_param(xch, dom, HVM_PARAM_ACCESS_RING_PFN,
+    xc_hvm_param_set(xch, dom, HVM_PARAM_ACCESS_RING_PFN,
                      special_pfn(SPECIALPAGE_ACCESS));
-    xc_set_hvm_param(xch, dom, HVM_PARAM_SHARING_RING_PFN,
+    xc_hvm_param_set(xch, dom, HVM_PARAM_SHARING_RING_PFN,
                      special_pfn(SPECIALPAGE_SHARING));
 
     /*
@@ -521,9 +521,9 @@ static int setup_guest(xc_interface *xch,
             goto error_out;
 
     /* Tell the domain where the pages are and how many there are */
-    xc_set_hvm_param(xch, dom, HVM_PARAM_IOREQ_SERVER_PFN,
+    xc_hvm_param_set(xch, dom, HVM_PARAM_IOREQ_SERVER_PFN,
                      ioreq_server_pfn(0));
-    xc_set_hvm_param(xch, dom, HVM_PARAM_NR_IOREQ_SERVER_PAGES,
+    xc_hvm_param_set(xch, dom, HVM_PARAM_NR_IOREQ_SERVER_PAGES,
                      NR_IOREQ_SERVER_PAGES);
 
     /*
@@ -538,7 +538,7 @@ static int setup_guest(xc_interface *xch,
         ident_pt[i] = ((i << 22) | _PAGE_PRESENT | _PAGE_RW | _PAGE_USER |
                        _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_PSE);
     munmap(ident_pt, PAGE_SIZE);
-    xc_set_hvm_param(xch, dom, HVM_PARAM_IDENT_PT,
+    xc_hvm_param_set(xch, dom, HVM_PARAM_IDENT_PT,
                      special_pfn(SPECIALPAGE_IDENT_PT) << PAGE_SHIFT);
 
     /* Insert JMP <rel32> instruction at address 0x0 to reach entry point. */
diff --git a/tools/libxc/xc_resume.c b/tools/libxc/xc_resume.c
index e423814..f48515a 100644
--- a/tools/libxc/xc_resume.c
+++ b/tools/libxc/xc_resume.c
@@ -51,8 +51,8 @@ static int modify_returncode(xc_interface *xch, uint32_t domid)
     if ( info.hvm )
     {
         /* HVM guests without PV drivers have no return code to modify. */
-        unsigned long irq = 0;
-        xc_get_hvm_param(xch, domid, HVM_PARAM_CALLBACK_IRQ, &irq);
+        uint64_t irq = 0;
+        xc_hvm_param_get(xch, domid, HVM_PARAM_CALLBACK_IRQ, &irq);
         if ( !irq )
             return 0;
 
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
index b55d857..b8fbfbe 100644
--- a/tools/libxc/xenctrl.h
+++ b/tools/libxc/xenctrl.h
@@ -1807,7 +1807,10 @@ const xc_error *xc_get_last_error(xc_interface *handle);
  */
 void xc_clear_last_error(xc_interface *xch);
 
+int xc_hvm_param_set(xc_interface *handle, domid_t dom, uint32_t param, uint64_t value);
+int xc_hvm_param_get(xc_interface *handle, domid_t dom, uint32_t param, uint64_t *value);
 
+/* Deprecated: use xc_hvm_param_set/get() instead. */
 int xc_set_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned long value);
 int xc_get_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned long *value);
 
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 9054c3b..be59f99 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -885,7 +885,7 @@ int libxl__domain_pvcontrol_available(libxl__gc *gc, uint32_t domid)
 {
     libxl_ctx *ctx = libxl__gc_owner(gc);
 
-    unsigned long pvdriver = 0;
+    uint64_t pvdriver = 0;
     int ret;
 
     libxl_domain_type domtype = libxl__domain_type(gc, domid);
@@ -895,7 +895,7 @@ int libxl__domain_pvcontrol_available(libxl__gc *gc, uint32_t domid)
     if (domtype == LIBXL_DOMAIN_TYPE_PV)
         return 1;
 
-    ret = xc_get_hvm_param(ctx->xch, domid, HVM_PARAM_CALLBACK_IRQ, &pvdriver);
+    ret = xc_hvm_param_get(ctx->xch, domid, HVM_PARAM_CALLBACK_IRQ, &pvdriver);
     if (ret<0) {
         LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting HVM callback IRQ");
         return ERROR_FAIL;
@@ -5080,7 +5080,7 @@ static int libxl__domain_s3_resume(libxl__gc *gc, int domid)
     case LIBXL_DOMAIN_TYPE_HVM:
         switch (libxl__device_model_version_running(gc, domid)) {
         case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL:
-            rc = xc_set_hvm_param(CTX->xch, domid, HVM_PARAM_ACPI_S_STATE, 0);
+            rc = xc_hvm_param_set(CTX->xch, domid, HVM_PARAM_ACPI_S_STATE, 0);
             break;
         case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
             rc = libxl__qmp_system_wakeup(gc, domid);
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index 661999c..8096d66 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -212,18 +212,18 @@ static unsigned long timer_mode(const libxl_domain_build_info *info)
 static void hvm_set_conf_params(xc_interface *handle, uint32_t domid,
                                 libxl_domain_build_info *const info)
 {
-    xc_set_hvm_param(handle, domid, HVM_PARAM_PAE_ENABLED,
+    xc_hvm_param_set(handle, domid, HVM_PARAM_PAE_ENABLED,
                     libxl_defbool_val(info->u.hvm.pae));
 #if defined(__i386__) || defined(__x86_64__)
-    xc_set_hvm_param(handle, domid, HVM_PARAM_VIRIDIAN,
+    xc_hvm_param_set(handle, domid, HVM_PARAM_VIRIDIAN,
                     libxl_defbool_val(info->u.hvm.viridian));
-    xc_set_hvm_param(handle, domid, HVM_PARAM_HPET_ENABLED,
+    xc_hvm_param_set(handle, domid, HVM_PARAM_HPET_ENABLED,
                     libxl_defbool_val(info->u.hvm.hpet));
 #endif
-    xc_set_hvm_param(handle, domid, HVM_PARAM_TIMER_MODE, timer_mode(info));
-    xc_set_hvm_param(handle, domid, HVM_PARAM_VPT_ALIGN,
+    xc_hvm_param_set(handle, domid, HVM_PARAM_TIMER_MODE, timer_mode(info));
+    xc_hvm_param_set(handle, domid, HVM_PARAM_VPT_ALIGN,
                     libxl_defbool_val(info->u.hvm.vpt_align));
-    xc_set_hvm_param(handle, domid, HVM_PARAM_NESTEDHVM,
+    xc_hvm_param_set(handle, domid, HVM_PARAM_NESTEDHVM,
                     libxl_defbool_val(info->u.hvm.nested_hvm));
 }
 
@@ -490,6 +490,7 @@ static int hvm_build_set_params(xc_interface *handle, uint32_t domid,
 {
     struct hvm_info_table *va_hvm;
     uint8_t *va_map, sum;
+    uint64_t str_mfn, cons_mfn;
     int i;
 
     va_map = xc_map_foreign_range(handle, domid,
@@ -508,10 +509,13 @@ static int hvm_build_set_params(xc_interface *handle, uint32_t domid,
     va_hvm->checksum -= sum;
     munmap(va_map, XC_PAGE_SIZE);
 
-    xc_get_hvm_param(handle, domid, HVM_PARAM_STORE_PFN, store_mfn);
-    xc_get_hvm_param(handle, domid, HVM_PARAM_CONSOLE_PFN, console_mfn);
-    xc_set_hvm_param(handle, domid, HVM_PARAM_STORE_EVTCHN, store_evtchn);
-    xc_set_hvm_param(handle, domid, HVM_PARAM_CONSOLE_EVTCHN, console_evtchn);
+    xc_hvm_param_get(handle, domid, HVM_PARAM_STORE_PFN, &str_mfn);
+    xc_hvm_param_get(handle, domid, HVM_PARAM_CONSOLE_PFN, &cons_mfn);
+    xc_hvm_param_set(handle, domid, HVM_PARAM_STORE_EVTCHN, store_evtchn);
+    xc_hvm_param_set(handle, domid, HVM_PARAM_CONSOLE_EVTCHN, console_evtchn);
+
+    *store_mfn = str_mfn;
+    *console_mfn = cons_mfn;
 
     xc_dom_gnttab_hvm_seed(handle, domid, *console_mfn, *store_mfn, console_domid, store_domid);
     return 0;
@@ -1070,15 +1074,15 @@ static void domain_suspend_callback_common(libxl__egc *egc,
                                            libxl__domain_suspend_state *dss)
 {
     STATE_AO_GC(dss->ao);
-    unsigned long hvm_s_state = 0, hvm_pvdrv = 0;
+    uint64_t hvm_s_state = 0, hvm_pvdrv = 0;
     int ret, rc;
 
     /* Convenience aliases */
     const uint32_t domid = dss->domid;
 
     if (dss->hvm) {
-        xc_get_hvm_param(CTX->xch, domid, HVM_PARAM_CALLBACK_IRQ, &hvm_pvdrv);
-        xc_get_hvm_param(CTX->xch, domid, HVM_PARAM_ACPI_S_STATE, &hvm_s_state);
+        xc_hvm_param_get(CTX->xch, domid, HVM_PARAM_CALLBACK_IRQ, &hvm_pvdrv);
+        xc_hvm_param_get(CTX->xch, domid, HVM_PARAM_ACPI_S_STATE, &hvm_s_state);
     }
 
     if ((hvm_s_state == 0) && (dss->guest_evtchn.port >= 0)) {
diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
index cb34446..314bb45 100644
--- a/tools/python/xen/lowlevel/xc/xc.c
+++ b/tools/python/xen/lowlevel/xc/xc.c
@@ -544,27 +544,27 @@ static PyObject *pyxc_linux_build(XcObject *self,
     return pyxc_error_to_exception(self->xc_handle);
 }
 
-static PyObject *pyxc_get_hvm_param(XcObject *self,
+static PyObject *pyxc_hvm_param_get(XcObject *self,
                                     PyObject *args,
                                     PyObject *kwds)
 {
     uint32_t dom;
     int param;
-    unsigned long value;
+    uint64_t value;
 
     static char *kwd_list[] = { "domid", "param", NULL }; 
     if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list,
                                       &dom, &param) )
         return NULL;
 
-    if ( xc_get_hvm_param(self->xc_handle, dom, param, &value) != 0 )
+    if ( xc_hvm_param_get(self->xc_handle, dom, param, &value) != 0 )
         return pyxc_error_to_exception(self->xc_handle);
 
-    return PyLong_FromUnsignedLong(value);
+    return PyLong_FromUnsignedLongLong(value);
 
 }
 
-static PyObject *pyxc_set_hvm_param(XcObject *self,
+static PyObject *pyxc_hvm_param_set(XcObject *self,
                                     PyObject *args,
                                     PyObject *kwds)
 {
@@ -577,7 +577,7 @@ static PyObject *pyxc_set_hvm_param(XcObject *self,
                                       &dom, &param, &value) )
         return NULL;
 
-    if ( xc_set_hvm_param(self->xc_handle, dom, param, value) != 0 )
+    if ( xc_hvm_param_set(self->xc_handle, dom, param, value) != 0 )
         return pyxc_error_to_exception(self->xc_handle);
 
     Py_INCREF(zero);
@@ -2480,7 +2480,7 @@ static PyMethodDef pyxc_methods[] = {
       "Returns: None on sucess. Raises exception on error.\n" },
 
     { "hvm_get_param", 
-      (PyCFunction)pyxc_get_hvm_param, 
+      (PyCFunction)pyxc_hvm_param_get,
       METH_VARARGS | METH_KEYWORDS, "\n"
       "get a parameter of HVM guest OS.\n"
       " dom     [int]:      Identifier of domain to build into.\n"
@@ -2488,7 +2488,7 @@ static PyMethodDef pyxc_methods[] = {
       "Returns: [long] value of the param.\n" },
 
     { "hvm_set_param", 
-      (PyCFunction)pyxc_set_hvm_param, 
+      (PyCFunction)pyxc_hvm_param_set,
       METH_VARARGS | METH_KEYWORDS, "\n"
       "set a parameter of HVM guest OS.\n"
       " dom     [int]:      Identifier of domain to build into.\n"
diff --git a/tools/tests/xen-access/xen-access.c b/tools/tests/xen-access/xen-access.c
index 0a84bd5..be4d100 100644
--- a/tools/tests/xen-access/xen-access.c
+++ b/tools/tests/xen-access/xen-access.c
@@ -223,6 +223,7 @@ xenaccess_t *xenaccess_init(xc_interface **xch_r, domid_t domain_id)
     xenaccess_t *xenaccess = 0;
     xc_interface *xch;
     int rc;
+    uint64_t val;
     unsigned long ring_pfn, mmap_pfn;
 
     xch = xc_interface_open(NULL, NULL, 0);
@@ -246,9 +247,9 @@ xenaccess_t *xenaccess_init(xc_interface **xch_r, domid_t domain_id)
     mem_event_ring_lock_init(&xenaccess->mem_event);
 
     /* Map the ring page */
-    xc_get_hvm_param(xch, xenaccess->mem_event.domain_id, 
-                        HVM_PARAM_ACCESS_RING_PFN, &ring_pfn);
-    mmap_pfn = ring_pfn;
+    xc_hvm_param_get(xch, xenaccess->mem_event.domain_id, 
+                        HVM_PARAM_ACCESS_RING_PFN, &val);
+    mmap_pfn = ring_pfn = val;
     xenaccess->mem_event.ring_page = 
         xc_map_foreign_batch(xch, xenaccess->mem_event.domain_id, 
                                 PROT_READ | PROT_WRITE, &mmap_pfn, 1);
@@ -536,9 +537,9 @@ int main(int argc, char *argv[])
     }
 
     if ( int3 )
-        rc = xc_set_hvm_param(xch, domain_id, HVM_PARAM_MEMORY_EVENT_INT3, HVMPME_mode_sync);
+        rc = xc_hvm_param_set(xch, domain_id, HVM_PARAM_MEMORY_EVENT_INT3, HVMPME_mode_sync);
     else
-        rc = xc_set_hvm_param(xch, domain_id, HVM_PARAM_MEMORY_EVENT_INT3, HVMPME_mode_disabled);
+        rc = xc_hvm_param_set(xch, domain_id, HVM_PARAM_MEMORY_EVENT_INT3, HVMPME_mode_disabled);
     if ( rc < 0 )
     {
         ERROR("Error %d setting int3 mem_event\n", rc);
@@ -556,7 +557,7 @@ int main(int argc, char *argv[])
             rc = xc_set_mem_access(xch, domain_id, XENMEM_access_rwx, ~0ull, 0);
             rc = xc_set_mem_access(xch, domain_id, XENMEM_access_rwx, 0,
                                    xenaccess->domain_info->max_pages);
-            rc = xc_set_hvm_param(xch, domain_id, HVM_PARAM_MEMORY_EVENT_INT3, HVMPME_mode_disabled);
+            rc = xc_hvm_param_set(xch, domain_id, HVM_PARAM_MEMORY_EVENT_INT3, HVMPME_mode_disabled);
 
             shutting_down = 1;
         }
diff --git a/tools/xenpaging/xenpaging.c b/tools/xenpaging/xenpaging.c
index 82c1ee4..442eed0 100644
--- a/tools/xenpaging/xenpaging.c
+++ b/tools/xenpaging/xenpaging.c
@@ -339,7 +339,7 @@ static struct xenpaging *xenpaging_init(int argc, char *argv[])
     }
 
     /* Map the ring page */
-    xc_get_hvm_param(xch, paging->mem_event.domain_id, 
+    xc_hvm_param_get(xch, paging->mem_event.domain_id, 
                         HVM_PARAM_PAGING_RING_PFN, &ring_pfn);
     mmap_pfn = ring_pfn;
     paging->mem_event.ring_page = 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 2/8] libxl: add libxl__random_bytes() which fills a buffer with random bytes
  2014-06-18 16:12 [PATCHv6 0/8] tools: rework VM Generation ID David Vrabel
  2014-06-18 16:12 ` [PATCH 1/8] libxc: add xc_hvm_param_get/set() to get/set 64-bit values David Vrabel
@ 2014-06-18 16:12 ` David Vrabel
  2014-06-18 16:12 ` [PATCH 3/8] hvmloader: add helper functions to get/set HVM params David Vrabel
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 19+ messages in thread
From: David Vrabel @ 2014-06-18 16:12 UTC (permalink / raw)
  To: xen-devel; +Cc: David Vrabel, Ian Jackson, Ian Campbell, Stefano Stabellini

The random bytes are obtained from /dev/urandom and are suitable for
almost all uses (except for generating long-lived secure keys).

Documentation suggests that /dev/urandom is widely available on Unix-like
systems (such FreeBSD and NetBSD).

A public libxl_random_bytes() (or similar) could be trivially added,
if this required in the future.

Signed-off-by: David Vrabel <david.vrabel@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 tools/libxl/libxl_internal.h |    2 ++
 tools/libxl/libxl_utils.c    |   22 ++++++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index a0d4f24..a9343e8 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -3180,6 +3180,8 @@ int libxl__uint64_parse_json(libxl__gc *gc, const libxl__json_object *o,
 int libxl__string_parse_json(libxl__gc *gc, const libxl__json_object *o,
                              char **p);
 
+int libxl__random_bytes(libxl__gc *gc, uint8_t *buf, size_t len);
+
 #endif
 
 /*
diff --git a/tools/libxl/libxl_utils.c b/tools/libxl/libxl_utils.c
index 476921e..3be01a5 100644
--- a/tools/libxl/libxl_utils.c
+++ b/tools/libxl/libxl_utils.c
@@ -1014,6 +1014,28 @@ int libxl_domid_valid_guest(uint32_t domid)
 }
 
 /*
+ * Fill @buf with @len random bytes.
+ */
+int libxl__random_bytes(libxl__gc *gc, uint8_t *buf, size_t len)
+{
+    static const char *dev = "/dev/urandom";
+    int fd;
+    int ret;
+
+    fd = open(dev, O_RDONLY | O_CLOEXEC);
+    if (fd < 0) {
+        LOGE(ERROR, "failed to open \"%s\"", dev);
+        return ERROR_FAIL;
+    }
+
+    ret = libxl_read_exactly(CTX, fd, buf, len, dev, NULL);
+
+    close(fd);
+
+    return ret;
+}
+
+/*
  * Local variables:
  * mode: C
  * c-basic-offset: 4
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 3/8] hvmloader: add helper functions to get/set HVM params
  2014-06-18 16:12 [PATCHv6 0/8] tools: rework VM Generation ID David Vrabel
  2014-06-18 16:12 ` [PATCH 1/8] libxc: add xc_hvm_param_get/set() to get/set 64-bit values David Vrabel
  2014-06-18 16:12 ` [PATCH 2/8] libxl: add libxl__random_bytes() which fills a buffer with random bytes David Vrabel
@ 2014-06-18 16:12 ` David Vrabel
  2014-06-18 16:12 ` [PATCH 4/8] hvm: add HVM_PARAM_VM_GENERATION_ID_ADDR David Vrabel
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 19+ messages in thread
From: David Vrabel @ 2014-06-18 16:12 UTC (permalink / raw)
  To: xen-devel; +Cc: David Vrabel, Ian Jackson, Ian Campbell, Stefano Stabellini

Signed-off-by: David Vrabel <david.vrabel@citrix.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 tools/firmware/hvmloader/Makefile    |    1 +
 tools/firmware/hvmloader/hvm_param.c |   36 ++++++++++++++++++++++++++++++++++
 tools/firmware/hvmloader/hvmloader.c |   14 ++-----------
 tools/firmware/hvmloader/util.h      |    9 +++++++++
 tools/firmware/hvmloader/xenbus.c    |   14 +++++--------
 5 files changed, 53 insertions(+), 21 deletions(-)
 create mode 100644 tools/firmware/hvmloader/hvm_param.c

diff --git a/tools/firmware/hvmloader/Makefile b/tools/firmware/hvmloader/Makefile
index 00ee952..46a79c5 100644
--- a/tools/firmware/hvmloader/Makefile
+++ b/tools/firmware/hvmloader/Makefile
@@ -31,6 +31,7 @@ CFLAGS += $(CFLAGS_xeninclude)
 OBJS  = hvmloader.o mp_tables.o util.o smbios.o 
 OBJS += smp.o cacheattr.o xenbus.o
 OBJS += e820.o pci.o pir.o ctype.o
+OBJS += hvm_param.o
 ifeq ($(debug),y)
 OBJS += tests.o
 endif
diff --git a/tools/firmware/hvmloader/hvm_param.c b/tools/firmware/hvmloader/hvm_param.c
new file mode 100644
index 0000000..f7d8720
--- /dev/null
+++ b/tools/firmware/hvmloader/hvm_param.c
@@ -0,0 +1,36 @@
+/*
+ * hvm_param.c: get/set HVM params.
+ *
+ * Copyright (C) 2014 Citrix Systems R&D Ltd.
+ */
+#include "util.h"
+#include "config.h"
+#include "hypercall.h"
+
+#include <xen/hvm/params.h>
+
+int hvm_param_get(uint32_t index, uint64_t *value)
+{
+    struct xen_hvm_param p;
+    int ret;
+
+    p.domid = DOMID_SELF;
+    p.index = index;
+
+    ret = hypercall_hvm_op(HVMOP_get_param, &p);
+    if (ret == 0)
+        *value = p.value;
+
+    return ret;
+}
+
+int hvm_param_set(uint32_t index, uint64_t value)
+{
+    struct xen_hvm_param p;
+
+    p.domid = DOMID_SELF;
+    p.index = index;
+    p.value = value;
+
+    return hypercall_hvm_op(HVMOP_set_param, &p);
+}
diff --git a/tools/firmware/hvmloader/hvmloader.c b/tools/firmware/hvmloader/hvmloader.c
index 1cc8cf2..7b0da38 100644
--- a/tools/firmware/hvmloader/hvmloader.c
+++ b/tools/firmware/hvmloader/hvmloader.c
@@ -176,14 +176,10 @@ static void cmos_write_memory_size(void)
 static void init_vm86_tss(void)
 {
     void *tss;
-    struct xen_hvm_param p;
 
     tss = mem_alloc(128, 128);
     memset(tss, 0, 128);
-    p.domid = DOMID_SELF;
-    p.index = HVM_PARAM_VM86_TSS;
-    p.value = virt_to_phys(tss);
-    hypercall_hvm_op(HVMOP_set_param, &p);
+    hvm_param_set(HVM_PARAM_VM86_TSS, virt_to_phys(tss));
     printf("vm86 TSS at %08lx\n", virt_to_phys(tss));
 }
 
@@ -314,12 +310,6 @@ int main(void)
 
     if ( acpi_enabled )
     {
-        struct xen_hvm_param p = {
-            .domid = DOMID_SELF,
-            .index = HVM_PARAM_ACPI_IOPORTS_LOCATION,
-            .value = 1,
-        };
-
         if ( bios->acpi_build_tables )
         {
             printf("Loading ACPI ...\n");
@@ -328,7 +318,7 @@ int main(void)
 
         acpi_enable_sci();
 
-        hypercall_hvm_op(HVMOP_set_param, &p);
+        hvm_param_set(HVM_PARAM_ACPI_IOPORTS_LOCATION, 1);
     }
 
     init_vm86_tss();
diff --git a/tools/firmware/hvmloader/util.h b/tools/firmware/hvmloader/util.h
index 9ccb905..e4b6be4 100644
--- a/tools/firmware/hvmloader/util.h
+++ b/tools/firmware/hvmloader/util.h
@@ -210,6 +210,15 @@ const char *xenstore_read(const char *path, const char *default_resp);
  */
 int xenstore_write(const char *path, const char *value);
 
+
+/* Get a HVM param.
+ */
+int hvm_param_get(uint32_t index, uint64_t *value);
+
+/* Set a HVM param.
+ */
+int hvm_param_set(uint32_t index, uint64_t value);
+
 /* Setup PCI bus */
 void pci_setup(void);
 
diff --git a/tools/firmware/hvmloader/xenbus.c b/tools/firmware/hvmloader/xenbus.c
index fe72e97..64c2176 100644
--- a/tools/firmware/hvmloader/xenbus.c
+++ b/tools/firmware/hvmloader/xenbus.c
@@ -41,21 +41,17 @@ static char payload[XENSTORE_PAYLOAD_MAX + 1];  /* Unmarshalling area */
  * Call once, before any other xenbus actions. */
 void xenbus_setup(void)
 {
-    xen_hvm_param_t param;
+    uint64_t val;
 
     /* Ask Xen where the xenbus shared page is. */
-    param.domid = DOMID_SELF;
-    param.index = HVM_PARAM_STORE_PFN;
-    if ( hypercall_hvm_op(HVMOP_get_param, &param) )
+    if ( hvm_param_get(HVM_PARAM_STORE_PFN, &val) )
         BUG();
-    rings = (void *) (unsigned long) (param.value << PAGE_SHIFT);
+    rings = (void *) (unsigned long) (val << PAGE_SHIFT);
 
     /* Ask Xen where the xenbus event channel is. */
-    param.domid = DOMID_SELF;
-    param.index = HVM_PARAM_STORE_EVTCHN;
-    if ( hypercall_hvm_op(HVMOP_get_param, &param) )
+    if ( hvm_param_get(HVM_PARAM_STORE_EVTCHN, &val) )
         BUG();
-    event = param.value;
+    event = val;
 
     printf("Xenbus rings @0x%lx, event channel %lu\n",
            (unsigned long) rings, (unsigned long) event);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 4/8] hvm: add HVM_PARAM_VM_GENERATION_ID_ADDR
  2014-06-18 16:12 [PATCHv6 0/8] tools: rework VM Generation ID David Vrabel
                   ` (2 preceding siblings ...)
  2014-06-18 16:12 ` [PATCH 3/8] hvmloader: add helper functions to get/set HVM params David Vrabel
@ 2014-06-18 16:12 ` David Vrabel
  2014-06-18 16:12 ` [PATCH 5/8] libxc, libxl, hvmloader: strip out outdated VM generation ID implementation David Vrabel
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 19+ messages in thread
From: David Vrabel @ 2014-06-18 16:12 UTC (permalink / raw)
  To: xen-devel; +Cc: David Vrabel, Ian Jackson, Ian Campbell, Stefano Stabellini

HVM_PARAM_VM_GENERATION_ID_ADDR is the guest physical address of the
VM Generation ID.  This parameter will be written by hvmloader and read
by the toolstack when updating the gen. ID (e.g., after restoring from a
snapshot).

A HVM parameter is easier for the save/restore code to work with (than
a XenStore key).

Signed-off-by: David Vrabel <david.vrabel@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
---
 xen/include/public/hvm/params.h |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/xen/include/public/hvm/params.h b/xen/include/public/hvm/params.h
index f830bdd..614ff5f 100644
--- a/xen/include/public/hvm/params.h
+++ b/xen/include/public/hvm/params.h
@@ -148,6 +148,9 @@
 #define HVM_PARAM_IOREQ_SERVER_PFN 32
 #define HVM_PARAM_NR_IOREQ_SERVER_PAGES 33
 
-#define HVM_NR_PARAMS          34
+/* Location of the VM Generation ID in guest physical address space. */
+#define HVM_PARAM_VM_GENERATION_ID_ADDR 34
+
+#define HVM_NR_PARAMS          35
 
 #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 5/8] libxc, libxl, hvmloader: strip out outdated VM generation ID implementation
  2014-06-18 16:12 [PATCHv6 0/8] tools: rework VM Generation ID David Vrabel
                   ` (3 preceding siblings ...)
  2014-06-18 16:12 ` [PATCH 4/8] hvm: add HVM_PARAM_VM_GENERATION_ID_ADDR David Vrabel
@ 2014-06-18 16:12 ` David Vrabel
  2014-06-27 12:41   ` Ian Campbell
  2014-06-18 16:12 ` [PATCH 6/8] libxl: allow a generation ID to be specified at domain creation David Vrabel
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 19+ messages in thread
From: David Vrabel @ 2014-06-18 16:12 UTC (permalink / raw)
  To: xen-devel; +Cc: David Vrabel, Ian Jackson, Ian Campbell, Stefano Stabellini

The VM generation ID support in libxc/libxl was based on a draft
specification which subsequently changed considerably.  Remove much of
the code in anticipation of introducing something simpler that
conforms to the current specification from Microsoft.

Switch to using a HVM param (HVM_PARAM_VM_GENERATION_ID_ADDR) instead
of the hvmloader/generation-id-address XenStore key.  This simplifies
save/restore since it only needs to transfer the value of this param.

There are no changes to the migration stream format or the public
libxl API.

Signed-off-by: David Vrabel <david.vrabel@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 tools/firmware/hvmloader/acpi/build.c |    9 +++----
 tools/libxc/xc_domain_restore.c       |   44 +++------------------------------
 tools/libxc/xc_domain_save.c          |    5 ++--
 tools/libxc/xenguest.h                |    8 ++----
 tools/libxl/libxl_create.c            |   12 +++------
 tools/libxl/libxl_dom.c               |   25 ++-----------------
 tools/libxl/libxl_internal.h          |    8 ++----
 tools/libxl/libxl_save_callout.c      |   10 +++-----
 tools/libxl/libxl_save_helper.c       |    9 +++----
 tools/libxl/libxl_save_msgs_gen.pl    |    3 +--
 10 files changed, 26 insertions(+), 107 deletions(-)

diff --git a/tools/firmware/hvmloader/acpi/build.c b/tools/firmware/hvmloader/acpi/build.c
index 5c42d89..1431296 100644
--- a/tools/firmware/hvmloader/acpi/build.c
+++ b/tools/firmware/hvmloader/acpi/build.c
@@ -24,6 +24,7 @@
 #include "../config.h"
 #include "../util.h"
 #include <xen/hvm/hvm_xs_strings.h>
+#include <xen/hvm/params.h>
 
 #define ACPI_MAX_SECONDARY_TABLES 16
 
@@ -362,7 +363,6 @@ static int construct_secondary_tables(unsigned long *table_ptrs,
 static int new_vm_gid(struct acpi_info *acpi_info)
 {
     uint64_t vm_gid[2], *buf;
-    char addr[12];
     const char * s;
     char *end;
 
@@ -383,12 +383,9 @@ static int new_vm_gid(struct acpi_info *acpi_info)
         return 0;
     memcpy(buf, vm_gid, sizeof(vm_gid));
 
-    /* set into ACPI table and XenStore the address */
+    /* set into ACPI table and HVM param the address */
     acpi_info->vm_gid_addr = virt_to_phys(buf);
-    if ( snprintf(addr, sizeof(addr), "0x%lx", virt_to_phys(buf))
-         >= sizeof(addr) )
-        return 0;
-    xenstore_write("hvmloader/generation-id-address", addr);
+    hvm_param_set(HVM_PARAM_VM_GENERATION_ID_ADDR, acpi_info->vm_gid_addr);
 
     return 1;
 }
diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
index 6849712..dea41a0 100644
--- a/tools/libxc/xc_domain_restore.c
+++ b/tools/libxc/xc_domain_restore.c
@@ -1431,8 +1431,7 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
                       domid_t store_domid, unsigned int console_evtchn,
                       unsigned long *console_mfn, domid_t console_domid,
                       unsigned int hvm, unsigned int pae, int superpages,
-                      int no_incr_generationid, int checkpointed_stream,
-                      unsigned long *vm_generationid_addr,
+                      int checkpointed_stream,
                       struct restore_callbacks *callbacks)
 {
     DECLARE_DOMCTL;
@@ -1657,44 +1656,9 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
                 xc_hvm_param_set(xch, dom, HVM_PARAM_VM86_TSS, pagebuf.vm86_tss);
             if ( pagebuf.console_pfn )
                 console_pfn = pagebuf.console_pfn;
-            if ( pagebuf.vm_generationid_addr ) {
-                if ( !no_incr_generationid ) {
-                    unsigned int offset;
-                    unsigned char *buf;
-                    unsigned long long generationid;
-
-                    /*
-                     * Map the VM generation id buffer and inject the new value.
-                     */
-
-                    pfn = pagebuf.vm_generationid_addr >> PAGE_SHIFT;
-                    offset = pagebuf.vm_generationid_addr & (PAGE_SIZE - 1);
-                
-                    if ( (pfn >= dinfo->p2m_size) ||
-                         (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB) )
-                    {
-                        ERROR("generation id buffer frame is bad");
-                        goto out;
-                    }
-
-                    mfn = ctx->p2m[pfn];
-                    buf = xc_map_foreign_range(xch, dom, PAGE_SIZE,
-                                               PROT_READ | PROT_WRITE, mfn);
-                    if ( buf == NULL )
-                    {
-                        ERROR("xc_map_foreign_range for generation id"
-                              " buffer failed");
-                        goto out;
-                    }
-
-                    generationid = *(unsigned long long *)(buf + offset);
-                    *(unsigned long long *)(buf + offset) = generationid + 1;
-
-                    munmap(buf, PAGE_SIZE);
-                }
-
-                *vm_generationid_addr = pagebuf.vm_generationid_addr;
-            }
+            if ( pagebuf.vm_generationid_addr )
+                xc_hvm_param_set(xch, dom, HVM_PARAM_VM_GENERATION_ID_ADDR,
+                                 pagebuf.vm_generationid_addr);
 
             break;  /* our work here is done */
         }
diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c
index 14502c1..b5a772b 100644
--- a/tools/libxc/xc_domain_save.c
+++ b/tools/libxc/xc_domain_save.c
@@ -802,8 +802,7 @@ static int save_tsc_info(xc_interface *xch, uint32_t dom, int io_fd)
 
 int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iters,
                    uint32_t max_factor, uint32_t flags,
-                   struct save_callbacks* callbacks, int hvm,
-                   unsigned long vm_generationid_addr)
+                   struct save_callbacks* callbacks, int hvm)
 {
     xc_dominfo_t info;
     DECLARE_DOMCTL;
@@ -1634,7 +1633,7 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iter
         } chunk = { 0, };
 
         chunk.id = XC_SAVE_ID_HVM_GENERATION_ID_ADDR;
-        chunk.data = vm_generationid_addr;
+        xc_hvm_param_get(xch, dom, HVM_PARAM_VM_GENERATION_ID_ADDR, &chunk.data);
 
         if ( (chunk.data != 0) &&
              wrexact(io_fd, &chunk, sizeof(chunk)) )
diff --git a/tools/libxc/xenguest.h b/tools/libxc/xenguest.h
index 1f216cd..40bbac8 100644
--- a/tools/libxc/xenguest.h
+++ b/tools/libxc/xenguest.h
@@ -86,8 +86,7 @@ struct save_callbacks {
  */
 int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iters,
                    uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */,
-                   struct save_callbacks* callbacks, int hvm,
-                   unsigned long vm_generationid_addr);
+                   struct save_callbacks* callbacks, int hvm);
 
 
 /* callbacks provided by xc_domain_restore */
@@ -113,9 +112,7 @@ struct restore_callbacks {
  * @parm hvm non-zero if this is a HVM restore
  * @parm pae non-zero if this HVM domain has PAE support enabled
  * @parm superpages non-zero to allocate guest memory with superpages
- * @parm no_incr_generationid non-zero if generation id is NOT to be incremented
  * @parm checkpointed_stream non-zero if the far end of the stream is using checkpointing
- * @parm vm_generationid_addr returned with the address of the generation id buffer
  * @parm callbacks non-NULL to receive a callback to restore toolstack
  *       specific data
  * @return 0 on success, -1 on failure
@@ -125,8 +122,7 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
                       domid_t store_domid, unsigned int console_evtchn,
                       unsigned long *console_mfn, domid_t console_domid,
                       unsigned int hvm, unsigned int pae, int superpages,
-                      int no_incr_generationid, int checkpointed_stream,
-                      unsigned long *vm_generationid_addr,
+                      int checkpointed_stream,
                       struct restore_callbacks *callbacks);
 /**
  * xc_domain_restore writes a file to disk that contains the device
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index d015cf4..cae6f53 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -584,12 +584,7 @@ retry_transaction:
                         ARRAY_SIZE(rwperm));
     }
 
-    if (info->type == LIBXL_DOMAIN_TYPE_HVM)
-        libxl__xs_mkdir(gc, t,
-            libxl__sprintf(gc, "%s/hvmloader/generation-id-address", dom_path),
-                        rwperm, ARRAY_SIZE(rwperm));
-
-                    vm_list = libxl_list_vm(ctx, &nb_vm);
+    vm_list = libxl_list_vm(ctx, &nb_vm);
     if (!vm_list) {
         LOG(ERROR, "cannot get number of running guests");
         rc = ERROR_FAIL;
@@ -903,7 +898,7 @@ static void domcreate_bootloader_done(libxl__egc *egc,
         goto out;
     }
     libxl__xc_domain_restore(egc, dcs,
-                             hvm, pae, superpages, 1);
+                             hvm, pae, superpages);
     return;
 
  out:
@@ -911,7 +906,7 @@ static void domcreate_bootloader_done(libxl__egc *egc,
 }
 
 void libxl__srm_callout_callback_restore_results(unsigned long store_mfn,
-          unsigned long console_mfn, unsigned long genidad, void *user)
+          unsigned long console_mfn, void *user)
 {
     libxl__save_helper_state *shs = user;
     libxl__domain_create_state *dcs = CONTAINER_OF(shs, *dcs, shs);
@@ -920,7 +915,6 @@ void libxl__srm_callout_callback_restore_results(unsigned long store_mfn,
 
     state->store_mfn =            store_mfn;
     state->console_mfn =          console_mfn;
-    state->vm_generationid_addr = genidad;
     shs->need_results =           0;
 }
 
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index 8096d66..a63c31c 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -279,7 +279,6 @@ int libxl__build_pre(libxl__gc *gc, uint32_t domid,
 
     state->store_port = xc_evtchn_alloc_unbound(ctx->xch, domid, state->store_domid);
     state->console_port = xc_evtchn_alloc_unbound(ctx->xch, domid, state->console_domid);
-    state->vm_generationid_addr = 0;
 
     if (info->type == LIBXL_DOMAIN_TYPE_HVM)
         hvm_set_conf_params(ctx->xch, domid, info);
@@ -297,7 +296,7 @@ int libxl__build_post(libxl__gc *gc, uint32_t domid,
     libxl_ctx *ctx = libxl__gc_owner(gc);
     char *dom_path, *vm_path;
     xs_transaction_t t;
-    char **ents, **hvm_ents;
+    char **ents;
     int i, rc;
 
     rc = libxl_domain_sched_params_set(CTX, domid, &info->sched_params);
@@ -334,13 +333,6 @@ int libxl__build_post(libxl__gc *gc, uint32_t domid,
                             ? "online" : "offline";
     }
 
-    hvm_ents = NULL;
-    if (info->type == LIBXL_DOMAIN_TYPE_HVM) {
-        hvm_ents = libxl__calloc(gc, 3, sizeof(char *));
-        hvm_ents[0] = "hvmloader/generation-id-address";
-        hvm_ents[1] = GCSPRINTF("0x%lx", state->vm_generationid_addr);
-    }
-
     dom_path = libxl__xs_get_dompath(gc, domid);
     if (!dom_path) {
         return ERROR_FAIL;
@@ -351,9 +343,6 @@ retry_transaction:
     t = xs_transaction_start(ctx->xsh);
 
     libxl__xs_writev(gc, t, dom_path, ents);
-    if (info->type == LIBXL_DOMAIN_TYPE_HVM)
-        libxl__xs_writev(gc, t, dom_path, hvm_ents);
-
     libxl__xs_writev(gc, t, dom_path, local_ents);
     libxl__xs_writev(gc, t, vm_path, vms_ents);
 
@@ -1506,7 +1495,6 @@ void libxl__domain_suspend(libxl__egc *egc, libxl__domain_suspend_state *dss)
     STATE_AO_GC(dss->ao);
     int port;
     int rc = ERROR_FAIL;
-    unsigned long vm_generationid_addr;
 
     /* Convenience aliases */
     const uint32_t domid = dss->domid;
@@ -1525,19 +1513,10 @@ void libxl__domain_suspend(libxl__egc *egc, libxl__domain_suspend_state *dss)
 
     switch (type) {
     case LIBXL_DOMAIN_TYPE_HVM: {
-        char *path;
-        char *addr;
-
-        path = GCSPRINTF("%s/hvmloader/generation-id-address",
-                              libxl__xs_get_dompath(gc, domid));
-        addr = libxl__xs_read(gc, XBT_NULL, path);
-
-        vm_generationid_addr = (addr) ? strtoul(addr, NULL, 0) : 0;
         dss->hvm = 1;
         break;
     }
     case LIBXL_DOMAIN_TYPE_PV:
-        vm_generationid_addr = 0;
         dss->hvm = 0;
         break;
     default:
@@ -1584,7 +1563,7 @@ void libxl__domain_suspend(libxl__egc *egc, libxl__domain_suspend_state *dss)
     callbacks->switch_qemu_logdirty = libxl__domain_suspend_common_switch_qemu_logdirty;
     dss->shs.callbacks.save.toolstack_save = libxl__toolstack_save;
 
-    libxl__xc_domain_save(egc, dss, vm_generationid_addr);
+    libxl__xc_domain_save(egc, dss);
     return;
 
  out:
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index a9343e8..d4f32a9 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -960,8 +960,6 @@ typedef struct {
     uint32_t console_domid;
     unsigned long console_mfn;
 
-    unsigned long vm_generationid_addr;
-
     char *saved_state;
 
     libxl__file_reference pv_kernel;
@@ -2791,8 +2789,7 @@ _hidden void libxl__domain_suspend(libxl__egc *egc,
 
 
 /* calls libxl__xc_domain_suspend_done when done */
-_hidden void libxl__xc_domain_save(libxl__egc*, libxl__domain_suspend_state*,
-                                   unsigned long vm_generationid_addr);
+_hidden void libxl__xc_domain_save(libxl__egc*, libxl__domain_suspend_state*);
 /* If rc==0 then retval is the return value from xc_domain_save
  * and errnoval is the errno value it provided.
  * If rc!=0, retval and errnoval are undefined. */
@@ -2816,8 +2813,7 @@ _hidden int libxl__toolstack_save(uint32_t domid, uint8_t **buf,
 /* calls libxl__xc_domain_restore_done when done */
 _hidden void libxl__xc_domain_restore(libxl__egc *egc,
                                       libxl__domain_create_state *dcs,
-                                      int hvm, int pae, int superpages,
-                                      int no_incr_generationid);
+                                      int hvm, int pae, int superpages);
 /* If rc==0 then retval is the return value from xc_domain_save
  * and errnoval is the errno value it provided.
  * If rc!=0, retval and errnoval are undefined. */
diff --git a/tools/libxl/libxl_save_callout.c b/tools/libxl/libxl_save_callout.c
index c35da4d..1c9f806 100644
--- a/tools/libxl/libxl_save_callout.c
+++ b/tools/libxl/libxl_save_callout.c
@@ -41,8 +41,7 @@ static void helper_done(libxl__egc *egc, libxl__save_helper_state *shs);
 /*----- entrypoints -----*/
 
 void libxl__xc_domain_restore(libxl__egc *egc, libxl__domain_create_state *dcs,
-                              int hvm, int pae, int superpages,
-                              int no_incr_generationid)
+                              int hvm, int pae, int superpages)
 {
     STATE_AO_GC(dcs->ao);
 
@@ -59,7 +58,7 @@ void libxl__xc_domain_restore(libxl__egc *egc, libxl__domain_create_state *dcs,
         state->store_port,
         state->store_domid, state->console_port,
         state->console_domid,
-        hvm, pae, superpages, no_incr_generationid,
+        hvm, pae, superpages,
         cbflags, dcs->checkpointed_stream,
     };
 
@@ -75,8 +74,7 @@ void libxl__xc_domain_restore(libxl__egc *egc, libxl__domain_create_state *dcs,
                argnums, ARRAY_SIZE(argnums));
 }
 
-void libxl__xc_domain_save(libxl__egc *egc, libxl__domain_suspend_state *dss,
-                           unsigned long vm_generationid_addr)
+void libxl__xc_domain_save(libxl__egc *egc, libxl__domain_suspend_state *dss)
 {
     STATE_AO_GC(dss->ao);
     int r, rc, toolstack_data_fd = -1;
@@ -112,7 +110,7 @@ void libxl__xc_domain_save(libxl__egc *egc, libxl__domain_suspend_state *dss,
     }
 
     const unsigned long argnums[] = {
-        dss->domid, 0, 0, dss->xcflags, dss->hvm, vm_generationid_addr,
+        dss->domid, 0, 0, dss->xcflags, dss->hvm,
         toolstack_data_fd, toolstack_data_len,
         cbflags,
     };
diff --git a/tools/libxl/libxl_save_helper.c b/tools/libxl/libxl_save_helper.c
index b259bd0..c760dd3 100644
--- a/tools/libxl/libxl_save_helper.c
+++ b/tools/libxl/libxl_save_helper.c
@@ -211,7 +211,6 @@ int main(int argc, char **argv)
         uint32_t max_factor =      strtoul(NEXTARG,0,10);
         uint32_t flags =           strtoul(NEXTARG,0,10);
         int hvm =                  atoi(NEXTARG);
-        unsigned long genidad =    strtoul(NEXTARG,0,10);
         toolstack_save_fd  =       atoi(NEXTARG);
         toolstack_save_len =       strtoul(NEXTARG,0,10);
         unsigned cbflags =         strtoul(NEXTARG,0,10);
@@ -224,7 +223,7 @@ int main(int argc, char **argv)
 
         startup("save");
         r = xc_domain_save(xch, io_fd, dom, max_iters, max_factor, flags,
-                           &helper_save_callbacks, hvm, genidad);
+                           &helper_save_callbacks, hvm);
         complete(r);
 
     } else if (!strcmp(mode,"--restore-domain")) {
@@ -238,7 +237,6 @@ int main(int argc, char **argv)
         unsigned int hvm =         strtoul(NEXTARG,0,10);
         unsigned int pae =         strtoul(NEXTARG,0,10);
         int superpages =           strtoul(NEXTARG,0,10);
-        int no_incr_genidad =      strtoul(NEXTARG,0,10);
         unsigned cbflags =         strtoul(NEXTARG,0,10);
         int checkpointed =         strtoul(NEXTARG,0,10);
         assert(!*++argv);
@@ -247,15 +245,14 @@ int main(int argc, char **argv)
 
         unsigned long store_mfn = 0;
         unsigned long console_mfn = 0;
-        unsigned long genidad = 0;
 
         startup("restore");
         r = xc_domain_restore(xch, io_fd, dom, store_evtchn, &store_mfn,
                               store_domid, console_evtchn, &console_mfn,
                               console_domid, hvm, pae, superpages,
-                              no_incr_genidad, checkpointed, &genidad,
+                              checkpointed,
                               &helper_restore_callbacks);
-        helper_stub_restore_results(store_mfn,console_mfn,genidad,0);
+        helper_stub_restore_results(store_mfn,console_mfn,0);
         complete(r);
 
     } else {
diff --git a/tools/libxl/libxl_save_msgs_gen.pl b/tools/libxl/libxl_save_msgs_gen.pl
index 745e2ac..88f4921 100755
--- a/tools/libxl/libxl_save_msgs_gen.pl
+++ b/tools/libxl/libxl_save_msgs_gen.pl
@@ -32,8 +32,7 @@ our @msgs = (
     [  7, 'rcxW',   "toolstack_restore",     [qw(uint32_t domid
                                                 BLOCK tsdata)] ],
     [  8, 'r',      "restore_results",       ['unsigned long', 'store_mfn',
-                                              'unsigned long', 'console_mfn',
-                                              'unsigned long', 'genidad'] ],
+                                              'unsigned long', 'console_mfn'] ],
     [  9, 'srW',    "complete",              [qw(int retval
                                                  int errnoval)] ],
 );
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 6/8] libxl: allow a generation ID to be specified at domain creation
  2014-06-18 16:12 [PATCHv6 0/8] tools: rework VM Generation ID David Vrabel
                   ` (4 preceding siblings ...)
  2014-06-18 16:12 ` [PATCH 5/8] libxc, libxl, hvmloader: strip out outdated VM generation ID implementation David Vrabel
@ 2014-06-18 16:12 ` David Vrabel
  2014-06-27 11:16   ` Ian Campbell
  2014-06-27 12:51   ` Ian Campbell
  2014-06-18 16:12 ` [PATCH 7/8] xl: generate a new random VM generation ID if requested David Vrabel
                   ` (2 subsequent siblings)
  8 siblings, 2 replies; 19+ messages in thread
From: David Vrabel @ 2014-06-18 16:12 UTC (permalink / raw)
  To: xen-devel; +Cc: David Vrabel, Ian Jackson, Ian Campbell, Stefano Stabellini

Toolstacks may specify a VM generation ID using the u.hvm.ms_vm_genid
field in the libxl_domain_build_info structure, when creating a
domain.

The toolstack is responsible for providing the correct generation ID
according to the Microsoft specification (e.g., generating new random
ones with libxl_ms_vm_genid_generate() as appropriate when restoring).

Although the specification requires that a ACPI Notify event is raised
if the generation ID is changed, the generation ID is never changed
when the domain is in a state to receive such an event (it's either
newly created or suspended).

Signed-off-by: David Vrabel <david.vrabel@citrix.com>
---
 tools/libxl/Makefile         |    1 +
 tools/libxl/gentest.py       |    2 +-
 tools/libxl/libxl.h          |   13 +++++
 tools/libxl/libxl_dom.c      |   10 ++++
 tools/libxl/libxl_genid.c    |  111 ++++++++++++++++++++++++++++++++++++++++++
 tools/libxl/libxl_internal.h |    6 +++
 tools/libxl/libxl_json.c     |   39 +++++++++++++++
 tools/libxl/libxl_json.h     |    1 +
 tools/libxl/libxl_types.idl  |    3 ++
 9 files changed, 185 insertions(+), 1 deletion(-)
 create mode 100644 tools/libxl/libxl_genid.c

diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index 4cfa275..6499aa7 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -77,6 +77,7 @@ LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o libxl_pci.o \
 			libxl_json.o libxl_aoutils.o libxl_numa.o \
 			libxl_save_callout.o _libxl_save_msgs_callout.o \
 			libxl_qmp.o libxl_event.o libxl_fork.o $(LIBXL_OBJS-y)
+LIBXL_OBJS += libxl_genid.o
 LIBXL_OBJS += _libxl_types.o libxl_flask.o _libxl_types_internal.o
 
 LIBXL_TESTS += timedereg
diff --git a/tools/libxl/gentest.py b/tools/libxl/gentest.py
index eb9a21b..0195bf4 100644
--- a/tools/libxl/gentest.py
+++ b/tools/libxl/gentest.py
@@ -60,7 +60,7 @@ def gen_rand_init(ty, v, indent = "    ", parent = None):
         s += "%s(%s);\n" % (ty.rand_init,
                             ty.pass_arg(v, isref=parent is None,
                                         passby=idl.PASS_BY_REFERENCE))
-    elif ty.typename in ["libxl_uuid", "libxl_mac", "libxl_hwcap"]:
+    elif ty.typename in ["libxl_uuid", "libxl_mac", "libxl_hwcap", "libxl_ms_vm_genid"]:
         s += "rand_bytes((uint8_t *)%s, sizeof(*%s));\n" % (v,v)
     elif ty.typename in ["libxl_domid", "libxl_devid"] or isinstance(ty, idl.Number):
         s += "%s = rand() %% (sizeof(%s)*8);\n" % \
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 17b8a7b..0fc6170 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -104,6 +104,11 @@
 #define LIBXL_HAVE_BUILDINFO_EVENT_CHANNELS 1
 
 /*
+ * libxl_domain_build_info has the u.hvm.ms_vm_genid field.
+ */
+#define LIBXL_HAVE_BUILDINFO_HVM_MS_VM_GENID 1
+
+/*
  * LIBXL_HAVE_DEVICE_DISK_DIRECT_IO_SAFE indicates that a
  * 'direct_io_safe' field (of boolean type) is present in
  * libxl_device_disk.
@@ -579,6 +584,11 @@ typedef struct libxl__ctx libxl_ctx;
 #define LIBXL_TIMER_MODE_DEFAULT -1
 #define LIBXL_MEMKB_DEFAULT ~0ULL
 
+#define LIBXL_MS_VM_GENID_LEN 16
+typedef struct {
+    uint8_t bytes[LIBXL_MS_VM_GENID_LEN];
+} libxl_ms_vm_genid;
+
 #include "_libxl_types.h"
 
 const libxl_version_info* libxl_get_version_info(libxl_ctx *ctx);
@@ -1189,6 +1199,9 @@ int libxl_flask_getenforce(libxl_ctx *ctx);
 int libxl_flask_setenforce(libxl_ctx *ctx, int mode);
 int libxl_flask_loadpolicy(libxl_ctx *ctx, void *policy, uint32_t size);
 
+int libxl_ms_vm_genid_generate(libxl_ctx *ctx, libxl_ms_vm_genid *id);
+bool libxl_ms_vm_genid_is_zero(const libxl_ms_vm_genid *id);
+
 /* misc */
 
 /* Each of these sets or clears the flag according to whether the
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index a63c31c..b94364f 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -314,6 +314,16 @@ int libxl__build_post(libxl__gc *gc, uint32_t domid,
     if (info->cpuid != NULL)
         libxl_cpuid_set(ctx, domid, info->cpuid);
 
+    if (info->type == LIBXL_DOMAIN_TYPE_HVM
+        && !libxl_ms_vm_genid_is_zero(&info->u.hvm.ms_vm_genid)) {
+        rc = libxl__ms_vm_genid_set(gc, domid,
+                                    &info->u.hvm.ms_vm_genid);
+        if (rc) {
+            LOG(ERROR, "Failed to set VM Generation ID");
+            return rc;
+        }
+    }
+
     ents = libxl__calloc(gc, 12 + (info->max_vcpus * 2) + 2, sizeof(char *));
     ents[0] = "memory/static-max";
     ents[1] = GCSPRINTF("%"PRId64, info->max_memkb);
diff --git a/tools/libxl/libxl_genid.c b/tools/libxl/libxl_genid.c
new file mode 100644
index 0000000..9853fa6
--- /dev/null
+++ b/tools/libxl/libxl_genid.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2014 Citrix Systems R&D Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "libxl_osdeps.h" /* must come before any other headers */
+
+#include "libxl_internal.h"
+
+#include <xenctrl.h>
+#include <xen/hvm/params.h>
+
+/*
+ * Generate a random VM generation ID.
+ *
+ * Returns ERROR_FAIL if a suitable source of random numbers is not
+ * available.
+ *
+ * See Microsoft's "Virtual Machine Generation ID" specification for
+ * further details, including when a new generation ID is required.
+ *
+ *   http://www.microsoft.com/en-us/download/details.aspx?id=30707
+ */
+int libxl_ms_vm_genid_generate(libxl_ctx *ctx, libxl_ms_vm_genid *id)
+{
+    GC_INIT(ctx);
+    int ret;
+
+    ret = libxl__random_bytes(gc, id->bytes, LIBXL_MS_VM_GENID_LEN);
+
+    GC_FREE;
+    return ret;
+}
+
+/*
+ * Is this VM generation ID all zeros?
+ */
+bool libxl_ms_vm_genid_is_zero(const libxl_ms_vm_genid *id)
+{
+    static const libxl_ms_vm_genid zero;
+
+    return memcmp(id->bytes, zero.bytes, LIBXL_MS_VM_GENID_LEN) == 0;
+}
+
+int libxl__ms_vm_genid_set(libxl__gc *gc, uint32_t domid,
+                           const libxl_ms_vm_genid *id)
+{
+    libxl_ctx *ctx = libxl__gc_owner(gc);
+    const char *dom_path;
+    uint64_t genid[2];
+    uint64_t paddr = 0;
+    int rc;
+
+    memcpy(genid, id->bytes, LIBXL_MS_VM_GENID_LEN);
+
+    /*
+     * Set the "platform/generation-id" XenStore key to pass the ID to
+     * hvmloader.
+     */
+    dom_path = libxl__xs_get_dompath(gc, domid);
+    if (!dom_path) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+    rc = libxl__xs_write(gc, XBT_NULL,
+                         GCSPRINTF("%s/platform/generation-id", dom_path),
+                         "%"PRIu64 ":%" PRIu64, genid[0], genid[1]);
+    if (rc < 0)
+        goto out;
+
+    /*
+     * Update the ID in guest memory (if available).
+     */
+    xc_hvm_param_get(ctx->xch, domid, HVM_PARAM_VM_GENERATION_ID_ADDR, &paddr);
+    if (paddr) {
+        void *vaddr;
+
+        vaddr = xc_map_foreign_range(ctx->xch, domid, XC_PAGE_SIZE,
+                                     PROT_READ | PROT_WRITE,
+                                     paddr >> XC_PAGE_SHIFT);
+        if (vaddr == NULL) {
+            rc = ERROR_FAIL;
+            goto out;
+        }
+        memcpy(vaddr + (paddr & ~XC_PAGE_MASK), genid, 2 * sizeof(*genid));
+        munmap(vaddr, XC_PAGE_SIZE);
+
+        /*
+         * The spec requires an ACPI Notify event is injected into the
+         * guest when the generation ID is changed.
+         *
+         * This is only called for domains that are suspended or newly
+         * created and they won't be in a state to receive such an
+         * event.
+         */
+    }
+
+    rc = 0;
+
+  out:
+    return rc;
+}
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index d4f32a9..2eea557 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -3086,6 +3086,10 @@ void libxl__numa_candidate_put_nodemap(libxl__gc *gc,
     libxl_bitmap_copy(CTX, &cndt->nodemap, nodemap);
 }
 
+_hidden int libxl__ms_vm_genid_set(libxl__gc *gc, uint32_t domid,
+                                   const libxl_ms_vm_genid *id);
+
+
 /* Som handy macros for defbool type. */
 #define LIBXL__DEFBOOL_DEFAULT     (0)
 #define LIBXL__DEFBOOL_FALSE       (-1)
@@ -3163,6 +3167,8 @@ int libxl_key_value_list_parse_json(libxl__gc *gc,
                                     libxl_key_value_list *p);
 int libxl_hwcap_parse_json(libxl__gc *gc, const libxl__json_object *o,
                            libxl_hwcap *p);
+int libxl_ms_vm_genid_parse_json(libxl__gc *gc, const libxl__json_object *o,
+                                 libxl_ms_vm_genid *p);
 int libxl__int_parse_json(libxl__gc *gc, const libxl__json_object *o,
                           void *p);
 int libxl__uint8_parse_json(libxl__gc *gc, const libxl__json_object *o,
diff --git a/tools/libxl/libxl_json.c b/tools/libxl/libxl_json.c
index fb9baf8..63125dc 100644
--- a/tools/libxl/libxl_json.c
+++ b/tools/libxl/libxl_json.c
@@ -377,6 +377,45 @@ int libxl_hwcap_parse_json(libxl__gc *gc, const libxl__json_object *o,
     return 0;
 }
 
+yajl_gen_status libxl_ms_vm_genid_gen_json(yajl_gen hand, libxl_ms_vm_genid *p)
+{
+    yajl_gen_status s;
+    int i;
+
+    s = yajl_gen_array_open(hand);
+    if (s != yajl_gen_status_ok)
+        return s;
+
+    for (i = 0; i < LIBXL_MS_VM_GENID_LEN; i++) {
+        s = yajl_gen_integer(hand, p->bytes[i]);
+        if (s != yajl_gen_status_ok)
+            return s;
+    }
+
+    return yajl_gen_array_close(hand);
+}
+
+int libxl_ms_vm_genid_parse_json(libxl__gc *gc, const libxl__json_object *o,
+                                 libxl_ms_vm_genid *p)
+{
+    unsigned int i;
+
+    if (!libxl__json_object_is_array(o))
+        return ERROR_FAIL;
+
+    for (i = 0; i < LIBXL_MS_VM_GENID_LEN; i++) {
+        const libxl__json_object *t;
+
+        t = libxl__json_array_get(o, i);
+        if (!t || !libxl__json_object_is_integer(t))
+            return ERROR_FAIL;
+
+        p->bytes[i] = libxl__json_object_get_integer(t);
+    }
+
+    return 0;
+}
+
 yajl_gen_status libxl__string_gen_json(yajl_gen hand,
                                        const char *p)
 {
diff --git a/tools/libxl/libxl_json.h b/tools/libxl/libxl_json.h
index e4c0f6c..af26e78 100644
--- a/tools/libxl/libxl_json.h
+++ b/tools/libxl/libxl_json.h
@@ -33,6 +33,7 @@ yajl_gen_status libxl_string_list_gen_json(yajl_gen hand, libxl_string_list *p);
 yajl_gen_status libxl_key_value_list_gen_json(yajl_gen hand,
                                               libxl_key_value_list *p);
 yajl_gen_status libxl_hwcap_gen_json(yajl_gen hand, libxl_hwcap *p);
+yajl_gen_status libxl_ms_vm_genid_gen_json(yajl_gen hand, libxl_ms_vm_genid *p);
 
 #include <_libxl_types_json.h>
 
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index f0f6e34..630698d 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -17,6 +17,7 @@ libxl_cpuid_policy_list = Builtin("cpuid_policy_list", dispose_fn="libxl_cpuid_d
 libxl_string_list = Builtin("string_list", dispose_fn="libxl_string_list_dispose", passby=PASS_BY_REFERENCE)
 libxl_key_value_list = Builtin("key_value_list", dispose_fn="libxl_key_value_list_dispose", passby=PASS_BY_REFERENCE)
 libxl_hwcap = Builtin("hwcap", passby=PASS_BY_REFERENCE)
+libxl_ms_vm_genid = Builtin("ms_vm_genid", passby=PASS_BY_REFERENCE)
 
 #
 # Specific integer types
@@ -371,6 +372,8 @@ libxl_domain_build_info = Struct("domain_build_info",[
                                        ("xen_platform_pci", libxl_defbool),
                                        ("usbdevice_list",   libxl_string_list),
                                        ("vendor_device",    libxl_vendor_device),
+                                       # See libxl_ms_vm_genid_generate()
+                                       ("ms_vm_genid",      libxl_ms_vm_genid),
                                        ])),
                  ("pv", Struct(None, [("kernel", string),
                                       ("slack_memkb", MemKB),
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 7/8] xl: generate a new random VM generation ID if requested
  2014-06-18 16:12 [PATCHv6 0/8] tools: rework VM Generation ID David Vrabel
                   ` (5 preceding siblings ...)
  2014-06-18 16:12 ` [PATCH 6/8] libxl: allow a generation ID to be specified at domain creation David Vrabel
@ 2014-06-18 16:12 ` David Vrabel
  2014-06-18 16:12 ` [PATCH 8/8] docs: update docs for the ~/platform/generation-id key David Vrabel
  2014-06-27 13:36 ` [PATCHv6 0/8] tools: rework VM Generation ID Ian Campbell
  8 siblings, 0 replies; 19+ messages in thread
From: David Vrabel @ 2014-06-18 16:12 UTC (permalink / raw)
  To: xen-devel; +Cc: David Vrabel, Ian Jackson, Ian Campbell, Stefano Stabellini

If the "generation_id" option is set in the domain configuration,
generate and set a new random VM generation ID every time a domain is
created or restored.

xl lacks the infrastructure to fully track the lifecycle of VM images
as they are snapshotted and cloned (etc) so always using a new ID is
the safe option and ensures that a new one will be used where it matters.

Signed-off-by: David Vrabel <david.vrabel@citrix.com>
---
 docs/man/xl.cfg.pod.5    |   29 +++++++++++++++++++++++++++++
 tools/libxl/xl_cmdimpl.c |   15 +++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5
index c087cbc..ff9ea77 100644
--- a/docs/man/xl.cfg.pod.5
+++ b/docs/man/xl.cfg.pod.5
@@ -936,6 +936,35 @@ number of vendor defined SMBIOS structures (type 128 - 255). Since SMBIOS
 structures do not present their overall size, each entry in the file must be
 preceded by a 32b integer indicating the size of the next structure.
 
+=item B<ms_vm_genid="OPTION">
+
+Provide a VM generation ID to the guest.
+
+The VM generation ID as a 128-bit random number that a guest may use
+to determine if the guest has been restored from an earlier snapshot
+or cloned.
+
+This is required for Microsoft Windows Server 2012 (and later) domain
+controllers.
+
+Valid options are:
+
+=over 4
+
+=item B<"generate">
+
+Generate a random VM generation ID every time the domain is created or
+restored.
+
+=item B<"none">
+
+Do not provide a VM generation ID.
+
+=back
+
+See also "Virtual Machine Generation ID" by Microsoft
+(http://www.microsoft.com/en-us/download/details.aspx?id=30707).
+
 =back 
 
 =head3 Guest Virtual Time Controls
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 64a1c77..6a67c9c 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -1021,6 +1021,21 @@ static void parse_config_data(const char *config_source,
                                &b_info->u.hvm.smbios_firmware, 0);
         xlu_cfg_replace_string(config, "acpi_firmware",
                                &b_info->u.hvm.acpi_firmware, 0);
+
+        if (!xlu_cfg_get_string(config, "ms_vm_genid", &buf, 0)) {
+            if (!strcmp(buf, "generate")) {
+                e = libxl_ms_vm_genid_generate(ctx, &b_info->u.hvm.ms_vm_genid);
+                if (e) {
+                    fprintf(stderr, "ERROR: failed to generate a VM Generation ID\n");
+                    exit(1);
+                }
+            } else if (!strcmp(buf, "none")) {
+                ;
+            } else {
+                    fprintf(stderr, "ERROR: \"ms_vm_genid\" option must be \"generate\" or \"none\"\n");
+                    exit(1);
+            }
+        }
         break;
     case LIBXL_DOMAIN_TYPE_PV:
     {
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 8/8] docs: update docs for the ~/platform/generation-id key
  2014-06-18 16:12 [PATCHv6 0/8] tools: rework VM Generation ID David Vrabel
                   ` (6 preceding siblings ...)
  2014-06-18 16:12 ` [PATCH 7/8] xl: generate a new random VM generation ID if requested David Vrabel
@ 2014-06-18 16:12 ` David Vrabel
  2014-06-27 13:36 ` [PATCHv6 0/8] tools: rework VM Generation ID Ian Campbell
  8 siblings, 0 replies; 19+ messages in thread
From: David Vrabel @ 2014-06-18 16:12 UTC (permalink / raw)
  To: xen-devel; +Cc: David Vrabel, Ian Jackson, Ian Campbell, Stefano Stabellini

Signed-off-by: David Vrabel <david.vrabel@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 docs/misc/xenstore-paths.markdown |   24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/docs/misc/xenstore-paths.markdown b/docs/misc/xenstore-paths.markdown
index 70ab7f4..ea67536 100644
--- a/docs/misc/xenstore-paths.markdown
+++ b/docs/misc/xenstore-paths.markdown
@@ -166,11 +166,6 @@ use the xenstore-based protocol instead (see ~/control/shutdown,
 below) even if the guest has advertised support for the event channel
 protocol.
 
-#### ~/hvmloader/generation-id-address = ADDRESS [r,HVM,INTERNAL]
-
-The hexadecimal representation of the address of the domain's
-"generation id".
-
 #### ~/hvmloader/allow-memory-relocate = ("1"|"0") [HVM,INTERNAL]
 
 If the default low MMIO hole (below 4GiB) is not big enough for all
@@ -193,9 +188,22 @@ Various platform properties.
 
 #### ~/platform/generation-id = INTEGER ":" INTEGER [HVM,INTERNAL]
 
-Two 64 bit values that represent the Windows Generation ID.
-Is used by the BIOS initializer to get this value.
-If not present or "0:0" (all zeroes) device will not be present to the machine.
+The lower and upper 64-bit words of the 128-bit VM Generation ID.
+
+This key is used by hvmloader to create the ACPI VM Generation ID
+device.  It initialises a 16 octet region of guest memory with this
+value.  The guest physical address of this region is saved in the
+HVM_PARAM_VM_GENERATION_ID_ADDR HVM parameter.
+
+If this key is not present, is empty, or is all-zeros ("0:0") then the
+ACPI device is not created.
+
+When restoring a guest, the toolstack may (in certain circumstances)
+need generate a new random generation ID and write it to guest memory
+at the guest physical address in HVM_PARAM_VM_GENERATION_ID_ADDR.
+
+See Microsoft's "Virtual Machine Generation ID" specification for the
+circumstances where the generation ID needs to be changed.
 
 ### Frontend device paths
 
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH 6/8] libxl: allow a generation ID to be specified at domain creation
  2014-06-18 16:12 ` [PATCH 6/8] libxl: allow a generation ID to be specified at domain creation David Vrabel
@ 2014-06-27 11:16   ` Ian Campbell
  2014-06-27 11:35     ` David Vrabel
  2014-06-27 12:51   ` Ian Campbell
  1 sibling, 1 reply; 19+ messages in thread
From: Ian Campbell @ 2014-06-27 11:16 UTC (permalink / raw)
  To: David Vrabel; +Cc: xen-devel, Ian Jackson, Stefano Stabellini

On Wed, 2014-06-18 at 17:12 +0100, David Vrabel wrote:
> Toolstacks may specify a VM generation ID using the u.hvm.ms_vm_genid
> field in the libxl_domain_build_info structure, when creating a
> domain.
> 
> The toolstack is responsible for providing the correct generation ID
> according to the Microsoft specification (e.g., generating new random
> ones with libxl_ms_vm_genid_generate() as appropriate when restoring).
> 
> Although the specification requires that a ACPI Notify event is raised
> if the generation ID is changed, the generation ID is never changed
> when the domain is in a state to receive such an event (it's either
> newly created or suspended).
> 
> Signed-off-by: David Vrabel <david.vrabel@citrix.com>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

And I intend to apply but one question:

> +bool libxl_ms_vm_genid_is_zero(const libxl_ms_vm_genid *id)
> +{
> +    static const libxl_ms_vm_genid zero;

Does this formally end up in .bss and is therefore definitely zero?

If it were global I'd have no doubt, but I'm not sure about it in this
scope.

Regardless, I'll assume for now that it is right. If not please send a
follow up with the necessary "= {0}".

Ian.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 6/8] libxl: allow a generation ID to be specified at domain creation
  2014-06-27 11:16   ` Ian Campbell
@ 2014-06-27 11:35     ` David Vrabel
  2014-06-27 12:23       ` Ian Campbell
  0 siblings, 1 reply; 19+ messages in thread
From: David Vrabel @ 2014-06-27 11:35 UTC (permalink / raw)
  To: Ian Campbell, David Vrabel; +Cc: xen-devel, Ian Jackson, Stefano Stabellini

On 27/06/14 12:16, Ian Campbell wrote:
> On Wed, 2014-06-18 at 17:12 +0100, David Vrabel wrote:
>> Toolstacks may specify a VM generation ID using the u.hvm.ms_vm_genid
>> field in the libxl_domain_build_info structure, when creating a
>> domain.
>>
>> The toolstack is responsible for providing the correct generation ID
>> according to the Microsoft specification (e.g., generating new random
>> ones with libxl_ms_vm_genid_generate() as appropriate when restoring).
>>
>> Although the specification requires that a ACPI Notify event is raised
>> if the generation ID is changed, the generation ID is never changed
>> when the domain is in a state to receive such an event (it's either
>> newly created or suspended).
>>
>> Signed-off-by: David Vrabel <david.vrabel@citrix.com>
> 
> Acked-by: Ian Campbell <ian.campbell@citrix.com>
> 
> And I intend to apply but one question:
> 
>> +bool libxl_ms_vm_genid_is_zero(const libxl_ms_vm_genid *id)
>> +{
>> +    static const libxl_ms_vm_genid zero;
> 
> Does this formally end up in .bss and is therefore definitely zero?

Yes.

K&R section A8.7 (initialization) makes no distinction between static
variables of file or function scope.

> If it were global I'd have no doubt, but I'm not sure about it in this
> scope.
> 
> Regardless, I'll assume for now that it is right. If not please send a
> follow up with the necessary "= {0}".

I almost put this on but thought someone might nitpick and say it was
unnecessary...

David

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 6/8] libxl: allow a generation ID to be specified at domain creation
  2014-06-27 11:35     ` David Vrabel
@ 2014-06-27 12:23       ` Ian Campbell
  0 siblings, 0 replies; 19+ messages in thread
From: Ian Campbell @ 2014-06-27 12:23 UTC (permalink / raw)
  To: David Vrabel; +Cc: xen-devel, Ian Jackson, Stefano Stabellini

On Fri, 2014-06-27 at 12:35 +0100, David Vrabel wrote:
> On 27/06/14 12:16, Ian Campbell wrote:
> > On Wed, 2014-06-18 at 17:12 +0100, David Vrabel wrote:
> >> Toolstacks may specify a VM generation ID using the u.hvm.ms_vm_genid
> >> field in the libxl_domain_build_info structure, when creating a
> >> domain.
> >>
> >> The toolstack is responsible for providing the correct generation ID
> >> according to the Microsoft specification (e.g., generating new random
> >> ones with libxl_ms_vm_genid_generate() as appropriate when restoring).
> >>
> >> Although the specification requires that a ACPI Notify event is raised
> >> if the generation ID is changed, the generation ID is never changed
> >> when the domain is in a state to receive such an event (it's either
> >> newly created or suspended).
> >>
> >> Signed-off-by: David Vrabel <david.vrabel@citrix.com>
> > 
> > Acked-by: Ian Campbell <ian.campbell@citrix.com>
> > 
> > And I intend to apply but one question:
> > 
> >> +bool libxl_ms_vm_genid_is_zero(const libxl_ms_vm_genid *id)
> >> +{
> >> +    static const libxl_ms_vm_genid zero;
> > 
> > Does this formally end up in .bss and is therefore definitely zero?
> 
> Yes.
> 
> K&R section A8.7 (initialization) makes no distinction between static
> variables of file or function scope.

Thanks.

> 
> > If it were global I'd have no doubt, but I'm not sure about it in this
> > scope.
> > 
> > Regardless, I'll assume for now that it is right. If not please send a
> > follow up with the necessary "= {0}".
> 
> I almost put this on but thought someone might nitpick and say it was
> unnecessary...

I would have been happy with it (as I'm now happy without). It serves a
purpose as documentation if nothing else...

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 5/8] libxc, libxl, hvmloader: strip out outdated VM generation ID implementation
  2014-06-18 16:12 ` [PATCH 5/8] libxc, libxl, hvmloader: strip out outdated VM generation ID implementation David Vrabel
@ 2014-06-27 12:41   ` Ian Campbell
  0 siblings, 0 replies; 19+ messages in thread
From: Ian Campbell @ 2014-06-27 12:41 UTC (permalink / raw)
  To: David Vrabel; +Cc: xen-devel, Ian Jackson, Stefano Stabellini

On Wed, 2014-06-18 at 17:12 +0100, David Vrabel wrote:
> The VM generation ID support in libxc/libxl was based on a draft
> specification which subsequently changed considerably.  Remove much of
> the code in anticipation of introducing something simpler that
> conforms to the current specification from Microsoft.
> 
> Switch to using a HVM param (HVM_PARAM_VM_GENERATION_ID_ADDR) instead
> of the hvmloader/generation-id-address XenStore key.  This simplifies
> save/restore since it only needs to transfer the value of this param.
> 
> There are no changes to the migration stream format or the public
> libxl API.
> 
> Signed-off-by: David Vrabel <david.vrabel@citrix.com>
> Acked-by: Ian Campbell <ian.campbell@citrix.com>

When committing I tweaked xc_nomigrate.c in the obvious way so it
continued to compile.

Ian.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 6/8] libxl: allow a generation ID to be specified at domain creation
  2014-06-18 16:12 ` [PATCH 6/8] libxl: allow a generation ID to be specified at domain creation David Vrabel
  2014-06-27 11:16   ` Ian Campbell
@ 2014-06-27 12:51   ` Ian Campbell
  1 sibling, 0 replies; 19+ messages in thread
From: Ian Campbell @ 2014-06-27 12:51 UTC (permalink / raw)
  To: David Vrabel; +Cc: xen-devel, Ian Jackson, Stefano Stabellini

On Wed, 2014-06-18 at 17:12 +0100, David Vrabel wrote:
> Toolstacks may specify a VM generation ID using the u.hvm.ms_vm_genid
> field in the libxl_domain_build_info structure, when creating a
> domain.
> 
> The toolstack is responsible for providing the correct generation ID
> according to the Microsoft specification (e.g., generating new random
> ones with libxl_ms_vm_genid_generate() as appropriate when restoring).
> 
> Although the specification requires that a ACPI Notify event is raised
> if the generation ID is changed, the generation ID is never changed
> when the domain is in a state to receive such an event (it's either
> newly created or suspended).
> 
> Signed-off-by: David Vrabel <david.vrabel@citrix.com>

I'm afraid I tried and failed to apply this because it broke the ocaml
bindings:
        
        PYTHONPATH=/local/scratch/ianc/devel/committer-i686.git/tools/ocaml/libs/xl/../../../../tools/libxl python genwrap.py \
                        /local/scratch/ianc/devel/committer-i686.git/tools/ocaml/libs/xl/../../../../tools/libxl/libxl_types.idl \
                        _libxl_types.mli.in _libxl_types.ml.in _libxl_types.inc
        Parsing /local/scratch/ianc/devel/committer-i686.git/tools/ocaml/libs/xl/../../../../tools/libxl/libxl_types.idl
        Traceback (most recent call last):
          File "genwrap.py", line 528, in <module>
            ml.write(gen_ocaml_ml(ty, False))
          File "genwrap.py", line 207, in gen_ocaml_ml
            ku, union_type = gen_ocaml_keyedunions(f.type, interface, "\t")
          File "genwrap.py", line 142, in gen_ocaml_keyedunions
            s += gen_struct(f.type)
          File "genwrap.py", line 118, in gen_struct
            x = ocaml_instance_of_field(f)
          File "genwrap.py", line 111, in ocaml_instance_of_field
            return "%s : %s" % (munge_name(name), ocaml_type_of(f.type))
          File "genwrap.py", line 81, in ocaml_type_of
            raise NotImplementedError("Unknown Builtin %s (%s)" % (ty.typename, type(ty)))
        NotImplementedError: Unknown Builtin libxl_ms_vm_genid (<class 'idl.Builtin'>)

Sadly builtins need special handling in tools/ocaml/libs/xl/genwrap.py.

Ian.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCHv6 0/8] tools: rework VM Generation ID
  2014-06-18 16:12 [PATCHv6 0/8] tools: rework VM Generation ID David Vrabel
                   ` (7 preceding siblings ...)
  2014-06-18 16:12 ` [PATCH 8/8] docs: update docs for the ~/platform/generation-id key David Vrabel
@ 2014-06-27 13:36 ` Ian Campbell
  2014-06-30 18:31   ` Aravindh Puthiyaparambil (aravindp)
  2014-07-02 19:53   ` Aravindh Puthiyaparambil (aravindp)
  8 siblings, 2 replies; 19+ messages in thread
From: Ian Campbell @ 2014-06-27 13:36 UTC (permalink / raw)
  To: David Vrabel, Aravindh Puthiyaparambil
  Cc: xen-devel, Ian Jackson, Stefano Stabellini


On Wed, 2014-06-18 at 17:12 +0100, David Vrabel wrote:
> This series reworks the VM Generation ID to a) conform to the
> published spec from Microsoft; b) simplify the save/restore code; and
> c) extend the libxl API to allow toolstacks to use this feature.
> 
> The VM Generation ID must be regenerated with a new random ID after
> certain VM operations. Since xl lacks infrastructure for tracking the
> life-cycle of snapshots and clones (etc), the safe option of always
> using a new generation ID is used.
> 
> You can download the spec from:
> 
>   http://www.microsoft.com/en-us/download/details.aspx?id=30707
> 
> Patch status ([A]cked, [M]odified, [N]ew):
> 
> M libxc: add xc_hvm_param_get/set() to get/set 64-bit
> A libxl: add libxl__random_bytes() which fills a buffer
> A hvmloader: add helper functions to get/set HVM params
> A hvm: add HVM_PARAM_VM_GENERATION_ID_ADDR
> A libxc,libxl,hvmloader: strip out outdated VM generation

I acked and applied up to here. thanks.

One hunk against tools/tests/xen-access/xen-access.c in the first patch
failed to apply and the new code in tools/libxc/xc_mem_event.c was
different enough that I didn't feel confident just fixing it. So I
dropped that hunk which was OK because the old functions remain. Perhaps
you or Aravindh (ccd) could followup with a fix?

> M libxl: allow a generation ID to be specified at domain

YHM about this one.

> M xl: generate a new random VM generation ID if requested

Acked-by: Ian Campbell <ian.campbell@citrix.com>

> A docs: update docs for the ~/platform/generation-id key

Ian.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCHv6 0/8] tools: rework VM Generation ID
  2014-06-27 13:36 ` [PATCHv6 0/8] tools: rework VM Generation ID Ian Campbell
@ 2014-06-30 18:31   ` Aravindh Puthiyaparambil (aravindp)
  2014-07-02 19:53   ` Aravindh Puthiyaparambil (aravindp)
  1 sibling, 0 replies; 19+ messages in thread
From: Aravindh Puthiyaparambil (aravindp) @ 2014-06-30 18:31 UTC (permalink / raw)
  To: Ian Campbell, David Vrabel; +Cc: xen-devel, Ian Jackson, Stefano Stabellini

>One hunk against tools/tests/xen-access/xen-access.c in the first patch failed
>to apply and the new code in tools/libxc/xc_mem_event.c was different
>enough that I didn't feel confident just fixing it. So I dropped that hunk which
>was OK because the old functions remain. Perhaps you or Aravindh (ccd)
>could followup with a fix?

I will send out a fix shortly.

Thanks,
Aravindh

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCHv6 0/8] tools: rework VM Generation ID
  2014-06-27 13:36 ` [PATCHv6 0/8] tools: rework VM Generation ID Ian Campbell
  2014-06-30 18:31   ` Aravindh Puthiyaparambil (aravindp)
@ 2014-07-02 19:53   ` Aravindh Puthiyaparambil (aravindp)
  2014-07-03  8:52     ` Ian Campbell
  1 sibling, 1 reply; 19+ messages in thread
From: Aravindh Puthiyaparambil (aravindp) @ 2014-07-02 19:53 UTC (permalink / raw)
  To: Ian Campbell, David Vrabel; +Cc: xen-devel, Ian Jackson, Stefano Stabellini

>>One hunk against tools/tests/xen-access/xen-access.c in the first patch
>>failed to apply and the new code in tools/libxc/xc_mem_event.c was
>>different enough that I didn't feel confident just fixing it. So I
>>dropped that hunk which was OK because the old functions remain.
>>Perhaps you or Aravindh (ccd) could followup with a fix?
>
>I will send out a fix shortly.

I added the following patch for the above:

diff --git a/tools/libxc/xc_mem_event.c b/tools/libxc/xc_mem_event.c
index 0b2eecb..faf1cc6 100644
--- a/tools/libxc/xc_mem_event.c
+++ b/tools/libxc/xc_mem_event.c
@@ -60,7 +60,7 @@ void *xc_mem_event_enable(xc_interface *xch, domid_t domain_id, int param,
                           uint32_t *port)
 {
     void *ring_page = NULL;
-    unsigned long pfn;
+    uint64_t pfn;
     xen_pfn_t ring_pfn, mmap_pfn;
     unsigned int op, mode;
     int rc1, rc2, saved_errno;
@@ -80,7 +80,7 @@ void *xc_mem_event_enable(xc_interface *xch, domid_t domain_id, int param,
     }
 
     /* Get the pfn of the ring page */
-    rc1 = xc_get_hvm_param(xch, domain_id, param, &pfn);
+    rc1 = xc_hvm_param_get(xch, domain_id, param, &pfn);
     if ( rc1 != 0 )
     {
         PERROR("Failed to get pfn of ring page\n");

This works for x86 Xen but when I tried cross compiling the ARM tools after following http://wiki.xenproject.org/wiki/Xen_ARM_with_Virtualization_Extensions/CrossCompiling, I am getting the following error. This happens with both armhf and arm64.

aarch64-linux-gnu-gcc  -O1 -fno-omit-frame-pointer  -g -fno-strict-aliasing -std=gnu99 -Wall -Wstrict-prototypes -Wdeclaration-after-statement -Wno-unused-but-set-variable -Wno-unused-local-typedefs   -D__XEN_TOOLS__ -MMD -MF .xc_mem_event.o.d -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -fno-optimize-sibling-calls -D_GNU_SOURCE  -I../../xen/common/libelf -Werror -Wmissing-prototypes -I. -I/xen.arm/tools/libxc/../../tools/include -pthread -include /xen.arm/tools/libxc/../../tools/config.h  -c -o xc_mem_event.o xc_mem_event.c
xc_mem_event.c: In function 'xc_mem_event_enable':
xc_mem_event.c:84:5: error: implicit declaration of function 'xc_hvm_param_get' [-Werror=implicit-function-declaration]
     rc1 = xc_hvm_param_get(xch, domain_id, param, &pfn);
     ^
cc1: all warnings being treated as errors
make[4]: *** [xc_mem_event.o] Error 1
make[4]: Leaving directory `/xen.arm/tools/libxc'
make[3]: *** [build] Error 2
make[3]: Leaving directory `/xen.arm/tools/libxc'
make[2]: *** [subdir-install-libxc] Error 2
make[2]: Leaving directory `/xen.arm/tools'
make[1]: *** [subdirs-install] Error 2
make[1]: Leaving directory `/xen.arm/tools'
make: *** [install-tools] Error 2

I cannot figure out why xc_get_hvm_param() works here but xc_hvm_param_get() does not. If I explicitly add the function prototype to xc_mem_event.c the compile goes through. But this shouldn’t be needed as "xc_private.h" is included which includes "xenctrl.h" where the prototype is present. So I don't think this is the right thing to do. Could this be an issue with just my build env? Any idea what is going on?

Thanks,
Aravindh

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCHv6 0/8] tools: rework VM Generation ID
  2014-07-02 19:53   ` Aravindh Puthiyaparambil (aravindp)
@ 2014-07-03  8:52     ` Ian Campbell
  2014-07-03 18:12       ` Aravindh Puthiyaparambil (aravindp)
  0 siblings, 1 reply; 19+ messages in thread
From: Ian Campbell @ 2014-07-03  8:52 UTC (permalink / raw)
  To: Aravindh Puthiyaparambil (aravindp)
  Cc: xen-devel, Ian Jackson, David Vrabel, Stefano Stabellini


On Wed, 2014-07-02 at 19:53 +0000, Aravindh Puthiyaparambil (aravindp) 
> I cannot figure out why xc_get_hvm_param() works here but
> xc_hvm_param_get() does not. If I explicitly add the function
> prototype to xc_mem_event.c the compile goes through. But this
> shouldn’t be needed as "xc_private.h" is included which includes
> "xenctrl.h" where the prototype is present. So I don't think this is
> the right thing to do. Could this be an issue with just my build env?
> Any idea what is going on?

Very odd. Nothing around this ought to be conditional and
xc_hvm_param_get works for everything else on ARM it seems.

Plus xc_get_hvm_param and xc_hvm_param_get are defined right next to
each other with no cpp magic anywhere near them.

My guess would be that the compiler is picking up some system version of
xenctrl.h instead of the one in tools/libxc. It really shouldn't be
though!

I cross built your patch on current staging and it was OK for me, so I
guess it is something strange in your chroot. I think I'd start from
"find $chroot -name xenctrl.h" and work from there.

But, given that it works for me and it looks sensible I don't mind if
you send it untested on ARM this time around.

Ian.


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCHv6 0/8] tools: rework VM Generation ID
  2014-07-03  8:52     ` Ian Campbell
@ 2014-07-03 18:12       ` Aravindh Puthiyaparambil (aravindp)
  0 siblings, 0 replies; 19+ messages in thread
From: Aravindh Puthiyaparambil (aravindp) @ 2014-07-03 18:12 UTC (permalink / raw)
  To: Ian Campbell; +Cc: xen-devel, Ian Jackson, David Vrabel, Stefano Stabellini

>Very odd. Nothing around this ought to be conditional and
>xc_hvm_param_get works for everything else on ARM it seems.
>
>Plus xc_get_hvm_param and xc_hvm_param_get are defined right next to
>each other with no cpp magic anywhere near them.
>
>My guess would be that the compiler is picking up some system version of
>xenctrl.h instead of the one in tools/libxc. It really shouldn't be though!
>
>I cross built your patch on current staging and it was OK for me, so I guess it is
>something strange in your chroot. I think I'd start from "find $chroot -name
>xenctrl.h" and work from there.
>
>But, given that it works for me and it looks sensible I don't mind if you send it
>untested on ARM this time around.

I blew my chroot away and rebuilt it before I saw your reply. I am now able to compile. Sorry for the noise.

Aravindh

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2014-07-03 18:12 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-18 16:12 [PATCHv6 0/8] tools: rework VM Generation ID David Vrabel
2014-06-18 16:12 ` [PATCH 1/8] libxc: add xc_hvm_param_get/set() to get/set 64-bit values David Vrabel
2014-06-18 16:12 ` [PATCH 2/8] libxl: add libxl__random_bytes() which fills a buffer with random bytes David Vrabel
2014-06-18 16:12 ` [PATCH 3/8] hvmloader: add helper functions to get/set HVM params David Vrabel
2014-06-18 16:12 ` [PATCH 4/8] hvm: add HVM_PARAM_VM_GENERATION_ID_ADDR David Vrabel
2014-06-18 16:12 ` [PATCH 5/8] libxc, libxl, hvmloader: strip out outdated VM generation ID implementation David Vrabel
2014-06-27 12:41   ` Ian Campbell
2014-06-18 16:12 ` [PATCH 6/8] libxl: allow a generation ID to be specified at domain creation David Vrabel
2014-06-27 11:16   ` Ian Campbell
2014-06-27 11:35     ` David Vrabel
2014-06-27 12:23       ` Ian Campbell
2014-06-27 12:51   ` Ian Campbell
2014-06-18 16:12 ` [PATCH 7/8] xl: generate a new random VM generation ID if requested David Vrabel
2014-06-18 16:12 ` [PATCH 8/8] docs: update docs for the ~/platform/generation-id key David Vrabel
2014-06-27 13:36 ` [PATCHv6 0/8] tools: rework VM Generation ID Ian Campbell
2014-06-30 18:31   ` Aravindh Puthiyaparambil (aravindp)
2014-07-02 19:53   ` Aravindh Puthiyaparambil (aravindp)
2014-07-03  8:52     ` Ian Campbell
2014-07-03 18:12       ` Aravindh Puthiyaparambil (aravindp)

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.