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

[Xen-devel] [PATCH 2/2] xl: add cpuid parsing and translation



Hi,

this one actually parses the cpuid option string and translates it into the 32-character string libxc expects.
Please comment!

Signed-off-by: Andre Przywara <andre.przywara@xxxxxxx>

--
Andre Przywara
AMD-Operating System Research Center (OSRC), Dresden, Germany
Tel: +49 351 448-3567-12
>From 042a22523e7ea68019e0a5733139671435d50ccf Mon Sep 17 00:00:00 2001
From: Andre Przywara <andre.przywara@xxxxxxx>
Date: Thu, 19 Aug 2010 11:51:00 +0200
Subject: [PATCH 2/2] xl: implement parsing of cpuid parameter and translate to 
Xen interface

Signed-off-by: Andre Przywara <andre.przywara@xxxxxxx>
---
 tools/libxl/xl_cmdimpl.c |  209 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 209 insertions(+), 0 deletions(-)

diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 0fa516b..180d0c4 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -562,6 +562,212 @@ static int parse_action_on_shutdown(const char *buf, enum 
action_on_shutdown *a)
     return 0;
 }
 
+#define REG_INV 0
+#define REG_EAX 1
+#define REG_EBX 2
+#define REG_ECX 3
+#define REG_EDX 4
+
+struct cpuid_flags {
+    char* name;
+    uint32_t leaf;
+    int reg;
+    int bit;
+    int length;
+};
+
+static libxl_cpuid_type* cpuid_find_match(libxl_cpuid_type **list,
+                                          uint32_t leaf, uint32_t subleaf)
+{
+    int i = 0;
+
+    if (*list != NULL) {
+        for (i = 0; (*list)[i].input[0] != XEN_CPUID_INPUT_UNUSED; i++) {
+            if ((*list)[i].input[0] == leaf && (*list)[i].input[1] == subleaf)
+                return *list + i;
+        }
+    }
+    *list = realloc(*list, sizeof(libxl_cpuid_type) * (i + 2));
+    (*list)[i].input[0] = leaf;
+    (*list)[i].input[1] = subleaf;
+    memset((*list)[i].policy, 0, 4 * sizeof(char*));
+    (*list)[i + 1].input[0] = XEN_CPUID_INPUT_UNUSED;
+    return *list + i;
+}
+
+static libxl_cpuid_type* parse_cpuid(const char* cpuidstr)
+{
+    struct cpuid_flags cpuid_flags[] = {
+        {"maxleaf",      0x00000000, REG_EAX,  0, 32},
+        {"family",       0x00000001, REG_EAX,  8,  8}, /* subject to tweaking 
*/
+        {"model",        0x00000001, REG_EAX,  4,  8}, /* subject to tweaking 
*/
+        {"stepping",     0x00000001, REG_EAX,  0,  4},
+        {"localapicid",  0x00000001, REG_EBX, 24,  8},
+        {"proccount",    0x00000001, REG_EBX, 16,  8},
+        {"clflush",      0x00000001, REG_EBX,  8,  8},
+        {"brandid",      0x00000001, REG_EBX,  0,  8},
+        {"osxsave",      0x00000001, REG_ECX, 27,  1},
+        {"xsave",        0x00000001, REG_ECX, 26,  1},
+        {"popcnt",       0x00000001, REG_ECX, 23,  1},
+        {"movbe",        0x00000001, REG_ECX, 22,  1},
+        {"x2apic",       0x00000001, REG_ECX, 21,  1},
+        {"sse4.2",       0x00000001, REG_ECX, 20,  1},
+        {"sse4.1",       0x00000001, REG_ECX, 19,  1},
+        {"dca",          0x00000001, REG_ECX, 18,  1},
+        {"pdcm",         0x00000001, REG_ECX, 15,  1},
+        {"xtpr",         0x00000001, REG_ECX, 14,  1},
+        {"cmpxchg16",    0x00000001, REG_ECX, 13,  1},
+        {"cntxid",       0x00000001, REG_ECX, 10,  1},
+        {"ssse3",        0x00000001, REG_ECX,  9,  1},
+        {"tm2",          0x00000001, REG_ECX,  8,  1},
+        {"est",          0x00000001, REG_ECX,  7,  1},
+        {"smx",          0x00000001, REG_ECX,  6,  1},
+        {"vmx",          0x00000001, REG_ECX,  5,  1},
+        {"dscpl",        0x00000001, REG_ECX,  4,  1},
+        {"monitor",      0x00000001, REG_ECX,  3,  1},
+        {"dtes64",       0x00000001, REG_ECX,  2,  1},
+        {"sse3",         0x00000001, REG_ECX,  0,  1},
+        {"pbe",          0x00000001, REG_EDX, 31,  1},
+        {"ia64",         0x00000001, REG_EDX, 30,  1},
+        {"tm",           0x00000001, REG_EDX, 29,  1},
+        {"htt",          0x00000001, REG_EDX, 28,  1},
+        {"ss",           0x00000001, REG_EDX, 27,  1},
+        {"sse2",         0x00000001, REG_EDX, 26,  1},
+        {"sse",          0x00000001, REG_EDX, 25,  1},
+        {"fxsr",         0x00000001, REG_EDX, 24,  1},
+        {"mmx",          0x00000001, REG_EDX, 23,  1},
+        {"acpi",         0x00000001, REG_EDX, 22,  1},
+        {"ds",           0x00000001, REG_EDX, 21,  1},
+        {"clfsh",        0x00000001, REG_EDX, 19,  1},
+        {"psn",          0x00000001, REG_EDX, 18,  1},
+        {"pse36",        0x00000001, REG_EDX, 17,  1},
+        {"pat",          0x00000001, REG_EDX, 16,  1},
+        {"cmov",         0x00000001, REG_EDX, 15,  1},
+        {"mca",          0x00000001, REG_EDX, 14,  1},
+        {"pge",          0x00000001, REG_EDX, 13,  1},
+        {"mtrr",         0x00000001, REG_EDX, 12,  1},
+        {"sysenter",     0x00000001, REG_EDX, 11,  1},
+        {"apic",         0x00000001, REG_EDX,  9,  1},
+        {"cmpxchg8",     0x00000001, REG_EDX,  8,  1},
+        {"mce",          0x00000001, REG_EDX,  7,  1},
+        {"pae",          0x00000001, REG_EDX,  6,  1},
+        {"msr",          0x00000001, REG_EDX,  5,  1},
+        {"tsc",          0x00000001, REG_EDX,  4,  1},
+        {"pse",          0x00000001, REG_EDX,  3,  1},
+        {"de",           0x00000001, REG_EDX,  2,  1},
+        {"vme",          0x00000001, REG_EDX,  1,  1},
+        {"fpu",          0x00000001, REG_EDX,  0,  1},
+        {"wdt",          0x80000001, REG_ECX, 13,  1},
+        {"skinit",       0x80000001, REG_ECX, 12,  1},
+        {"xop",          0x80000001, REG_ECX, 11,  1},
+        {"ibs",          0x80000001, REG_ECX, 10,  1},
+        {"osvw",         0x80000001, REG_ECX, 10,  1},
+        {"3dnowprefetch",0x80000001, REG_ECX,  8,  1},
+        {"misalignsse",  0x80000001, REG_ECX,  7,  1},
+        {"sse4a",        0x80000001, REG_ECX,  6,  1},
+        {"abm",          0x80000001, REG_ECX,  5,  1},
+        {"altmovcr8",    0x80000001, REG_ECX,  4,  1},
+        {"extapic",      0x80000001, REG_ECX,  3,  1},
+        {"svm",          0x80000001, REG_ECX,  2,  1},
+        {"cmplegacy",    0x80000001, REG_ECX,  1,  1},
+        {"lahfsahf",     0x80000001, REG_ECX,  0,  1},
+        {"3dnowext",     0x80000001, REG_EDX, 31,  1},
+        {"3dnow",        0x80000001, REG_EDX, 30,  1},
+        {"lm",           0x80000001, REG_EDX, 29,  1},
+        {"rdtscp",       0x80000001, REG_EDX, 27,  1},
+        {"page1gb",      0x80000001, REG_EDX, 26,  1},
+        {"ffxsr",        0x80000001, REG_EDX, 25,  1},
+        {"mmxext",       0x80000001, REG_EDX, 22,  1},
+        {"nx",           0x80000001, REG_EDX, 20,  1},
+        {"syscall",      0x80000001, REG_EDX, 11,  1},
+        {"apicidsize",   0x80000008, REG_ECX, 12,  4},
+        {"nc",           0x80000008, REG_ECX,  0,  8},
+
+        {NULL, 0, 0, 0, 0}
+    };
+    char *buf, *strtok_ptr, *p, *val, *endptr;
+    int i;
+    struct cpuid_flags *flag;
+    libxl_cpuid_type *cpuid_info = NULL, *entry;
+    unsigned long num;
+    char flags[33], *resstr;
+
+    buf = strdup(cpuidstr);
+    p = strtok_r(buf, ",", &strtok_ptr);
+    /* base model is ignored for now */
+    for (; p; p = strtok_r(NULL, ",", &strtok_ptr)) {
+        val = strchr(p, '=');
+        /* detect leading + or - for en/disabling feature bits */
+        if (val == NULL) {
+            if (*p == '+') {
+                p++;
+                val = "1";
+            } else if (*p == '-') {
+                p++;
+                val = "0";
+            } else
+                continue;
+        } else {
+            *val++ = 0;
+        }
+        for (flag = cpuid_flags; flag->name != NULL; flag++)
+            if(!strcmp(p, flag->name))
+                break;
+        if (flag->name == NULL) {
+            fprintf(stderr, "cpuid: could not find feature called \"%s\"\n", 
p);
+            continue;
+        }
+        entry = cpuid_find_match(&cpuid_info, flag->leaf,
+                                  XEN_CPUID_INPUT_UNUSED);
+        resstr = entry->policy[flag->reg - 1];
+        if (resstr == NULL)
+            resstr = strdup("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
+        num = strtoull(val, &endptr, 0);
+        flags[flag->length] = 0;
+        if (endptr != val) {
+            for (i = 0; i < flag->length; i++)
+                flags[flag->length - 1 - i] = "01"[!!(num & (1 << i))];
+        } else {
+            switch(val[0]) {
+            case 'x': case 'k': case 's':
+                memset(flags, val[0], flag->length);
+                break;
+            default:
+                fprintf(stderr,
+                        "invalid value \"%s\" for flag \"%s\"\n",
+                        val, p);
+                continue;
+            }
+        }
+        /* the family and model entry is potentially split up across
+         * two fields in Fn0000_0001_EAX, so handle them here separately.
+         */
+        if (!strcmp(p, "family")) {
+            if (num < 16) {
+                memcpy(resstr + (32 - 4) - flag->bit, flags + 4, 4);
+                memcpy(resstr + (32 - 8) - 20, "00000000", 8);
+            } else {
+                num -= 15;
+                memcpy(resstr + (32 - 4) - flag->bit, "1111", 4);
+                for (i = 0; i < 7; i++) {
+                    flags[7 - i] = "01"[num & 1];
+                    num >>= 1;
+                }
+                memcpy(resstr + (32 - 8) - 20, flags, 8);
+            }
+        } else if (!strcmp(p, "model")) {
+            memcpy(resstr + (32 - 4) - 16, flags, 4);
+            memcpy(resstr + (32 - 4) - flag->bit, flags + 4, 4);
+        } else
+            memcpy(resstr + (32 - flag->length) - flag->bit, flags,
+                   flag->length);
+        entry->policy[flag->reg - 1] = resstr;
+    }
+    free(buf);
+
+    return cpuid_info;
+}
+
 static void parse_config_data(const char *configfile_filename_report,
                               const char *configfile_data,
                               int configfile_len,
@@ -1001,6 +1207,9 @@ skip_vfb:
         }
     }
 
+    if (!xlu_cfg_get_string(config, "cpuid", &buf))
+        b_info->cpuid = parse_cpuid(buf);
+
     if (c_info->hvm == 1) {
         /* init dm from c and b */
         init_dm_info(dm_info, c_info, b_info);
-- 
1.6.4

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

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