@@ -927,7 +927,7 @@ static CPUState *pc_new_cpu(const char *cpu_model)
env = cpu_init(cpu_model);
if (!env) {
- fprintf(stderr, "Unable to find x86 CPU definition\n");
+ fprintf(stderr, "Unable to support requested x86 CPU definition\n");
exit(1);
}
if ((env->cpuid_features & CPUID_APIC) || smp_cpus > 1) {
@@ -8,7 +8,7 @@
model = "15"
stepping = "3"
feature_edx = "sse2 sse fxsr mmx pat cmov pge sep apic cx8 mce pae msr tsc pse de fpu mtrr clflush mca pse36"
- feature_ecx = "sse3 ssse3"
+ feature_ecx = "sse3 ssse3 x2apic"
extfeature_edx = "fxsr mmx pat cmov pge apic cx8 mce pae msr tsc pse de fpu lm syscall nx"
extfeature_ecx = "lahf_lm"
xlevel = "0x8000000A"
@@ -22,7 +22,7 @@
model = "23"
stepping = "3"
feature_edx = "sse2 sse fxsr mmx pat cmov pge sep apic cx8 mce pae msr tsc pse de fpu mtrr clflush mca pse36"
- feature_ecx = "sse3 cx16 ssse3 sse4.1"
+ feature_ecx = "sse3 cx16 ssse3 sse4.1 x2apic"
extfeature_edx = "fxsr mmx pat cmov pge apic cx8 mce pae msr tsc pse de fpu lm syscall nx"
extfeature_ecx = "lahf_lm"
xlevel = "0x8000000A"
@@ -36,7 +36,7 @@
model = "26"
stepping = "3"
feature_edx = "sse2 sse fxsr mmx pat cmov pge sep apic cx8 mce pae msr tsc pse de fpu mtrr clflush mca pse36"
- feature_ecx = "sse3 cx16 ssse3 sse4.1 sse4.2 popcnt"
+ feature_ecx = "sse3 cx16 ssse3 sse4.1 sse4.2 popcnt x2apic"
extfeature_edx = "fxsr mmx pat cmov pge apic cx8 mce pae msr tsc pse de fpu lm syscall nx"
extfeature_ecx = "lahf_lm"
xlevel = "0x8000000A"
@@ -50,7 +50,7 @@
model = "6"
stepping = "1"
feature_edx = "sse2 sse fxsr mmx pat cmov pge sep apic cx8 mce pae msr tsc pse de fpu mtrr clflush mca pse36"
- feature_ecx = "sse3"
+ feature_ecx = "sse3 x2apic" # x2apic kvm emulated
extfeature_edx = "fxsr mmx pat cmov pge apic cx8 mce pae msr tsc pse de fpu lm syscall nx"
# extfeature_ecx = ""
xlevel = "0x80000008"
@@ -64,7 +64,7 @@
model = "6"
stepping = "1"
feature_edx = "sse2 sse fxsr mmx pat cmov pge sep apic cx8 mce pae msr tsc pse de fpu mtrr clflush mca pse36"
- feature_ecx = "sse3 cx16"
+ feature_ecx = "sse3 cx16 x2apic" # x2apic kvm emulated
extfeature_edx = "fxsr mmx pat cmov pge apic cx8 mce pae msr tsc pse de fpu lm syscall nx rdtscp"
extfeature_ecx = "svm lahf_lm"
xlevel = "0x80000008"
@@ -78,7 +78,7 @@
model = "6"
stepping = "1"
feature_edx = "sse2 sse fxsr mmx pat cmov pge sep apic cx8 mce pae msr tsc pse de fpu mtrr clflush mca pse36"
- feature_ecx = "sse3 cx16 monitor popcnt"
+ feature_ecx = "sse3 cx16 monitor popcnt x2apic" # x2apic kvm emulated
extfeature_edx = "fxsr mmx pat cmov pge apic cx8 mce pae msr tsc pse de fpu lm syscall nx rdtscp"
extfeature_ecx = "svm sse4a abm misalignsse lahf_lm"
xlevel = "0x80000008"
@@ -549,15 +549,40 @@ static int unavailable_host_feature(struct model_features_t *f, uint32_t mask)
return 0;
}
-/* best effort attempt to inform user requested cpu flags aren't making
- * their way to the guest. Note: ft[].check_feat ideally should be
- * specified via a guest_def field to suppress report of extraneous flags.
+/* determine the effective set of cpuid features visible to a guest.
+ * in the case kvm is enabled, we also selectively include features
+ * emulated by the hypervisor
*/
-static int check_features_against_host(x86_def_t *guest_def)
+static void summary_cpuid_features(CPUX86State *env, x86_def_t *hd)
+{
+ struct {
+ uint32_t *pfeat, cmd, reg, mask;
+ } fmap[] = {
+ {&hd->features, 0x00000001, R_EDX, 0},
+ {&hd->ext_features, 0x00000001, R_ECX, CPUID_EXT_X2APIC},
+ {&hd->ext2_features, 0x80000001, R_EDX, 0},
+ {&hd->ext3_features, 0x80000001, R_ECX, 0},
+ {NULL} }, *p;
+
+ cpu_x86_fill_host(hd);
+ if (kvm_enabled()) {
+ for (p = fmap; p->pfeat; ++p) {
+ if (p->mask) {
+ *p->pfeat |= p->mask &
+ kvm_arch_get_supported_cpuid(env, p->cmd, 0, p->reg);
+ }
+ }
+ }
+}
+
+/* inform the user of any requested cpu features (both explicitly requested
+ * flags and implicit cpu model flags) not making their way to the guest
+ */
+static int check_features_against_host(CPUX86State *env, x86_def_t *guest_def)
{
x86_def_t host_def;
uint32_t mask;
- int rv, i;
+ int rv;
struct model_features_t ft[] = {
{&guest_def->features, &host_def.features,
~0, feature_name, 0x00000000},
@@ -566,16 +591,16 @@ static int check_features_against_host(x86_def_t *guest_def)
{&guest_def->ext2_features, &host_def.ext2_features,
~PPRO_FEATURES, ext2_feature_name, 0x80000000},
{&guest_def->ext3_features, &host_def.ext3_features,
- ~CPUID_EXT3_SVM, ext3_feature_name, 0x80000001}};
+ ~CPUID_EXT3_SVM, ext3_feature_name, 0x80000001},
+ {NULL} }, *p;
- cpu_x86_fill_host(&host_def);
- for (rv = 0, i = 0; i < ARRAY_SIZE(ft); ++i)
+ summary_cpuid_features(env, &host_def);
+ for (rv = 0, p = ft; p->guest_feat; ++p)
for (mask = 1; mask; mask <<= 1)
- if (ft[i].check_feat & mask && *ft[i].guest_feat & mask &&
- !(*ft[i].host_feat & mask)) {
- unavailable_host_feature(&ft[i], mask);
- rv = 1;
- }
+ if (mask & p->check_feat & *p->guest_feat & ~*p->host_feat) {
+ unavailable_host_feature(p, mask);
+ rv = 1;
+ }
return rv;
}
@@ -602,6 +627,7 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
if (kvm_enabled() && strcmp(name, "host") == 0) {
cpu_x86_fill_host(x86_cpu_def);
} else if (!def) {
+ fprintf(stderr, "Unknown cpu model: %s\n", name);
goto error;
} else {
memcpy(x86_cpu_def, def, sizeof(*def));
@@ -715,10 +741,6 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
x86_cpu_def->ext3_features &= ~minus_ext3_features;
x86_cpu_def->kvm_features &= ~minus_kvm_features;
x86_cpu_def->svm_features &= ~minus_svm_features;
- if (check_cpuid) {
- if (check_features_against_host(x86_cpu_def) && enforce_cpuid)
- goto error;
- }
free(s);
return 0;
@@ -880,6 +902,11 @@ int cpu_x86_register (CPUX86State *env, const char *cpu_model)
env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
}
}
+ if (check_cpuid) {
+ if (check_features_against_host(env, def) && enforce_cpuid) {
+ return -1;
+ }
+ }
return 0;
}