mirror of https://github.com/xemu-project/xemu.git
X86 queue, 2016-06-14 (v2)
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJXYHcgAAoJECgHk2+YTcWmRoMP/2YZd1wDM1vRxIMjOSH5X26K qJpj8jPpKQKJjQ7pftWlhE8Itufs9UT+C9tebNXH2rpaduPqoNQUQ4GeRonM2Ypi Hzcx8xbX8weX9WAOH35FHj4Xd/R1ZoShGorQjkZfgTsqidU0hW5I5s7cULhCzbT+ r1tA6F+59ujt+nS1ifsETzLK3c2oiAjLC9Ocv36rZfx3SfD74kpFGRzW3rfGMe8P VExhFnZIySfb2aesHR7nmhXmlX1Biy9TLErUjE5EjtCdgv0VDovVAsCBWKHYsPJK s2JTwF7oHbc7wxrVr6P3D/EVww1vsGx4K3vBLbWwagSvgM0E6gg/Z7eub0dDMk0H cR/vfDkxyJUjwbi+qbJM68/mNBIE2e5s7M8aQPt85xqOj7ekiRgQyBgBqLUvSGs7 7CHTg6enkN5QNfZflR+QtTlYWW4Kx/DPwOCCBvmOKYoxN6htFCNnJoyrrXMviqhL ZNyo1kbPw2no9mONGDsCpEhvTLHl8MRIQlnVL8ksFSXsHhXnF8785axQWpQAiPoO +YFV24tSW+IQDbODNl0T04gwGdlDsDIoqxhzsi8zjY9hzdAdy9HIKv0zjsKzLW0h xPCZKhI5uIU7pylRnJhvyt+kCypyT0aQES8PR3u9pGhlUbJQ0J6M87aWhEDAsqZH NPd7R+sAqCub558T1Vr8 =JI9l -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/ehabkost/tags/x86-pull-request' into staging X86 queue, 2016-06-14 (v2) # gpg: Signature made Tue 14 Jun 2016 22:29:04 BST # gpg: using RSA key 0x2807936F984DC5A6 # gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>" # Primary key fingerprint: 5A32 2FD5 ABC4 D3DB ACCF D1AA 2807 936F 984D C5A6 * remotes/ehabkost/tags/x86-pull-request: target-i386: Consolidate calls of object_property_parse() in x86_cpu_parse_featurestr target-i386: Use cpu_generic_init() in cpu_x86_init() target-i386: Move xcc->kvm_required check to realize time target-i386: Remove assert(kvm_enabled()) from host_x86_cpu_initfn() target-i386: Move features logic that requires CPUState to realize time target-i386: Remove xlevel & hv-spinlocks option fixups target-i386: Implement CPUID[0xB] (Extended Topology Enumeration) pc: Add 2.7 machine target-i386: add Skylake-Client cpu model Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
5deaac15bf
|
@ -432,13 +432,25 @@ static void pc_i440fx_machine_options(MachineClass *m)
|
|||
m->default_display = "std";
|
||||
}
|
||||
|
||||
static void pc_i440fx_2_6_machine_options(MachineClass *m)
|
||||
static void pc_i440fx_2_7_machine_options(MachineClass *m)
|
||||
{
|
||||
pc_i440fx_machine_options(m);
|
||||
m->alias = "pc";
|
||||
m->is_default = 1;
|
||||
}
|
||||
|
||||
DEFINE_I440FX_MACHINE(v2_7, "pc-i440fx-2.7", NULL,
|
||||
pc_i440fx_2_7_machine_options);
|
||||
|
||||
|
||||
static void pc_i440fx_2_6_machine_options(MachineClass *m)
|
||||
{
|
||||
pc_i440fx_2_7_machine_options(m);
|
||||
m->is_default = 0;
|
||||
m->alias = NULL;
|
||||
SET_MACHINE_COMPAT(m, PC_COMPAT_2_6);
|
||||
}
|
||||
|
||||
DEFINE_I440FX_MACHINE(v2_6, "pc-i440fx-2.6", NULL,
|
||||
pc_i440fx_2_6_machine_options);
|
||||
|
||||
|
@ -447,8 +459,6 @@ static void pc_i440fx_2_5_machine_options(MachineClass *m)
|
|||
{
|
||||
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
|
||||
pc_i440fx_2_6_machine_options(m);
|
||||
m->alias = NULL;
|
||||
m->is_default = 0;
|
||||
pcmc->save_tsc_khz = false;
|
||||
m->legacy_fw_cfg_order = 1;
|
||||
SET_MACHINE_COMPAT(m, PC_COMPAT_2_5);
|
||||
|
|
|
@ -283,12 +283,22 @@ static void pc_q35_machine_options(MachineClass *m)
|
|||
m->no_floppy = 1;
|
||||
}
|
||||
|
||||
static void pc_q35_2_6_machine_options(MachineClass *m)
|
||||
static void pc_q35_2_7_machine_options(MachineClass *m)
|
||||
{
|
||||
pc_q35_machine_options(m);
|
||||
m->alias = "q35";
|
||||
}
|
||||
|
||||
DEFINE_Q35_MACHINE(v2_7, "pc-q35-2.7", NULL,
|
||||
pc_q35_2_7_machine_options);
|
||||
|
||||
static void pc_q35_2_6_machine_options(MachineClass *m)
|
||||
{
|
||||
pc_q35_2_7_machine_options(m);
|
||||
m->alias = NULL;
|
||||
SET_MACHINE_COMPAT(m, PC_COMPAT_2_6);
|
||||
}
|
||||
|
||||
DEFINE_Q35_MACHINE(v2_6, "pc-q35-2.6", NULL,
|
||||
pc_q35_2_6_machine_options);
|
||||
|
||||
|
@ -296,7 +306,6 @@ static void pc_q35_2_5_machine_options(MachineClass *m)
|
|||
{
|
||||
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
|
||||
pc_q35_2_6_machine_options(m);
|
||||
m->alias = NULL;
|
||||
pcmc->save_tsc_khz = false;
|
||||
m->legacy_fw_cfg_order = 1;
|
||||
SET_MACHINE_COMPAT(m, PC_COMPAT_2_5);
|
||||
|
|
|
@ -356,7 +356,16 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
|
|||
int e820_get_num_entries(void);
|
||||
bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
||||
|
||||
#define PC_COMPAT_2_6 \
|
||||
HW_COMPAT_2_6 \
|
||||
{\
|
||||
.driver = TYPE_X86_CPU,\
|
||||
.property = "cpuid-0xb",\
|
||||
.value = "off",\
|
||||
},
|
||||
|
||||
#define PC_COMPAT_2_5 \
|
||||
PC_COMPAT_2_6 \
|
||||
HW_COMPAT_2_5
|
||||
|
||||
/* Helper for setting model-id for CPU models that changed model-id
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/i386/topology.h"
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
#include "exec/address-spaces.h"
|
||||
#include "hw/hw.h"
|
||||
|
@ -677,6 +678,14 @@ static ObjectClass *x86_cpu_class_by_name(const char *cpu_model)
|
|||
return oc;
|
||||
}
|
||||
|
||||
static char *x86_cpu_class_get_model_name(X86CPUClass *cc)
|
||||
{
|
||||
const char *class_name = object_class_get_name(OBJECT_CLASS(cc));
|
||||
assert(g_str_has_suffix(class_name, X86_CPU_TYPE_SUFFIX));
|
||||
return g_strndup(class_name,
|
||||
strlen(class_name) - strlen(X86_CPU_TYPE_SUFFIX));
|
||||
}
|
||||
|
||||
struct X86CPUDefinition {
|
||||
const char *name;
|
||||
uint32_t level;
|
||||
|
@ -1238,6 +1247,51 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
|||
.xlevel = 0x80000008,
|
||||
.model_id = "Intel Core Processor (Broadwell)",
|
||||
},
|
||||
{
|
||||
.name = "Skylake-Client",
|
||||
.level = 0xd,
|
||||
.vendor = CPUID_VENDOR_INTEL,
|
||||
.family = 6,
|
||||
.model = 94,
|
||||
.stepping = 3,
|
||||
.features[FEAT_1_EDX] =
|
||||
CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
|
||||
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
|
||||
CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
|
||||
CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
|
||||
CPUID_DE | CPUID_FP87,
|
||||
.features[FEAT_1_ECX] =
|
||||
CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
|
||||
CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 |
|
||||
CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
|
||||
CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 |
|
||||
CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE |
|
||||
CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND,
|
||||
.features[FEAT_8000_0001_EDX] =
|
||||
CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
|
||||
CPUID_EXT2_SYSCALL,
|
||||
.features[FEAT_8000_0001_ECX] =
|
||||
CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH,
|
||||
.features[FEAT_7_0_EBX] =
|
||||
CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
|
||||
CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
|
||||
CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
|
||||
CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
|
||||
CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_MPX,
|
||||
/* Missing: XSAVES (not supported by some Linux versions,
|
||||
* including v4.1 to v4.6).
|
||||
* KVM doesn't yet expose any XSAVES state save component,
|
||||
* and the only one defined in Skylake (processor tracing)
|
||||
* probably will block migration anyway.
|
||||
*/
|
||||
.features[FEAT_XSAVE] =
|
||||
CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC |
|
||||
CPUID_XSAVE_XGETBV1,
|
||||
.features[FEAT_6_EAX] =
|
||||
CPUID_6_EAX_ARAT,
|
||||
.xlevel = 0x80000008,
|
||||
.model_id = "Intel Core Processor (Skylake)",
|
||||
},
|
||||
{
|
||||
.name = "Opteron_G1",
|
||||
.level = 5,
|
||||
|
@ -1501,16 +1555,17 @@ static void host_x86_cpu_initfn(Object *obj)
|
|||
CPUX86State *env = &cpu->env;
|
||||
KVMState *s = kvm_state;
|
||||
|
||||
assert(kvm_enabled());
|
||||
|
||||
/* We can't fill the features array here because we don't know yet if
|
||||
* "migratable" is true or false.
|
||||
*/
|
||||
cpu->host_features = true;
|
||||
|
||||
env->cpuid_level = kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX);
|
||||
env->cpuid_xlevel = kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX);
|
||||
env->cpuid_xlevel2 = kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX);
|
||||
/* If KVM is disabled, x86_cpu_realizefn() will report an error later */
|
||||
if (kvm_enabled()) {
|
||||
env->cpuid_level = kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX);
|
||||
env->cpuid_xlevel = kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX);
|
||||
env->cpuid_xlevel2 = kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX);
|
||||
}
|
||||
|
||||
object_property_set_bool(OBJECT(cpu), true, "pmu", &error_abort);
|
||||
}
|
||||
|
@ -1894,6 +1949,14 @@ static inline void feat2prop(char *s)
|
|||
}
|
||||
}
|
||||
|
||||
/* Compatibily hack to maintain legacy +-feat semantic,
|
||||
* where +-feat overwrites any feature set by
|
||||
* feat=on|feat even if the later is parsed after +-feat
|
||||
* (i.e. "-x2apic,x2apic=on" will result in x2apic disabled)
|
||||
*/
|
||||
static FeatureWordArray plus_features = { 0 };
|
||||
static FeatureWordArray minus_features = { 0 };
|
||||
|
||||
/* Parse "+feature,-feature,feature=foo" CPU feature string
|
||||
*/
|
||||
static void x86_cpu_parse_featurestr(CPUState *cs, char *features,
|
||||
|
@ -1901,97 +1964,61 @@ static void x86_cpu_parse_featurestr(CPUState *cs, char *features,
|
|||
{
|
||||
X86CPU *cpu = X86_CPU(cs);
|
||||
char *featurestr; /* Single 'key=value" string being parsed */
|
||||
FeatureWord w;
|
||||
/* Features to be added */
|
||||
FeatureWordArray plus_features = { 0 };
|
||||
/* Features to be removed */
|
||||
FeatureWordArray minus_features = { 0 };
|
||||
uint32_t numvalue;
|
||||
CPUX86State *env = &cpu->env;
|
||||
Error *local_err = NULL;
|
||||
|
||||
featurestr = features ? strtok(features, ",") : NULL;
|
||||
if (!features) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (featurestr) {
|
||||
char *val;
|
||||
for (featurestr = strtok(features, ",");
|
||||
featurestr && !local_err;
|
||||
featurestr = strtok(NULL, ",")) {
|
||||
const char *name;
|
||||
const char *val = NULL;
|
||||
char *eq = NULL;
|
||||
|
||||
/* Compatibility syntax: */
|
||||
if (featurestr[0] == '+') {
|
||||
add_flagname_to_bitmaps(featurestr + 1, plus_features, &local_err);
|
||||
continue;
|
||||
} else if (featurestr[0] == '-') {
|
||||
add_flagname_to_bitmaps(featurestr + 1, minus_features, &local_err);
|
||||
} else if ((val = strchr(featurestr, '='))) {
|
||||
*val = 0; val++;
|
||||
feat2prop(featurestr);
|
||||
if (!strcmp(featurestr, "xlevel")) {
|
||||
char *err;
|
||||
char num[32];
|
||||
continue;
|
||||
}
|
||||
|
||||
numvalue = strtoul(val, &err, 0);
|
||||
if (!*val || *err) {
|
||||
error_setg(errp, "bad numerical value %s", val);
|
||||
return;
|
||||
}
|
||||
if (numvalue < 0x80000000) {
|
||||
error_report("xlevel value shall always be >= 0x80000000"
|
||||
", fixup will be removed in future versions");
|
||||
numvalue += 0x80000000;
|
||||
}
|
||||
snprintf(num, sizeof(num), "%" PRIu32, numvalue);
|
||||
object_property_parse(OBJECT(cpu), num, featurestr, &local_err);
|
||||
} else if (!strcmp(featurestr, "tsc-freq")) {
|
||||
int64_t tsc_freq;
|
||||
char *err;
|
||||
char num[32];
|
||||
|
||||
tsc_freq = qemu_strtosz_suffix_unit(val, &err,
|
||||
QEMU_STRTOSZ_DEFSUFFIX_B, 1000);
|
||||
if (tsc_freq < 0 || *err) {
|
||||
error_setg(errp, "bad numerical value %s", val);
|
||||
return;
|
||||
}
|
||||
snprintf(num, sizeof(num), "%" PRId64, tsc_freq);
|
||||
object_property_parse(OBJECT(cpu), num, "tsc-frequency",
|
||||
&local_err);
|
||||
} else if (!strcmp(featurestr, "hv-spinlocks")) {
|
||||
char *err;
|
||||
const int min = 0xFFF;
|
||||
char num[32];
|
||||
numvalue = strtoul(val, &err, 0);
|
||||
if (!*val || *err) {
|
||||
error_setg(errp, "bad numerical value %s", val);
|
||||
return;
|
||||
}
|
||||
if (numvalue < min) {
|
||||
error_report("hv-spinlocks value shall always be >= 0x%x"
|
||||
", fixup will be removed in future versions",
|
||||
min);
|
||||
numvalue = min;
|
||||
}
|
||||
snprintf(num, sizeof(num), "%" PRId32, numvalue);
|
||||
object_property_parse(OBJECT(cpu), num, featurestr, &local_err);
|
||||
} else {
|
||||
object_property_parse(OBJECT(cpu), val, featurestr, &local_err);
|
||||
}
|
||||
eq = strchr(featurestr, '=');
|
||||
if (eq) {
|
||||
*eq++ = 0;
|
||||
val = eq;
|
||||
} else {
|
||||
feat2prop(featurestr);
|
||||
object_property_parse(OBJECT(cpu), "on", featurestr, &local_err);
|
||||
val = "on";
|
||||
}
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
|
||||
feat2prop(featurestr);
|
||||
name = featurestr;
|
||||
|
||||
/* Special case: */
|
||||
if (!strcmp(name, "tsc-freq")) {
|
||||
int64_t tsc_freq;
|
||||
char *err;
|
||||
char num[32];
|
||||
|
||||
tsc_freq = qemu_strtosz_suffix_unit(val, &err,
|
||||
QEMU_STRTOSZ_DEFSUFFIX_B, 1000);
|
||||
if (tsc_freq < 0 || *err) {
|
||||
error_setg(errp, "bad numerical value %s", val);
|
||||
return;
|
||||
}
|
||||
snprintf(num, sizeof(num), "%" PRId64, tsc_freq);
|
||||
val = num;
|
||||
name = "tsc-frequency";
|
||||
}
|
||||
featurestr = strtok(NULL, ",");
|
||||
|
||||
object_property_parse(OBJECT(cpu), val, name, &local_err);
|
||||
}
|
||||
|
||||
if (cpu->host_features) {
|
||||
for (w = 0; w < FEATURE_WORDS; w++) {
|
||||
env->features[w] =
|
||||
x86_cpu_get_supported_feature_word(w, cpu->migratable);
|
||||
}
|
||||
}
|
||||
|
||||
for (w = 0; w < FEATURE_WORDS; w++) {
|
||||
env->features[w] |= plus_features[w];
|
||||
env->features[w] &= ~minus_features[w];
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2175,7 +2202,6 @@ static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp)
|
|||
X86CPU *cpu_x86_create(const char *cpu_model, Error **errp)
|
||||
{
|
||||
X86CPU *cpu = NULL;
|
||||
X86CPUClass *xcc;
|
||||
ObjectClass *oc;
|
||||
gchar **model_pieces;
|
||||
char *name, *features;
|
||||
|
@ -2194,12 +2220,6 @@ X86CPU *cpu_x86_create(const char *cpu_model, Error **errp)
|
|||
error_setg(&error, "Unable to find CPU definition: %s", name);
|
||||
goto out;
|
||||
}
|
||||
xcc = X86_CPU_CLASS(oc);
|
||||
|
||||
if (xcc->kvm_required && !kvm_enabled()) {
|
||||
error_setg(&error, "CPU model '%s' requires KVM", name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
cpu = X86_CPU(object_new(object_class_get_name(oc)));
|
||||
|
||||
|
@ -2222,25 +2242,7 @@ out:
|
|||
|
||||
X86CPU *cpu_x86_init(const char *cpu_model)
|
||||
{
|
||||
Error *error = NULL;
|
||||
X86CPU *cpu;
|
||||
|
||||
cpu = cpu_x86_create(cpu_model, &error);
|
||||
if (error) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
object_property_set_bool(OBJECT(cpu), true, "realized", &error);
|
||||
|
||||
out:
|
||||
if (error) {
|
||||
error_report_err(error);
|
||||
if (cpu != NULL) {
|
||||
object_unref(OBJECT(cpu));
|
||||
cpu = NULL;
|
||||
}
|
||||
}
|
||||
return cpu;
|
||||
return X86_CPU(cpu_generic_init(TYPE_X86_CPU, cpu_model));
|
||||
}
|
||||
|
||||
static void x86_cpu_cpudef_class_init(ObjectClass *oc, void *data)
|
||||
|
@ -2447,6 +2449,36 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
|||
*edx = 0;
|
||||
}
|
||||
break;
|
||||
case 0xB:
|
||||
/* Extended Topology Enumeration Leaf */
|
||||
if (!cpu->enable_cpuid_0xb) {
|
||||
*eax = *ebx = *ecx = *edx = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
*ecx = count & 0xff;
|
||||
*edx = cpu->apic_id;
|
||||
|
||||
switch (count) {
|
||||
case 0:
|
||||
*eax = apicid_core_offset(smp_cores, smp_threads);
|
||||
*ebx = smp_threads;
|
||||
*ecx |= CPUID_TOPOLOGY_LEVEL_SMT;
|
||||
break;
|
||||
case 1:
|
||||
*eax = apicid_pkg_offset(smp_cores, smp_threads);
|
||||
*ebx = smp_cores * smp_threads;
|
||||
*ecx |= CPUID_TOPOLOGY_LEVEL_CORE;
|
||||
break;
|
||||
default:
|
||||
*eax = 0;
|
||||
*ebx = 0;
|
||||
*ecx |= CPUID_TOPOLOGY_LEVEL_INVALID;
|
||||
}
|
||||
|
||||
assert(!(*eax & ~0x1f));
|
||||
*ebx &= 0xffff; /* The count doesn't need to be reliable. */
|
||||
break;
|
||||
case 0xD: {
|
||||
KVMState *s = cs->kvm_state;
|
||||
uint64_t ena_mask;
|
||||
|
@ -2874,12 +2906,37 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
|
|||
CPUX86State *env = &cpu->env;
|
||||
Error *local_err = NULL;
|
||||
static bool ht_warned;
|
||||
FeatureWord w;
|
||||
|
||||
if (xcc->kvm_required && !kvm_enabled()) {
|
||||
char *name = x86_cpu_class_get_model_name(xcc);
|
||||
error_setg(&local_err, "CPU model '%s' requires KVM", name);
|
||||
g_free(name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (cpu->apic_id < 0) {
|
||||
error_setg(errp, "apic-id property was not initialized properly");
|
||||
return;
|
||||
}
|
||||
|
||||
/*TODO: cpu->host_features incorrectly overwrites features
|
||||
* set using "feat=on|off". Once we fix this, we can convert
|
||||
* plus_features & minus_features to global properties
|
||||
* inside x86_cpu_parse_featurestr() too.
|
||||
*/
|
||||
if (cpu->host_features) {
|
||||
for (w = 0; w < FEATURE_WORDS; w++) {
|
||||
env->features[w] =
|
||||
x86_cpu_get_supported_feature_word(w, cpu->migratable);
|
||||
}
|
||||
}
|
||||
|
||||
for (w = 0; w < FEATURE_WORDS; w++) {
|
||||
cpu->env.features[w] |= plus_features[w];
|
||||
cpu->env.features[w] &= ~minus_features[w];
|
||||
}
|
||||
|
||||
if (env->features[FEAT_7_0_EBX] && env->cpuid_level < 7) {
|
||||
env->cpuid_level = 7;
|
||||
}
|
||||
|
@ -3206,6 +3263,7 @@ static Property x86_cpu_properties[] = {
|
|||
DEFINE_PROP_UINT32("xlevel", X86CPU, env.cpuid_xlevel, 0),
|
||||
DEFINE_PROP_UINT32("xlevel2", X86CPU, env.cpuid_xlevel2, 0),
|
||||
DEFINE_PROP_STRING("hv-vendor-id", X86CPU, hyperv_vendor_id),
|
||||
DEFINE_PROP_BOOL("cpuid-0xb", X86CPU, enable_cpuid_0xb, true),
|
||||
DEFINE_PROP_END_OF_LIST()
|
||||
};
|
||||
|
||||
|
|
|
@ -636,6 +636,11 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
|
|||
#define CPUID_MWAIT_IBE (1U << 1) /* Interrupts can exit capability */
|
||||
#define CPUID_MWAIT_EMX (1U << 0) /* enumeration supported */
|
||||
|
||||
/* CPUID[0xB].ECX level types */
|
||||
#define CPUID_TOPOLOGY_LEVEL_INVALID (0U << 8)
|
||||
#define CPUID_TOPOLOGY_LEVEL_SMT (1U << 8)
|
||||
#define CPUID_TOPOLOGY_LEVEL_CORE (2U << 8)
|
||||
|
||||
#ifndef HYPERV_SPINLOCK_NEVER_RETRY
|
||||
#define HYPERV_SPINLOCK_NEVER_RETRY 0xFFFFFFFF
|
||||
#endif
|
||||
|
@ -1173,6 +1178,9 @@ struct X86CPU {
|
|||
*/
|
||||
bool enable_pmu;
|
||||
|
||||
/* Compatibility bits for old machine types: */
|
||||
bool enable_cpuid_0xb;
|
||||
|
||||
/* in order to simplify APIC support, we leave this pointer to the
|
||||
user */
|
||||
struct DeviceState *apic_state;
|
||||
|
|
Loading…
Reference in New Issue