|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 6/8] libxl: allow a generation ID to be specified at domain creation
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@xxxxxxxxxx>
---
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
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |