[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [Patch v6 06/13] tools/libxc: x86 common code



Save/restore records common to all x86 domain types (HVM, PV).

This is only the TSC_INFO record.

Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
Acked-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
---
 tools/libxc/saverestore/common_x86.c |  133 ++++++++++++++++++++++++++++++++++
 tools/libxc/saverestore/common_x86.h |   26 +++++++
 2 files changed, 159 insertions(+)
 create mode 100644 tools/libxc/saverestore/common_x86.c
 create mode 100644 tools/libxc/saverestore/common_x86.h

diff --git a/tools/libxc/saverestore/common_x86.c 
b/tools/libxc/saverestore/common_x86.c
new file mode 100644
index 0000000..b64b291
--- /dev/null
+++ b/tools/libxc/saverestore/common_x86.c
@@ -0,0 +1,133 @@
+#include "common_x86.h"
+
+static void cpuid_count(uint32_t leaf, uint32_t subleaf,
+                        uint32_t *eax, uint32_t *ebx,
+                        uint32_t *ecx, uint32_t *edx)
+{
+    asm volatile ("cpuid"
+                  : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
+                  : "a" (leaf), "c" (subleaf));
+}
+
+static void cpuid(uint32_t leaf,
+                  uint32_t *eax, uint32_t *ebx,
+                  uint32_t *ecx, uint32_t *edx)
+{
+    cpuid_count(leaf, 0, eax, ebx, ecx, edx);
+}
+
+static int get_processor_brand_string(char *str)
+{
+    uint32_t *parts = (uint32_t*)str;
+    uint32_t max_extd_leaf, dummy;
+
+    cpuid(0x80000000, &max_extd_leaf, &dummy, &dummy, &dummy);
+
+    if ( max_extd_leaf < 0x80000004 )
+        return -1;
+
+    cpuid(0x80000002, &parts[0], &parts[1], &parts[2],  &parts[3]);
+    cpuid(0x80000003, &parts[4], &parts[5], &parts[6],  &parts[7]);
+    cpuid(0x80000004, &parts[8], &parts[9], &parts[10], &parts[11]);
+
+    return 0;
+}
+
+int write_tsc_info(struct xc_sr_context *ctx)
+{
+    xc_interface *xch = ctx->xch;
+    struct xc_sr_rec_tsc_info tsc = { 0 };
+    struct xc_sr_record rec =
+    {
+        .type = REC_TYPE_TSC_INFO,
+        .length = sizeof(tsc),
+        .data = &tsc
+    };
+
+    if ( xc_domain_get_tsc_info(xch, ctx->domid, &tsc.mode,
+                                &tsc.nsec, &tsc.khz, &tsc.incarnation) < 0 )
+    {
+        PERROR("Unable to obtain TSC information");
+        return -1;
+    }
+
+    return write_record(ctx, &rec);
+}
+
+int handle_tsc_info(struct xc_sr_context *ctx, struct xc_sr_record *rec)
+{
+    xc_interface *xch = ctx->xch;
+    struct xc_sr_rec_tsc_info *tsc = rec->data;
+
+    if ( rec->length != sizeof(*tsc) )
+    {
+        ERROR("TSC_INFO record wrong size: length %"PRIu32", expected %zu",
+              rec->length, sizeof(*tsc));
+        return -1;
+    }
+
+    if ( xc_domain_set_tsc_info(xch, ctx->domid, tsc->mode,
+                                tsc->nsec, tsc->khz, tsc->incarnation) )
+    {
+        PERROR("Unable to set TSC information");
+        return -1;
+    }
+
+    return 0;
+}
+
+int arch_write_saving_cpu(struct xc_sr_context *ctx)
+{
+    xc_interface *xch = ctx->xch;
+    char *brand_string = alloca(49); /* 48 from cpuid, and NUL. */
+    struct xc_sr_record rec;
+
+    if ( get_processor_brand_string(brand_string) )
+    {
+        ERROR("Failed to obtain cpuid long processor brand string");
+        return -1;
+    }
+
+    brand_string[48] = '\0';
+    while ( *brand_string == ' ' ) /* Strip leading spaces. */
+        brand_string++;
+
+    rec.type = REC_TYPE_SAVING_CPU;
+    rec.length = strlen(brand_string);
+    rec.data = brand_string;
+
+    return write_record(ctx, &rec);
+}
+
+int arch_handle_saving_cpu(struct xc_sr_context *ctx, struct xc_sr_record *rec)
+{
+    xc_interface *xch = ctx->xch;
+    char *brand_string = alloca(49); /* 48 from cpuid, and NUL. */
+
+    if ( rec->length == 0 )
+        return 0;
+
+    DPRINTF("Saving cpu was '%*s'",
+            (int)rec->length, (char*)rec->data);
+
+    if ( !get_processor_brand_string(brand_string) )
+    {
+        brand_string[48] = '\0';
+        while ( *brand_string == ' ' ) /* Strip leading spaces. */
+            brand_string++;
+
+        DPRINTF("Current cpu is '%s'", brand_string);
+    }
+
+    return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxc/saverestore/common_x86.h 
b/tools/libxc/saverestore/common_x86.h
new file mode 100644
index 0000000..5971bc5
--- /dev/null
+++ b/tools/libxc/saverestore/common_x86.h
@@ -0,0 +1,26 @@
+#ifndef __COMMON_X86__H
+#define __COMMON_X86__H
+
+#include "common.h"
+
+/*
+ * Obtains a domains TSC information from Xen and writes a TSC_INFO record
+ * into the stream.
+ */
+int write_tsc_info(struct xc_sr_context *ctx);
+
+/*
+ * Parses a TSC_INFO record and applies the result to the domain.
+ */
+int handle_tsc_info(struct xc_sr_context *ctx, struct xc_sr_record *rec);
+
+#endif
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
1.7.10.4


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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.