All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Vrabel <david.vrabel@citrix.com>
To: xen-devel@lists.xenproject.org
Cc: David Vrabel <david.vrabel@citrix.com>,
	Ian Jackson <ian.jackson@eu.citrix.com>,
	Ian Campbell <ian.campbell@citrix.com>,
	Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Subject: [PATCH 6/8] libxl: allow a generation ID to be specified at domain creation
Date: Wed, 18 Jun 2014 17:12:55 +0100	[thread overview]
Message-ID: <1403107977-13795-7-git-send-email-david.vrabel@citrix.com> (raw)
In-Reply-To: <1403107977-13795-1-git-send-email-david.vrabel@citrix.com>

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

  parent reply	other threads:[~2014-06-18 16:13 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 ` David Vrabel [this message]
2014-06-27 11:16   ` [PATCH 6/8] libxl: allow a generation ID to be specified at domain creation 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)
  -- strict thread matches above, loose matches on Subject: below --
2014-06-12 15:04 [PATCHv5 " David Vrabel
2014-06-12 15:04 ` [PATCH 6/8] libxl: allow a generation ID to be specified at domain creation David Vrabel
2014-06-18  5:18   ` Hongyang Yang
2014-06-18  9:38     ` David Vrabel
2014-06-18  9:39       ` Ian Campbell
2014-06-18 11:33   ` Ian Campbell
2014-06-18 12:09     ` David Vrabel
2014-06-18 12:25       ` Ian Campbell
2014-06-18 13:22         ` David Vrabel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1403107977-13795-7-git-send-email-david.vrabel@citrix.com \
    --to=david.vrabel@citrix.com \
    --cc=ian.campbell@citrix.com \
    --cc=ian.jackson@eu.citrix.com \
    --cc=stefano.stabellini@eu.citrix.com \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.