Skip to contentSkip to conversation

Add support for a VM generation ID virtual device

PATCH New Paul Durrant 2 participants 12 messages Nov 28, 2011

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Add support for a VM generation ID virtual device

The following patch series adds support for a VM generation ID virtual device.
The basic requirements of this device are as follows:

- It must be exposed somewhere in ACPI namespace with a _CID of "VM_Gen_Counter".
- It must also include a _DDN of "VM_Gen_Counter".
- It must contain a _HID object but no particular value is required.
- It must expose a package called ADDR which evaluates to two integers; the first being the low order 32-bits of a guest physical address (GPA), the second by the high order 32-bits of the GPA. This GPA is the address of an 8-byte aligned 8-byte buffer containing the VM generation ID.
This buffer must not be in ranges supported as AddressRangeMemory or AddressRangeACPI and must not be mapped by any PTE with caching disabled.

The semantics of the VM generation ID itself are left up to the tools but it must be possible to change it each time the VM is booted, migrated, or restored from a saved image.

Patch 1 adds the device and an acpi_info field to allow population of the ADDR package.
Patch 2 adds ctype infrastructure to hvloader in preparation for... Patch 3 adds all the code to plumb the value of a new 'generation_id' parameter in the VM config through to the VM generation id buffer at VM boot time.
Patch 4 adds code to do the same at VM migrate or restore time. Patch 5 is some code tidy-up facilitated by the patch 4.

#1 lore raw

PATCH 1/1 Add an ACPI device exposing a package called ADDR, evaluating to two

# HG changeset patch
# User Paul Durrant <[email protected]>
# Date 1322482488 0
# Node ID 346b54217c4c3fcdebfde41d636d0ec1c11a7672
# Parent a9c67c2daf4b0181ef2581471ea920eecb495616
Add an ACPI device exposing a package called ADDR, evaluating to two integers, and with _CID and _DDN set to "VM_Gen_Counter".

tools/firmware/hvmloader/acpi/build.c +1 -0
diff -r a9c67c2daf4b -r 346b54217c4c tools/firmware/hvmloader/acpi/build.c
@@ -47,6 +47,7 @@ struct acpi_info {
     uint32_t pci_min, pci_len;  /* 4, 8 - PCI I/O hole boundaries */
     uint32_t madt_csum_addr;    /* 12   - Address of MADT checksum */
     uint32_t madt_lapic0_addr;  /* 16   - Address of first MADT LAPIC struct */
+    uint32_t vm_gid_addr;       /* 20   - Address of VM generation id buffer */
 };
 
 /* Number of processor objects in the chosen DSDT. */
tools/firmware/hvmloader/acpi/dsdt.asl +27 -1
diff -r a9c67c2daf4b -r 346b54217c4c tools/firmware/hvmloader/acpi/dsdt.asl
@@ -55,7 +55,8 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, 
            PMIN, 32,
            PLEN, 32,
            MSUA, 32, /* MADT checksum address */
-           MAPA, 32  /* MADT LAPIC0 address */
+           MAPA, 32, /* MADT LAPIC0 address */
+           VGIA, 32  /* VM generation id address */
        }
 
         /* Fix HCT test for 0x400 pci memory:
@@ -396,6 +397,31 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, 
                         IRQNoFlags () {7}
                     })
                 } 
+
+                Device(VGID) {
+                    Name(_HID, "ACPI0001")
+                    Name(_UID, 0x00)
+                    Name(_CID, "VM_Gen_Counter")
+                    Name(_DDN, "VM_Gen_Counter")
+                    Method(_STA, 0, NotSerialized)
+                    {
+                        If(LEqual(\_SB.VGIA, 0x00000000)) {
+                            Return(0x00)
+                        } Else {
+                            Return(0x0F)
+                        }
+                    }
+                    Name(PKG, Package ()
+                    {
+                        0x00000000,
+                        0x00000000
+                    })
+                    Method(ADDR, 0, NotSerialized)
+                    {
+                        Store(\_SB.VGIA, Index(PKG, 0))
+                        Return(PKG)
+                    }
+                }
             }
         }
     }
#2 lore raw

PATCH 1/1 Add 'ctype' infrastructure to hvmloader

In reply to Paul Durrant

# HG changeset patch
# User Paul Durrant <[email protected]> # Date 1322482488 0
# Node ID b383a1053d1d5e598bb39923eee8cec57e5666e9 # Parent 346b54217c4c3fcdebfde41d636d0ec1c11a7672 Add 'ctype' infrastructure to hvmloader.

tools/firmware/hvmloader/Makefile +1 -1
diff -r 346b54217c4c -r b383a1053d1d tools/firmware/hvmloader/Makefile
@@ -30,7 +30,7 @@ CFLAGS += $(CFLAGS_xeninclude)
 
 OBJS  = hvmloader.o mp_tables.o util.o smbios.o 
 OBJS += 32bitbios_support.o smp.o cacheattr.o xenbus.o
-OBJS += e820.o pci.o pir.o
+OBJS += e820.o pci.o pir.o ctype.o
 ifeq ($(debug),y)
 OBJS += tests.o
 endif
tools/firmware/hvmloader/ctype.c new file +27 -0
diff -r 346b54217c4c -r b383a1053d1d tools/firmware/hvmloader/ctype.c
@@ -0,0 +1,27 @@
+#include "ctype.h"
+
+const unsigned char _ctype[] = {
+_C,_C,_C,_C,_C,_C,_C,_C,                        /* 0-7 */
+_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C,         /* 8-15 */
+_C,_C,_C,_C,_C,_C,_C,_C,                        /* 16-23 */
+_C,_C,_C,_C,_C,_C,_C,_C,                        /* 24-31 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,                    /* 32-39 */
+_P,_P,_P,_P,_P,_P,_P,_P,                        /* 40-47 */
+_D,_D,_D,_D,_D,_D,_D,_D,                        /* 48-55 */
+_D,_D,_P,_P,_P,_P,_P,_P,                        /* 56-63 */
+_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U,      /* 64-71 */
+_U,_U,_U,_U,_U,_U,_U,_U,                        /* 72-79 */
+_U,_U,_U,_U,_U,_U,_U,_U,                        /* 80-87 */
+_U,_U,_U,_P,_P,_P,_P,_P,                        /* 88-95 */
+_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L,      /* 96-103 */
+_L,_L,_L,_L,_L,_L,_L,_L,                        /* 104-111 */
+_L,_L,_L,_L,_L,_L,_L,_L,                        /* 112-119 */
+_L,_L,_L,_P,_P,_P,_P,_C,                        /* 120-127 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,                /* 128-143 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,                /* 144-159 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,   /* 160-175 */
+_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,       /* 176-191 */
+_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,       /* 192-207 */
+_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L,       /* 208-223 */
+_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,       /* 224-239 */
+_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L};      /* 240-255 */
tools/firmware/hvmloader/ctype.h new file +30 -0
diff -r 346b54217c4c -r b383a1053d1d tools/firmware/hvmloader/ctype.h
@@ -0,0 +1,30 @@
+#ifndef __HVMLOADER_CTYPE_H__
+#define __HVMLOADER_CTYPE_H__
+
+#define _U	0x01	/* upper */
+#define _L	0x02	/* lower */
+#define _D	0x04	/* digit */
+#define _C	0x08	/* cntrl */
+#define _P	0x10	/* punct */
+#define _S	0x20	/* white space (space/lf/tab) */
+#define _X	0x40	/* hex digit */
+#define _SP	0x80	/* hard space (0x20) */
+
+extern const unsigned char _ctype[];
+
+#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
+
+#define isalnum(c)	((__ismask(c)&(_U|_L|_D)) != 0)
+#define isalpha(c)	((__ismask(c)&(_U|_L)) != 0)
+#define iscntrl(c)	((__ismask(c)&(_C)) != 0)
+#define isdigit(c)	((__ismask(c)&(_D)) != 0)
+#define isgraph(c)	((__ismask(c)&(_P|_U|_L|_D)) != 0)
+#define islower(c)	((__ismask(c)&(_L)) != 0)
+#define isprint(c)	((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
+#define ispunct(c)	((__ismask(c)&(_P)) != 0)
+#define isspace(c)	((__ismask(c)&(_S)) != 0)
+#define isupper(c)	((__ismask(c)&(_U)) != 0)
+#define isxdigit(c)	((__ismask(c)&(_D|_X)) != 0)
+
+#endif /* __HVMLOADER_CTYPE_H__ */
+
tools/firmware/hvmloader/util.c +1 -0
diff -r 346b54217c4c -r b383a1053d1d tools/firmware/hvmloader/util.c
@@ -21,6 +21,7 @@
 #include "util.h"
 #include "config.h"
 #include "hypercall.h"
+#include "ctype.h"
 #include <stdint.h>
 #include <xen/xen.h>
 #include <xen/memory.h>
tools/firmware/hvmloader/util.h +0 -2
diff -r 346b54217c4c -r b383a1053d1d tools/firmware/hvmloader/util.h
@@ -225,8 +225,6 @@ void perform_tests(void);
 #define perform_tests() ((void)0)
 #endif
 
-#define isdigit(c) ((c) >= '0' && (c) <= '9')
-
 extern char _start[], _end[];
 
 #endif /* __HVMLOADER_UTIL_H__ */
#3 lore raw

Re: [PATCH 2 of 5] Add 'ctype' infrastructure to hvmloader

Quoted 6 lines · Paul Durrant

# HG changeset patch
# User Paul Durrant <[email protected]> # Date 1322482488 0
# Node ID b383a1053d1d5e598bb39923eee8cec57e5666e9 # Parent 346b54217c4c3fcdebfde41d636d0ec1c11a7672 Add 'ctype' infrastructure to hvmloader.

Where did this ctype code come from? Is it appropriately licensed?

Cheers,

Tim

Quoted 107 lines

diff -r 346b54217c4c -r b383a1053d1d tools/firmware/hvmloader/Makefile

tools/firmware/hvmloader/Makefile +1 -1
@@ -30,7 +30,7 @@ CFLAGS += $(CFLAGS_xeninclude)
 
 OBJS  = hvmloader.o mp_tables.o util.o smbios.o 
 OBJS += 32bitbios_support.o smp.o cacheattr.o xenbus.o
-OBJS += e820.o pci.o pir.o
+OBJS += e820.o pci.o pir.o ctype.o
 ifeq ($(debug),y)
 OBJS += tests.o
 endif

diff -r 346b54217c4c -r b383a1053d1d tools/firmware/hvmloader/ctype.c

tools/firmware/hvmloader/ctype.c new file +27 -0
@@ -0,0 +1,27 @@
+#include "ctype.h"
+
+const unsigned char _ctype[] = {
+_C,_C,_C,_C,_C,_C,_C,_C,                        /* 0-7 */
+_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C,         /* 8-15 */
+_C,_C,_C,_C,_C,_C,_C,_C,                        /* 16-23 */
+_C,_C,_C,_C,_C,_C,_C,_C,                        /* 24-31 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,                    /* 32-39 */
+_P,_P,_P,_P,_P,_P,_P,_P,                        /* 40-47 */
+_D,_D,_D,_D,_D,_D,_D,_D,                        /* 48-55 */
+_D,_D,_P,_P,_P,_P,_P,_P,                        /* 56-63 */
+_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U,      /* 64-71 */
+_U,_U,_U,_U,_U,_U,_U,_U,                        /* 72-79 */
+_U,_U,_U,_U,_U,_U,_U,_U,                        /* 80-87 */
+_U,_U,_U,_P,_P,_P,_P,_P,                        /* 88-95 */
+_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L,      /* 96-103 */
+_L,_L,_L,_L,_L,_L,_L,_L,                        /* 104-111 */
+_L,_L,_L,_L,_L,_L,_L,_L,                        /* 112-119 */
+_L,_L,_L,_P,_P,_P,_P,_C,                        /* 120-127 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,                /* 128-143 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,                /* 144-159 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,   /* 160-175 */
+_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,       /* 176-191 */
+_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,       /* 192-207 */
+_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L,       /* 208-223 */
+_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,       /* 224-239 */
+_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L};      /* 240-255 */

diff -r 346b54217c4c -r b383a1053d1d tools/firmware/hvmloader/ctype.h

tools/firmware/hvmloader/ctype.h new file +30 -0
@@ -0,0 +1,30 @@
+#ifndef __HVMLOADER_CTYPE_H__
+#define __HVMLOADER_CTYPE_H__
+
+#define _U	0x01	/* upper */
+#define _L	0x02	/* lower */
+#define _D	0x04	/* digit */
+#define _C	0x08	/* cntrl */
+#define _P	0x10	/* punct */
+#define _S	0x20	/* white space (space/lf/tab) */
+#define _X	0x40	/* hex digit */
+#define _SP	0x80	/* hard space (0x20) */
+
+extern const unsigned char _ctype[];
+
+#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
+
+#define isalnum(c)	((__ismask(c)&(_U|_L|_D)) != 0)
+#define isalpha(c)	((__ismask(c)&(_U|_L)) != 0)
+#define iscntrl(c)	((__ismask(c)&(_C)) != 0)
+#define isdigit(c)	((__ismask(c)&(_D)) != 0)
+#define isgraph(c)	((__ismask(c)&(_P|_U|_L|_D)) != 0)
+#define islower(c)	((__ismask(c)&(_L)) != 0)
+#define isprint(c)	((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
+#define ispunct(c)	((__ismask(c)&(_P)) != 0)
+#define isspace(c)	((__ismask(c)&(_S)) != 0)
+#define isupper(c)	((__ismask(c)&(_U)) != 0)
+#define isxdigit(c)	((__ismask(c)&(_D|_X)) != 0)
+
+#endif /* __HVMLOADER_CTYPE_H__ */
+

diff -r 346b54217c4c -r b383a1053d1d tools/firmware/hvmloader/util.c

tools/firmware/hvmloader/util.c +1 -0
@@ -21,6 +21,7 @@
 #include "util.h"
 #include "config.h"
 #include "hypercall.h"
+#include "ctype.h"
 #include <stdint.h>
 #include <xen/xen.h>
 #include <xen/memory.h>

diff -r 346b54217c4c -r b383a1053d1d tools/firmware/hvmloader/util.h

tools/firmware/hvmloader/util.h +0 -2
@@ -225,8 +225,6 @@ void perform_tests(void);
 #define perform_tests() ((void)0)
 #endif
 
-#define isdigit(c) ((c) >= '0' && (c) <= '9')
-
 extern char _start[], _end[];
 
 #endif /* __HVMLOADER_UTIL_H__ */

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel

#4 lore raw

Re: [PATCH 2 of 5] Add 'ctype' infrastructure to hvmloader

Quoted 9 lines

-----Original Message-----
From: Tim Deegan [mailto:[email protected]]
Sent: 28 November 2011 12:28
To: Paul Durrant
Cc: [email protected]
Subject: Re: [Xen-devel] [PATCH 2 of 5] Add 'ctype' infrastructure to hvmloader

At 12:15 +0000 on 28 Nov (1322482534), Paul Durrant wrote:

Quoted 9 lines
Quoted 2 lines

# HG changeset patch
# User Paul Durrant <[email protected]> # Date 1322482488 0

#

Quoted 3 lines

Node ID b383a1053d1d5e598bb39923eee8cec57e5666e9 # Parent 346b54217c4c3fcdebfde41d636d0ec1c11a7672 Add 'ctype' infrastructure to hvmloader.

Where did this ctype code come from? Is it appropriately licensed?

Tim,

It's the minios one that's already in the Xen mercurial repo. which IIRC is BSD licensed, so I thought it was a reasonably safe one to grab.

Paul

#5 lore raw

PATCH 1/1 Allocate an 8 byte buffer to contain the VM generation id and populate it

In reply to Paul Durrant

# HG changeset patch
# User Paul Durrant <[email protected]>
# Date 1322482488 0
# Node ID 3886d406c13aa66b2af123d52a1bef8b6f41d144
# Parent b383a1053d1d5e598bb39923eee8cec57e5666e9
Allocate an 8 byte buffer to contain the VM generation id and populate it at boot time with a value read from "platform/generation_id". Also add code to libxl to populate this xenstore key with the value of a new 'generation_id' parameter in the VM config file.
Populate the ADDR package of VM_Gen_Counter ACPI device such that the first integer evaluates to the low order 32 bits of the buffer address and the second integer evaluates to the high order 32 bits of the buffer address.

tools/firmware/hvmloader/acpi/build.c +19 -0
diff -r b383a1053d1d -r 3886d406c13a tools/firmware/hvmloader/acpi/build.c
@@ -297,6 +297,20 @@ static int construct_secondary_tables(un
     return nr_tables;
 }
 
+unsigned long new_vm_gid(void)
+{
+    uint64_t gid;
+    unsigned char *buf;
+
+    buf = mem_alloc(8, 8);
+    if (!buf) return 0;
+
+    gid = strtoll(xenstore_read("platform/generation-id", "0"), NULL, 0);
+    *(uint64_t *)buf = gid;
+
+    return virt_to_phys(buf);    
+}
+
 void acpi_build_tables(struct acpi_config *config, unsigned int physical)
 {
     struct acpi_info *acpi_info;
@@ -309,6 +323,7 @@ void acpi_build_tables(struct acpi_confi
     unsigned char       *dsdt;
     unsigned long        secondary_tables[16];
     int                  nr_secondaries, i;
+    unsigned long        vm_gid_addr;
 
     /* Allocate and initialise the acpi info area. */
     mem_hole_populate_ram(ACPI_INFO_PHYSICAL_ADDRESS >> PAGE_SHIFT, 1);
@@ -421,12 +436,16 @@ void acpi_build_tables(struct acpi_confi
                  offsetof(struct acpi_20_rsdp, extended_checksum),
                  sizeof(struct acpi_20_rsdp));
 
+    vm_gid_addr = new_vm_gid();
+    if (!vm_gid_addr) goto oom;
+
     acpi_info->com1_present = uart_exists(0x3f8);
     acpi_info->com2_present = uart_exists(0x2f8);
     acpi_info->lpt1_present = lpt_exists(0x378);
     acpi_info->hpet_present = hpet_exists(ACPI_HPET_ADDRESS);
     acpi_info->pci_min = pci_mem_start;
     acpi_info->pci_len = pci_mem_end - pci_mem_start;
+    acpi_info->vm_gid_addr = vm_gid_addr;
 
     return;
 
tools/firmware/hvmloader/util.c +72 -0

78 lines not on this page · raw message

tools/firmware/hvmloader/util.h +1 -0
diff -r b383a1053d1d -r 3886d406c13a tools/firmware/hvmloader/util.h
@@ -152,6 +152,7 @@ int strncmp(const char *s1, const char *
 char *strcpy(char *dest, const char *src);
 char *strncpy(char *dest, const char *src, unsigned n);
 unsigned strlen(const char *s);
+long long strtoll(const char *s, char **end, int base);
 int memcmp(const void *s1, const void *s2, unsigned n);
 void *memcpy(void *dest, const void *src, unsigned n);
 void *memmove(void *dest, const void *src, unsigned n);
tools/libxl/libxl_create.c +4 -1
diff -r b383a1053d1d -r 3886d406c13a tools/libxl/libxl_create.c
@@ -101,6 +101,7 @@ int libxl_init_build_info(libxl_ctx *ctx
         b_info->u.hvm.vpt_align = 1;
         b_info->u.hvm.timer_mode = 1;
         b_info->u.hvm.nested_hvm = 0;
+        b_info->u.hvm.generation_id = 0;
         break;
     case LIBXL_DOMAIN_TYPE_PV:
         b_info->u.pv.slack_memkb = 8 * 1024;
@@ -191,13 +192,15 @@ int libxl__domain_build(libxl__gc *gc,
         vments[4] = "start_time";
         vments[5] = libxl__sprintf(gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
 
-        localents = libxl__calloc(gc, 7, sizeof(char *));
+        localents = libxl__calloc(gc, 9, sizeof(char *));
         localents[0] = "platform/acpi";
         localents[1] = (info->u.hvm.acpi) ? "1" : "0";
         localents[2] = "platform/acpi_s3";
         localents[3] = (info->u.hvm.acpi_s3) ? "1" : "0";
         localents[4] = "platform/acpi_s4";
         localents[5] = (info->u.hvm.acpi_s4) ? "1" : "0";
+        localents[6] = "platform/generation-id";
+        localents[7] = libxl__sprintf(gc, "0x%llx", info->u.hvm.generation_id);
 
         break;
     case LIBXL_DOMAIN_TYPE_PV:
tools/libxl/libxl_types.idl +1 -0
diff -r b383a1053d1d -r 3886d406c13a tools/libxl/libxl_types.idl
@@ -176,6 +176,7 @@ libxl_domain_build_info = Struct("domain
                                        ("vpt_align", bool),
                                        ("timer_mode", integer),
                                        ("nested_hvm", bool),
+                                       ("generation_id", uint64),
                                        ])),
                  ("pv", Struct(None, [("kernel", libxl_file_reference),
                                       ("slack_memkb", uint32),
tools/libxl/libxlu_cfg.c +28 -0
diff -r b383a1053d1d -r 3886d406c13a tools/libxl/libxlu_cfg.c
@@ -232,7 +232,35 @@ int xlu_cfg_get_long(const XLU_Config *c
     return 0;
 }
 
+int xlu_cfg_get_long_long(const XLU_Config *cfg, const char *n,
+                          long long *value_r) {
+    long long ll;
+    XLU_ConfigSetting *set;
+    int e;
+    char *ep;
 
+    e= find_atom(cfg,n,&set);  if (e) return e;
+    errno= 0; ll= strtoll(set->values[0], &ep, 0);
+    e= errno;
+    if (errno) {
+        e= errno;
+        assert(e==EINVAL || e==ERANGE);
+        fprintf(cfg->report,
+                "%s:%d: warning: parameter `%s' could not be parsed"
+                " as a number: %s\n",
+                cfg->filename, set->lineno, n, strerror(e));
+        return e;
+    }
+    if (*ep || ep==set->values[0]) {
+        fprintf(cfg->report,
+                "%s:%d: warning: parameter `%s' is not a valid number\n",
+                cfg->filename, set->lineno, n);
+        return EINVAL;
+    }
+    *value_r= ll;
+    return 0;
+}
+ 
 int xlu_cfg_get_list(const XLU_Config *cfg, const char *n,
                      XLU_ConfigList **list_r, int *entries_r, int dont_warn) {
     XLU_ConfigSetting *set;
tools/libxl/libxlutil.h +1 -0
diff -r b383a1053d1d -r 3886d406c13a tools/libxl/libxlutil.h
@@ -48,6 +48,7 @@ void xlu_cfg_destroy(XLU_Config*);
 int xlu_cfg_get_string(const XLU_Config*, const char *n, const char **value_r);
 int xlu_cfg_replace_string(const XLU_Config *cfg, const char *n, char **value_r); /* free/strdup version */
 int xlu_cfg_get_long(const XLU_Config*, const char *n, long *value_r);
+int xlu_cfg_get_long_long(const XLU_Config*, const char *n, long long *value_r);
 
 int xlu_cfg_get_list(const XLU_Config*, const char *n,
                      XLU_ConfigList **list_r /* may be 0 */,
tools/libxl/xl_cmdimpl.c +4 -0
diff -r b383a1053d1d -r 3886d406c13a tools/libxl/xl_cmdimpl.c
@@ -355,6 +355,7 @@ static void printf_info(int domid,
         printf("\t\t\t(vpt_align %d)\n", b_info->u.hvm.vpt_align);
         printf("\t\t\t(timer_mode %d)\n", b_info->u.hvm.timer_mode);
         printf("\t\t\t(nestedhvm %d)\n", b_info->u.hvm.nested_hvm);
+        printf("\t\t\t(generation_id %llx)\n", b_info->u.hvm.generation_id);
 
         printf("\t\t\t(device_model %s)\n", dm_info->device_model ? : "default");
         printf("\t\t\t(videoram %d)\n", dm_info->videoram);
@@ -523,6 +524,7 @@ static void parse_config_data(const char
 {
     const char *buf;
     long l;
+    long long ll;
     XLU_Config *config;
     XLU_ConfigList *vbds, *nics, *pcis, *cvfbs, *cpuids;
     int pci_power_mgmt = 0;
@@ -699,6 +701,8 @@ static void parse_config_data(const char
             b_info->u.hvm.timer_mode = l;
         if (!xlu_cfg_get_long (config, "nestedhvm", &l))
             b_info->u.hvm.nested_hvm = l;
+        if (!xlu_cfg_get_long_long (config, "generation_id", &ll))
+            b_info->u.hvm.generation_id = ll;
         break;
     case LIBXL_DOMAIN_TYPE_PV:
     {
#6 lore raw

PATCH 1/1 Add code to track the address of the VM generation id buffer across a

In reply to Paul Durrant

# HG changeset patch
# User Paul Durrant <[email protected]>
# Date 1322482489 0
# Node ID c4613164ee1c5f3bf2085008359ebb5b7924c660
# Parent 3886d406c13aa66b2af123d52a1bef8b6f41d144
Add code to track the address of the VM generation id buffer across a save/restore or migrate and inject a new value.

tools/firmware/hvmloader/acpi/build.c +2 -0
diff -r 3886d406c13a -r c4613164ee1c tools/firmware/hvmloader/acpi/build.c
@@ -23,6 +23,7 @@
 #include "ssdt_pm.h"
 #include "../config.h"
 #include "../util.h"
+#include <xen/hvm/params.h>
 
 #define align16(sz)        (((sz) + 15) & ~15)
 #define fixed_strcpy(d, s) strncpy((d), (s), sizeof(d))
@@ -308,6 +309,7 @@ unsigned long new_vm_gid(void)
     gid = strtoll(xenstore_read("platform/generation-id", "0"), NULL, 0);
     *(uint64_t *)buf = gid;
 
+    set_param(HVM_PARAM_VM_GENERATION_ID_ADDR, virt_to_phys(buf));
     return virt_to_phys(buf);    
 }
 
tools/firmware/hvmloader/util.c +12 -0
diff -r 3886d406c13a -r c4613164ee1c tools/firmware/hvmloader/util.c
@@ -26,6 +26,7 @@
 #include <xen/xen.h>
 #include <xen/memory.h>
 #include <xen/sched.h>
+#include <xen/hvm/hvm_op.h>
 
 void wrmsr(uint32_t idx, uint64_t v)
 {
@@ -792,6 +793,17 @@ int hpet_exists(unsigned long hpet_base)
     return ((hpet_id >> 16) == 0x8086);
 }
 
+void set_param(int param, uint64_t value)
+{
+    struct xen_hvm_param p;
+
+    p.domid = DOMID_SELF;
+    p.index = param;
+    p.value = value;
+    if ( hypercall_hvm_op(HVMOP_set_param, &p) != 0 )
+        BUG();
+}
+
 /*
  * Local variables:
  * mode: C
tools/firmware/hvmloader/util.h +2 -0
diff -r 3886d406c13a -r c4613164ee1c tools/firmware/hvmloader/util.h
@@ -228,6 +228,8 @@ void perform_tests(void);
 
 extern char _start[], _end[];
 
+void set_param(int param, uint64_t value);
+
 #endif /* __HVMLOADER_UTIL_H__ */
 
 /*
tools/libxc/ia64/xc_ia64_linux_restore.c +2 -1
diff -r 3886d406c13a -r c4613164ee1c tools/libxc/ia64/xc_ia64_linux_restore.c
@@ -548,7 +548,8 @@ int
 xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
                   unsigned int store_evtchn, unsigned long *store_mfn,
                   unsigned int console_evtchn, unsigned long *console_mfn,
-                  unsigned int hvm, unsigned int pae, int superpages)
+                  unsigned int hvm, unsigned int pae, int superpages,
+                  uint64_t gid)
 {
     DECLARE_DOMCTL;
     int rc = 1;
tools/libxc/xc_domain_restore.c +42 -1

67 lines not on this page · raw message

tools/libxc/xc_domain_save.c +11 -0
diff -r 3886d406c13a -r c4613164ee1c tools/libxc/xc_domain_save.c
@@ -1518,6 +1518,17 @@ int xc_domain_save(xc_interface *xch, in
             PERROR("Error when writing the viridian flag");
             goto out;
         }
+
+        chunk.id = XC_SAVE_ID_HVM_GENERATION_ID_ADDR;
+        chunk.data = 0;
+        xc_get_hvm_param(xch, dom, HVM_PARAM_VM_GENERATION_ID_ADDR,
+                         (unsigned long *)&chunk.data);
+
+        if ((chunk.data != 0) && wrexact(io_fd, &chunk, sizeof(chunk)))
+        {
+            PERROR("Error when writing the generation id buffer location for guest");
+            goto out;
+        }
     }
 
     if ( !callbacks->checkpoint )
tools/libxc/xenguest.h +3 -1
diff -r 3886d406c13a -r c4613164ee1c tools/libxc/xenguest.h
@@ -71,12 +71,14 @@ int xc_domain_save(xc_interface *xch, in
  * @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 gid the new generation id of the VM
  * @return 0 on success, -1 on failure
  */
 int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom,
                       unsigned int store_evtchn, unsigned long *store_mfn,
                       unsigned int console_evtchn, unsigned long *console_mfn,
-                      unsigned int hvm, unsigned int pae, int superpages);
+                      unsigned int hvm, unsigned int pae, int superpages,
+                      uint64_t gid);
 /**
  * xc_domain_restore writes a file to disk that contains the device
  * model saved state.
tools/libxc/xg_save_restore.h +1 -0
diff -r 3886d406c13a -r c4613164ee1c tools/libxc/xg_save_restore.h
@@ -135,6 +135,7 @@
 #define XC_SAVE_ID_LAST_CHECKPOINT    -9 /* Commit to restoring after completion of current iteration. */
 #define XC_SAVE_ID_HVM_ACPI_IOPORTS_LOCATION -10
 #define XC_SAVE_ID_HVM_VIRIDIAN       -11
+#define XC_SAVE_ID_HVM_GENERATION_ID_ADDR -12
 
 /*
 ** We process save/restore/migrate in batches of pages; the below
tools/libxl/libxl_dom.c +4 -1
diff -r 3886d406c13a -r c4613164ee1c tools/libxl/libxl_dom.c
@@ -340,16 +340,19 @@ int libxl__domain_restore_common(libxl__
     /* read signature */
     int rc;
     int hvm, pae, superpages;
+    uint64_t gid;
     switch (info->type) {
     case LIBXL_DOMAIN_TYPE_HVM:
         hvm = 1;
         superpages = 1;
         pae = info->u.hvm.pae;
+        gid = info->u.hvm.generation_id;
         break;
     case LIBXL_DOMAIN_TYPE_PV:
         hvm = 0;
         superpages = 0;
         pae = 1;
+        gid = 0;
         break;
     default:
         return ERROR_INVAL;
@@ -357,7 +360,7 @@ int libxl__domain_restore_common(libxl__
     rc = xc_domain_restore(ctx->xch, fd, domid,
                            state->store_port, &state->store_mfn,
                            state->console_port, &state->console_mfn,
-                           hvm, pae, superpages);
+                           hvm, pae, superpages, gid);
     if ( rc ) {
         LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "restoring domain");
         return ERROR_FAIL;
tools/xcutils/xc_restore.c +8 -2
diff -r 3886d406c13a -r c4613164ee1c tools/xcutils/xc_restore.c
@@ -24,6 +24,7 @@ main(int argc, char **argv)
     int io_fd, ret;
     int superpages;
     unsigned long store_mfn, console_mfn;
+    uint64_t gid;
 
     if ( (argc != 8) && (argc != 9) )
         errx(1, "usage: %s iofd domid store_evtchn "
@@ -40,13 +41,18 @@ main(int argc, char **argv)
     hvm  = atoi(argv[5]);
     pae  = atoi(argv[6]);
     apic = atoi(argv[7]);
-    if ( argc == 9 )
+    if ( argc >= 9 )
 	    superpages = atoi(argv[8]);
     else
 	    superpages = !!hvm;
+    if ( argc >= 10 )
+	    gid = strtoll(argv[9], NULL, 0);
+    else
+	    gid = 0;
 
     ret = xc_domain_restore(xch, io_fd, domid, store_evtchn, &store_mfn,
-                            console_evtchn, &console_mfn, hvm, pae, superpages);
+                            console_evtchn, &console_mfn, hvm, pae, superpages,
+                            gid);
 
     if ( ret == 0 )
     {
xen/include/public/hvm/params.h +4 -1
diff -r 3886d406c13a -r c4613164ee1c xen/include/public/hvm/params.h
@@ -142,6 +142,9 @@
 /* Boolean: Enable nestedhvm (hvm only) */
 #define HVM_PARAM_NESTEDHVM    24
 
-#define HVM_NR_PARAMS          27
+/* Address of VM generation id buffer */
+#define HVM_PARAM_VM_GENERATION_ID_ADDR 27
+
+#define HVM_NR_PARAMS          28
 
 #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
#7 lore raw

Re: [PATCH 4 of 5] Add code to track the address of the VM generation id buffer across a

xen/include/public/hvm/params.h line 150

Quoted 13 lines · Paul Durrant
xen/include/public/hvm/params.h +4 -1
@@ -142,6 +142,9 @@
 /* Boolean: Enable nestedhvm (hvm only) */
 #define HVM_PARAM_NESTEDHVM    24
 
-#define HVM_NR_PARAMS          27
+/* Address of VM generation id buffer */
+#define HVM_PARAM_VM_GENERATION_ID_ADDR 27
+
+#define HVM_NR_PARAMS          28
 
 #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */

Since the hypervisor doesn't use this value, I don't think this is the right place for it to live. Tools-only VM metadata should probably go in xenstore or in the toolstacks' own datastructures.

Tim.

#8 lore raw

Re: [PATCH 4 of 5] Add code to track the address of the VM generation id buffer across a

Quoted 23 lines

-----Original Message-----
From: Tim Deegan [mailto:[email protected]]
Sent: 28 November 2011 12:33
To: Paul Durrant
Cc: [email protected]
Subject: Re: [Xen-devel] [PATCH 4 of 5] Add code to track the address of the VM generation id buffer across a

Quoted 1 line · Paul Durrant

--- a/xen/include/public/hvm/params.h Mon Nov 28 12:14:48 2011

+0000

Quoted 1 line

+++ b/xen/include/public/hvm/params.h Mon Nov 28 12:14:49 2011

+0000

Quoted 10 lines
xen/include/public/hvm/params.h +4 -1
@@ -142,6 +142,9 @@
 /* Boolean: Enable nestedhvm (hvm only) */
 #define HVM_PARAM_NESTEDHVM    24
 
-#define HVM_NR_PARAMS          27
+/* Address of VM generation id buffer */ #define
+HVM_PARAM_VM_GENERATION_ID_ADDR 27
+
+#define HVM_NR_PARAMS          28
 
Quoted 6 lines

xen/include/public/hvm/params.h line 150

Quoted 1 line
xen/include/public/hvm/params.h +0 -0
 #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */

Since the hypervisor doesn't use this value, I don't think this is the right place for it to live. Tools-only VM metadata should probably go in xenstore or in the toolstacks' own datastructures.

Yes, I was a little unsure about that. Is there any precedent for getting information from hvmloader out to the tools? Writing guest physical addresses into xenstore seems like the wrong thing to but apart from HVM params or the shared hvm info page, I couldn't think of another way apart from putting the VM generation id in a static well-known place.

Paul

#9 lore raw

Re: [PATCH 4 of 5] Add code to track the address of the VM generation id buffer across a

Quoted 12 lines · Paul Durrant
Quoted 11 lines

xen/include/public/hvm/params.h line 150

Quoted 6 lines
xen/include/public/hvm/params.h +4 -0
+/* Address of VM generation id buffer */ #define
+HVM_PARAM_VM_GENERATION_ID_ADDR 27
+
+#define HVM_NR_PARAMS          28
 
 #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */

Since the hypervisor doesn't use this value, I don't think this is the right place for it to live. Tools-only VM metadata should probably go in xenstore or in the toolstacks' own datastructures.

Quoted 6 lines

Yes, I was a little unsure about that. Is there any precedent for getting information from hvmloader out to the tools? Writing guest physical addresses into xenstore seems like the wrong thing to but apart from HVM params or the shared hvm info page, I couldn't think of another way apart from putting the VM generation id in a static well-known place.

Presumably in this case the tools can find the address by walking the ACPI tables, just like the guest OS would. :P Not very pretty, though.

I don't think there's anything wrong with putting a GPA into xenstore. All the other tools interactions are in guest-physical addressing already. IIRC HVMloader's xenbus client doesn't have a xenstore_write() but it shouldn't be hard to add.

I can't think of another way to pass data from hvmloader to the tools right now -- I think the hvm-info page should probably be replaced entirely with xenstore keys at some point.

Tim.

#10 lore raw

Re: [PATCH 4 of 5] Add code to track the address of the VM generation id buffer across a

Quoted 6 lines

-----Original Message-----

Presumably in this case the tools can find the address by walking the ACPI tables, just like the guest OS would. :P Not very pretty, though.

Erk, no! That would not be pretty.

Quoted 5 lines

I don't think there's anything wrong with putting a GPA into xenstore. All the other tools interactions are in guest-physical addressing already. IIRC HVMloader's xenbus client doesn't have a xenstore_write() but it shouldn't be hard to add.

OK, I'll go with that. Re-worked series coming up...

Quoted 4 lines

I can't think of another way to pass data from hvmloader to the tools right now -- I think the hvm-info page should probably be replaced entirely with xenstore keys at some point.

Yes, that was why I moved acpi_enabled out of there. Didn't really want to put something else in there :-)

Paul

#11 lore raw

PATCH 1/1 Modify init_vm86_tss() to take advantage of the new set_param() function

In reply to Paul Durrant

# HG changeset patch
# User Paul Durrant <[email protected]>
# Date 1322482489 0
# Node ID 57100f663da56491619ac6f49eae17f9dd5a71e9
# Parent c4613164ee1c5f3bf2085008359ebb5b7924c660
Modify init_vm86_tss() to take advantage of the new set_param() function.

tools/firmware/hvmloader/hvmloader.c +2 -5
diff -r c4613164ee1c -r 57100f663da5 tools/firmware/hvmloader/hvmloader.c
@@ -344,14 +344,11 @@ 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);
+
+    set_param(HVM_PARAM_VM86_TSS, virt_to_phys(tss));
     printf("vm86 TSS at %08lx\n", virt_to_phys(tss));
 }