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
|