#include "libxl_internal.h"
+#include <xen/lib/x86/cpu-policy.h>
+
int libxl__cpuid_policy_is_empty(libxl_cpuid_policy_list *pl)
{
return !libxl_cpuid_policy_list_length(pl);
* Used for the static structure describing all features.
*/
struct cpuid_flags {
- char* name;
+ const char* name;
uint32_t leaf;
uint32_t subleaf;
int reg;
return *list + i;
}
+static int search_feature(const void *a, const void *b)
+{
+ const char *key = a;
+ const char *feat = ((struct { const char *n; } *)b)->n;
+
+ return strncmp(key, feat, strlen(key)) ?: strlen(key) - strlen(feat);
+}
+
/* parse a single key=value pair and translate it into the libxc
* used interface using 32-characters strings for each register.
* Will overwrite earlier entries and thus can be called multiple
{"proccount", 0x00000001, NA, CPUID_REG_EBX, 16, 8},
{"localapicid", 0x00000001, NA, CPUID_REG_EBX, 24, 8},
- {"sse3", 0x00000001, NA, CPUID_REG_ECX, 0, 1},
- {"pclmulqdq", 0x00000001, NA, CPUID_REG_ECX, 1, 1},
- {"dtes64", 0x00000001, NA, CPUID_REG_ECX, 2, 1},
- {"monitor", 0x00000001, NA, CPUID_REG_ECX, 3, 1},
- {"dscpl", 0x00000001, NA, CPUID_REG_ECX, 4, 1},
- {"vmx", 0x00000001, NA, CPUID_REG_ECX, 5, 1},
- {"smx", 0x00000001, NA, CPUID_REG_ECX, 6, 1},
{"est", 0x00000001, NA, CPUID_REG_ECX, 7, 1},
- {"tm2", 0x00000001, NA, CPUID_REG_ECX, 8, 1},
- {"ssse3", 0x00000001, NA, CPUID_REG_ECX, 9, 1},
{"cntxid", 0x00000001, NA, CPUID_REG_ECX, 10, 1},
- {"fma", 0x00000001, NA, CPUID_REG_ECX, 12, 1},
{"cmpxchg16", 0x00000001, NA, CPUID_REG_ECX, 13, 1},
- {"xtpr", 0x00000001, NA, CPUID_REG_ECX, 14, 1},
- {"pdcm", 0x00000001, NA, CPUID_REG_ECX, 15, 1},
- {"pcid", 0x00000001, NA, CPUID_REG_ECX, 17, 1},
- {"dca", 0x00000001, NA, CPUID_REG_ECX, 18, 1},
/* Linux uses sse4_{1,2}. Keep sse4.{1,2} for compatibility */
- {"sse4_1", 0x00000001, NA, CPUID_REG_ECX, 19, 1},
{"sse4.1", 0x00000001, NA, CPUID_REG_ECX, 19, 1},
- {"sse4_2", 0x00000001, NA, CPUID_REG_ECX, 20, 1},
{"sse4.2", 0x00000001, NA, CPUID_REG_ECX, 20, 1},
- {"x2apic", 0x00000001, NA, CPUID_REG_ECX, 21, 1},
- {"movbe", 0x00000001, NA, CPUID_REG_ECX, 22, 1},
- {"popcnt", 0x00000001, NA, CPUID_REG_ECX, 23, 1},
- {"tsc-deadline", 0x00000001, NA, CPUID_REG_ECX, 24, 1},
{"aes", 0x00000001, NA, CPUID_REG_ECX, 25, 1},
- {"xsave", 0x00000001, NA, CPUID_REG_ECX, 26, 1},
- {"osxsave", 0x00000001, NA, CPUID_REG_ECX, 27, 1},
- {"avx", 0x00000001, NA, CPUID_REG_ECX, 28, 1},
- {"f16c", 0x00000001, NA, CPUID_REG_ECX, 29, 1},
- {"rdrand", 0x00000001, NA, CPUID_REG_ECX, 30, 1},
- {"hypervisor", 0x00000001, NA, CPUID_REG_ECX, 31, 1},
-
- {"fpu", 0x00000001, NA, CPUID_REG_EDX, 0, 1},
- {"vme", 0x00000001, NA, CPUID_REG_EDX, 1, 1},
- {"de", 0x00000001, NA, CPUID_REG_EDX, 2, 1},
- {"pse", 0x00000001, NA, CPUID_REG_EDX, 3, 1},
- {"tsc", 0x00000001, NA, CPUID_REG_EDX, 4, 1},
- {"msr", 0x00000001, NA, CPUID_REG_EDX, 5, 1},
- {"pae", 0x00000001, NA, CPUID_REG_EDX, 6, 1},
- {"mce", 0x00000001, NA, CPUID_REG_EDX, 7, 1},
+
{"cmpxchg8", 0x00000001, NA, CPUID_REG_EDX, 8, 1},
- {"apic", 0x00000001, NA, CPUID_REG_EDX, 9, 1},
{"sysenter", 0x00000001, NA, CPUID_REG_EDX, 11, 1},
- {"mtrr", 0x00000001, NA, CPUID_REG_EDX, 12, 1},
- {"pge", 0x00000001, NA, CPUID_REG_EDX, 13, 1},
- {"mca", 0x00000001, NA, CPUID_REG_EDX, 14, 1},
- {"cmov", 0x00000001, NA, CPUID_REG_EDX, 15, 1},
- {"pat", 0x00000001, NA, CPUID_REG_EDX, 16, 1},
- {"pse36", 0x00000001, NA, CPUID_REG_EDX, 17, 1},
{"psn", 0x00000001, NA, CPUID_REG_EDX, 18, 1},
{"clfsh", 0x00000001, NA, CPUID_REG_EDX, 19, 1},
- {"ds", 0x00000001, NA, CPUID_REG_EDX, 21, 1},
- {"acpi", 0x00000001, NA, CPUID_REG_EDX, 22, 1},
- {"mmx", 0x00000001, NA, CPUID_REG_EDX, 23, 1},
- {"fxsr", 0x00000001, NA, CPUID_REG_EDX, 24, 1},
- {"sse", 0x00000001, NA, CPUID_REG_EDX, 25, 1},
- {"sse2", 0x00000001, NA, CPUID_REG_EDX, 26, 1},
- {"ss", 0x00000001, NA, CPUID_REG_EDX, 27, 1},
- {"htt", 0x00000001, NA, CPUID_REG_EDX, 28, 1},
{"tm", 0x00000001, NA, CPUID_REG_EDX, 29, 1},
{"ia64", 0x00000001, NA, CPUID_REG_EDX, 30, 1},
{"pbe", 0x00000001, NA, CPUID_REG_EDX, 31, 1},
{"arat", 0x00000006, NA, CPUID_REG_EAX, 2, 1},
- {"fsgsbase", 0x00000007, 0, CPUID_REG_EBX, 0, 1},
- {"tsc_adjust", 0x00000007, 0, CPUID_REG_EBX, 1, 1},
- {"bmi1", 0x00000007, 0, CPUID_REG_EBX, 3, 1},
- {"hle", 0x00000007, 0, CPUID_REG_EBX, 4, 1},
- {"avx2", 0x00000007, 0, CPUID_REG_EBX, 5, 1},
- {"smep", 0x00000007, 0, CPUID_REG_EBX, 7, 1},
- {"bmi2", 0x00000007, 0, CPUID_REG_EBX, 8, 1},
- {"erms", 0x00000007, 0, CPUID_REG_EBX, 9, 1},
- {"invpcid", 0x00000007, 0, CPUID_REG_EBX, 10, 1},
- {"rtm", 0x00000007, 0, CPUID_REG_EBX, 11, 1},
- {"cmt", 0x00000007, 0, CPUID_REG_EBX, 12, 1},
- {"mpx", 0x00000007, 0, CPUID_REG_EBX, 14, 1},
- {"avx512f", 0x00000007, 0, CPUID_REG_EBX, 16, 1},
- {"avx512dq", 0x00000007, 0, CPUID_REG_EBX, 17, 1},
- {"rdseed", 0x00000007, 0, CPUID_REG_EBX, 18, 1},
- {"adx", 0x00000007, 0, CPUID_REG_EBX, 19, 1},
- {"smap", 0x00000007, 0, CPUID_REG_EBX, 20, 1},
- {"avx512-ifma", 0x00000007, 0, CPUID_REG_EBX, 21, 1},
- {"clflushopt", 0x00000007, 0, CPUID_REG_EBX, 23, 1},
- {"clwb", 0x00000007, 0, CPUID_REG_EBX, 24, 1},
- {"proc-trace", 0x00000007, 0, CPUID_REG_EBX, 25, 1},
- {"avx512pf", 0x00000007, 0, CPUID_REG_EBX, 26, 1},
- {"avx512er", 0x00000007, 0, CPUID_REG_EBX, 27, 1},
- {"avx512cd", 0x00000007, 0, CPUID_REG_EBX, 28, 1},
- {"sha", 0x00000007, 0, CPUID_REG_EBX, 29, 1},
- {"avx512bw", 0x00000007, 0, CPUID_REG_EBX, 30, 1},
- {"avx512vl", 0x00000007, 0, CPUID_REG_EBX, 31, 1},
-
- {"prefetchwt1", 0x00000007, 0, CPUID_REG_ECX, 0, 1},
- {"avx512-vbmi", 0x00000007, 0, CPUID_REG_ECX, 1, 1},
- {"umip", 0x00000007, 0, CPUID_REG_ECX, 2, 1},
- {"pku", 0x00000007, 0, CPUID_REG_ECX, 3, 1},
- {"ospke", 0x00000007, 0, CPUID_REG_ECX, 4, 1},
- {"avx512-vbmi2", 0x00000007, 0, CPUID_REG_ECX, 6, 1},
- {"cet-ss", 0x00000007, 0, CPUID_REG_ECX, 7, 1},
- {"gfni", 0x00000007, 0, CPUID_REG_ECX, 8, 1},
- {"vaes", 0x00000007, 0, CPUID_REG_ECX, 9, 1},
- {"vpclmulqdq", 0x00000007, 0, CPUID_REG_ECX, 10, 1},
- {"avx512-vnni", 0x00000007, 0, CPUID_REG_ECX, 11, 1},
- {"avx512-bitalg",0x00000007, 0, CPUID_REG_ECX, 12, 1},
- {"avx512-vpopcntdq",0x00000007,0,CPUID_REG_ECX, 14, 1},
- {"rdpid", 0x00000007, 0, CPUID_REG_ECX, 22, 1},
- {"cldemote", 0x00000007, 0, CPUID_REG_ECX, 25, 1},
- {"pks", 0x00000007, 0, CPUID_REG_ECX, 31, 1},
-
- {"avx512-4vnniw",0x00000007, 0, CPUID_REG_EDX, 2, 1},
- {"avx512-4fmaps",0x00000007, 0, CPUID_REG_EDX, 3, 1},
- {"fsrm", 0x00000007, 0, CPUID_REG_EDX, 4, 1},
- {"avx512-vp2intersect",0x00000007,0,CPUID_REG_EDX,8, 1},
- {"srbds-ctrl", 0x00000007, 0, CPUID_REG_EDX, 9, 1},
- {"md-clear", 0x00000007, 0, CPUID_REG_EDX, 10, 1},
- {"serialize", 0x00000007, 0, CPUID_REG_EDX, 14, 1},
- {"tsxldtrk", 0x00000007, 0, CPUID_REG_EDX, 16, 1},
- {"cet-ibt", 0x00000007, 0, CPUID_REG_EDX, 20, 1},
- {"avx512-fp16", 0x00000007, 0, CPUID_REG_EDX, 23, 1},
- {"ibrsb", 0x00000007, 0, CPUID_REG_EDX, 26, 1},
- {"stibp", 0x00000007, 0, CPUID_REG_EDX, 27, 1},
- {"l1d-flush", 0x00000007, 0, CPUID_REG_EDX, 28, 1},
- {"arch-caps", 0x00000007, 0, CPUID_REG_EDX, 29, 1},
- {"core-caps", 0x00000007, 0, CPUID_REG_EDX, 30, 1},
- {"ssbd", 0x00000007, 0, CPUID_REG_EDX, 31, 1},
-
- {"avx-vnni", 0x00000007, 1, CPUID_REG_EAX, 4, 1},
- {"avx512-bf16", 0x00000007, 1, CPUID_REG_EAX, 5, 1},
- {"fzrm", 0x00000007, 1, CPUID_REG_EAX, 10, 1},
- {"fsrs", 0x00000007, 1, CPUID_REG_EAX, 11, 1},
- {"fsrcs", 0x00000007, 1, CPUID_REG_EAX, 12, 1},
- {"wrmsrns", 0x00000007, 1, CPUID_REG_EAX, 19, 1},
- {"avx-ifma", 0x00000007, 1, CPUID_REG_EAX, 23, 1},
-
- {"avx-vnni-int8",0x00000007, 1, CPUID_REG_EDX, 4, 1},
- {"avx-ne-convert",0x00000007, 1, CPUID_REG_EDX, 5, 1},
- {"cet-sss", 0x00000007, 1, CPUID_REG_EDX, 18, 1},
-
- {"intel-psfd", 0x00000007, 2, CPUID_REG_EDX, 0, 1},
- {"ipred-ctrl", 0x00000007, 2, CPUID_REG_EDX, 1, 1},
- {"rrsba-ctrl", 0x00000007, 2, CPUID_REG_EDX, 2, 1},
- {"ddp-ctrl", 0x00000007, 2, CPUID_REG_EDX, 3, 1},
- {"bhi-ctrl", 0x00000007, 2, CPUID_REG_EDX, 4, 1},
- {"mcdt-no", 0x00000007, 2, CPUID_REG_EDX, 5, 1},
-
{"lahfsahf", 0x80000001, NA, CPUID_REG_ECX, 0, 1},
{"cmplegacy", 0x80000001, NA, CPUID_REG_ECX, 1, 1},
- {"svm", 0x80000001, NA, CPUID_REG_ECX, 2, 1},
- {"extapic", 0x80000001, NA, CPUID_REG_ECX, 3, 1},
{"altmovcr8", 0x80000001, NA, CPUID_REG_ECX, 4, 1},
- {"abm", 0x80000001, NA, CPUID_REG_ECX, 5, 1},
- {"sse4a", 0x80000001, NA, CPUID_REG_ECX, 6, 1},
- {"misalignsse", 0x80000001, NA, CPUID_REG_ECX, 7, 1},
- {"3dnowprefetch",0x80000001, NA, CPUID_REG_ECX, 8, 1},
- {"osvw", 0x80000001, NA, CPUID_REG_ECX, 9, 1},
- {"ibs", 0x80000001, NA, CPUID_REG_ECX, 10, 1},
- {"xop", 0x80000001, NA, CPUID_REG_ECX, 11, 1},
- {"skinit", 0x80000001, NA, CPUID_REG_ECX, 12, 1},
- {"wdt", 0x80000001, NA, CPUID_REG_ECX, 13, 1},
- {"lwp", 0x80000001, NA, CPUID_REG_ECX, 15, 1},
- {"fma4", 0x80000001, NA, CPUID_REG_ECX, 16, 1},
{"nodeid", 0x80000001, NA, CPUID_REG_ECX, 19, 1},
- {"tbm", 0x80000001, NA, CPUID_REG_ECX, 21, 1},
- {"topoext", 0x80000001, NA, CPUID_REG_ECX, 22, 1},
{"perfctr_core", 0x80000001, NA, CPUID_REG_ECX, 23, 1},
{"perfctr_nb", 0x80000001, NA, CPUID_REG_ECX, 24, 1},
- {"syscall", 0x80000001, NA, CPUID_REG_EDX, 11, 1},
- {"nx", 0x80000001, NA, CPUID_REG_EDX, 20, 1},
- {"mmxext", 0x80000001, NA, CPUID_REG_EDX, 22, 1},
- {"ffxsr", 0x80000001, NA, CPUID_REG_EDX, 25, 1},
- {"page1gb", 0x80000001, NA, CPUID_REG_EDX, 26, 1},
- {"rdtscp", 0x80000001, NA, CPUID_REG_EDX, 27, 1},
- {"lm", 0x80000001, NA, CPUID_REG_EDX, 29, 1},
- {"3dnowext", 0x80000001, NA, CPUID_REG_EDX, 30, 1},
- {"3dnow", 0x80000001, NA, CPUID_REG_EDX, 31, 1},
-
{"procpkg", 0x00000004, 0, CPUID_REG_EAX, 26, 6},
{"invtsc", 0x80000007, NA, CPUID_REG_EDX, 8, 1},
- {"clzero", 0x80000008, NA, CPUID_REG_EBX, 0, 1},
- {"rstr-fp-err-ptrs", 0x80000008, NA, CPUID_REG_EBX, 2, 1},
- {"wbnoinvd", 0x80000008, NA, CPUID_REG_EBX, 9, 1},
- {"ibpb", 0x80000008, NA, CPUID_REG_EBX, 12, 1},
- {"ibrs", 0x80000008, NA, CPUID_REG_EBX, 14, 1},
- {"amd-stibp", 0x80000008, NA, CPUID_REG_EBX, 15, 1},
- {"ibrs-always", 0x80000008, NA, CPUID_REG_EBX, 16, 1},
- {"stibp-always", 0x80000008, NA, CPUID_REG_EBX, 17, 1},
- {"ibrs-fast", 0x80000008, NA, CPUID_REG_EBX, 18, 1},
- {"ibrs-same-mode", 0x80000008, NA, CPUID_REG_EBX, 19, 1},
- {"no-lmsl", 0x80000008, NA, CPUID_REG_EBX, 20, 1},
{"ppin", 0x80000008, NA, CPUID_REG_EBX, 23, 1},
- {"amd-ssbd", 0x80000008, NA, CPUID_REG_EBX, 24, 1},
- {"virt-ssbd", 0x80000008, NA, CPUID_REG_EBX, 25, 1},
- {"ssb-no", 0x80000008, NA, CPUID_REG_EBX, 26, 1},
- {"psfd", 0x80000008, NA, CPUID_REG_EBX, 28, 1},
{"btc-no", 0x80000008, NA, CPUID_REG_EBX, 29, 1},
- {"ibpb-ret", 0x80000008, NA, CPUID_REG_EBX, 30, 1},
{"nc", 0x80000008, NA, CPUID_REG_ECX, 0, 8},
{"apicidsize", 0x80000008, NA, CPUID_REG_ECX, 12, 4},
{"svm_pausefilt",0x8000000a, NA, CPUID_REG_EDX, 10, 1},
{"lfence+", 0x80000021, NA, CPUID_REG_EAX, 2, 1},
- {"nscb", 0x80000021, NA, CPUID_REG_EAX, 6, 1},
- {"auto-ibrs", 0x80000021, NA, CPUID_REG_EAX, 8, 1},
- {"cpuid-user-dis", 0x80000021, NA, CPUID_REG_EAX, 17, 1},
{"maxhvleaf", 0x40000000, NA, CPUID_REG_EAX, 0, 8},
{NULL, 0, NA, CPUID_REG_INV, 0, 0}
};
+ static const struct feature_name {
+ const char *name;
+ unsigned int bit;
+ } features[] = INIT_FEATURE_NAMES;
+ static const struct {
+ uint32_t leaf, subleaf;
+ unsigned int reg;
+ } feature_to_cpuid[] = {
+ {0x00000001, NA, CPUID_REG_EDX},
+ {0x00000001, NA, CPUID_REG_ECX},
+ {0x80000001, NA, CPUID_REG_EDX},
+ {0x80000001, NA, CPUID_REG_ECX},
+ {0x0000000D, 1, CPUID_REG_EAX},
+ {0x00000007, 0, CPUID_REG_EBX},
+ {0x00000007, 0, CPUID_REG_ECX},
+ {0x80000007, NA, CPUID_REG_EDX},
+ {0x80000008, NA, CPUID_REG_EBX},
+ {0x00000007, 0, CPUID_REG_EDX},
+ {0x00000007, 1, CPUID_REG_EAX},
+ {0x80000021, NA, CPUID_REG_EAX},
+ {0x00000007, 1, CPUID_REG_EBX},
+ {0x00000007, 2, CPUID_REG_EDX},
+ {0x00000007, 1, CPUID_REG_ECX},
+ {0x00000007, 1, CPUID_REG_EDX},
+ { NA, NA, CPUID_REG_INV}, /* MSR_ARCH_CAPS.eax */
+ { NA, NA, CPUID_REG_INV}, /* MSR_ARCH_CAPS.edx */
+ };
#undef NA
char *sep, *val, *endptr;
int i;
const struct cpuid_flags *flag;
+ struct cpuid_flags f;
struct xc_xend_cpuid *entry;
unsigned long num;
char flags[33], *resstr;
+ BUILD_BUG_ON(ARRAY_SIZE(feature_to_cpuid) != FEATURESET_NR_ENTRIES);
+
sep = strchr(str, '=');
if (sep == NULL) {
return 1;
if(!strncmp(str, flag->name, sep - str) && flag->name[sep - str] == 0)
break;
}
+ if (flag->name == NULL) {
+ const struct feature_name *feat;
+ /* Provide a NUL terminated feature name to the search helper. */
+ char *name = strndup(str, sep - str);
+
+ if (name == NULL)
+ return 4;
+
+ feat = bsearch(name, features, ARRAY_SIZE(features), sizeof(features[0]),
+ search_feature);
+ free(name);
+
+ if (feat != NULL) {
+ f.name = feat->name;
+ f.leaf = feature_to_cpuid[feat->bit / 32].leaf;
+ f.subleaf = feature_to_cpuid[feat->bit / 32].subleaf;
+ f.reg = feature_to_cpuid[feat->bit / 32].reg;
+ f.bit = feat->bit % 32;
+ f.length = 1,
+ flag = &f;
+ }
+ }
if (flag->name == NULL) {
return 2;
}