#include "sysemu/sysemu.h"
#include "hw/qdev-properties.h"
-#include "hw/cpu/icc_bus.h"
#ifndef CONFIG_USER_ONLY
#include "exec/address-spaces.h"
#include "hw/xen/xen.h"
static const char *cpuid_7_0_ebx_feature_name[] = {
"fsgsbase", "tsc_adjust", NULL, "bmi1", "hle", "avx2", NULL, "smep",
"bmi2", "erms", "invpcid", "rtm", NULL, NULL, "mpx", NULL,
- "avx512f", NULL, "rdseed", "adx", "smap", NULL, NULL, NULL,
- NULL, NULL, "avx512pf", "avx512er", "avx512cd", NULL, NULL, NULL,
+ "avx512f", NULL, "rdseed", "adx", "smap", NULL, "pcommit", "clflushopt",
+ "clwb", NULL, "avx512pf", "avx512er", "avx512cd", NULL, NULL, NULL,
+};
+
+static const char *cpuid_7_0_ecx_feature_name[] = {
+ NULL, NULL, NULL, "pku",
+ "ospke", NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
};
static const char *cpuid_apm_edx_feature_name[] = {
CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC | CPUID_SEP | \
CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
CPUID_PSE36 | CPUID_CLFLUSH | CPUID_ACPI | CPUID_MMX | \
- CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS)
+ CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS | CPUID_DE)
/* partly implemented:
CPUID_MTRR, CPUID_MCA, CPUID_CLFLUSH (needed for Win64) */
/* missing:
#define TCG_SVM_FEATURES 0
#define TCG_KVM_FEATURES 0
#define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP | \
- CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX)
+ CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX | \
+ CPUID_7_0_EBX_PCOMMIT | CPUID_7_0_EBX_CLFLUSHOPT | \
+ CPUID_7_0_EBX_CLWB)
/* missing:
CPUID_7_0_EBX_FSGSBASE, CPUID_7_0_EBX_HLE, CPUID_7_0_EBX_AVX2,
CPUID_7_0_EBX_ERMS, CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM,
CPUID_7_0_EBX_RDSEED */
+#define TCG_7_0_ECX_FEATURES 0
#define TCG_APM_FEATURES 0
#define TCG_6_EAX_FEATURES CPUID_6_EAX_ARAT
.cpuid_reg = R_EBX,
.tcg_features = TCG_7_0_EBX_FEATURES,
},
+ [FEAT_7_0_ECX] = {
+ .feat_names = cpuid_7_0_ecx_feature_name,
+ .cpuid_eax = 7,
+ .cpuid_needs_ecx = true, .cpuid_ecx = 0,
+ .cpuid_reg = R_ECX,
+ .tcg_features = TCG_7_0_ECX_FEATURES,
+ },
[FEAT_8000_0007_EDX] = {
.feat_names = cpuid_apm_edx_feature_name,
.cpuid_eax = 0x80000007,
.offset = 0x480, .size = 0x200 },
[7] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F,
.offset = 0x680, .size = 0x400 },
+ [9] = { .feature = FEAT_7_0_ECX, .bits = CPUID_7_0_ECX_PKU,
+ .offset = 0xA80, .size = 0x8 },
};
const char *get_register_name_32(unsigned int reg)
return x86_reg_info_32[reg].name;
}
-/* KVM-specific features that are automatically added to all CPU models
- * when KVM is enabled.
- */
-static uint32_t kvm_default_features[FEATURE_WORDS] = {
- [FEAT_KVM] = (1 << KVM_FEATURE_CLOCKSOURCE) |
- (1 << KVM_FEATURE_NOP_IO_DELAY) |
- (1 << KVM_FEATURE_CLOCKSOURCE2) |
- (1 << KVM_FEATURE_ASYNC_PF) |
- (1 << KVM_FEATURE_STEAL_TIME) |
- (1 << KVM_FEATURE_PV_EOI) |
- (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT),
- [FEAT_1_ECX] = CPUID_EXT_X2APIC,
-};
-
-/* Features that are not added by default to any CPU model when KVM is enabled.
- */
-static uint32_t kvm_default_unset_features[FEATURE_WORDS] = {
- [FEAT_1_EDX] = CPUID_ACPI,
- [FEAT_1_ECX] = CPUID_EXT_MONITOR,
- [FEAT_8000_0001_ECX] = CPUID_EXT3_SVM,
-};
-
-void x86_cpu_compat_kvm_no_autoenable(FeatureWord w, uint32_t features)
-{
- kvm_default_features[w] &= ~features;
-}
-
-void x86_cpu_compat_kvm_no_autodisable(FeatureWord w, uint32_t features)
-{
- kvm_default_unset_features[w] &= ~features;
-}
-
/*
* Returns the set of feature flags that are supported and migratable by
* QEMU, for a given FeatureWord.
int stepping;
FeatureWordArray features;
char model_id[48];
- bool cache_info_passthrough;
};
static X86CPUDefinition builtin_x86_defs[] = {
{
.name = "qemu64",
- .level = 4,
+ .level = 0xd,
.vendor = CPUID_VENDOR_AMD,
.family = 6,
.model = 6,
CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
CPUID_PSE36,
.features[FEAT_1_ECX] =
- CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT,
+ CPUID_EXT_SSE3 | CPUID_EXT_CX16,
.features[FEAT_8000_0001_EDX] =
CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
.features[FEAT_8000_0001_ECX] =
- CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
- CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
+ CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM,
.xlevel = 0x8000000A,
},
{
},
{
.name = "kvm64",
- .level = 5,
+ .level = 0xd,
.vendor = CPUID_VENDOR_INTEL,
.family = 15,
.model = 6,
.features[FEAT_1_EDX] =
PPRO_FEATURES,
.features[FEAT_1_ECX] =
- CPUID_EXT_SSE3 | CPUID_EXT_POPCNT,
+ CPUID_EXT_SSE3,
.xlevel = 0x80000004,
},
{
},
{
.name = "pentium3",
- .level = 2,
+ .level = 3,
.vendor = CPUID_VENDOR_INTEL,
.family = 6,
.model = 7,
},
{
.name = "n270",
- /* original is on level 10 */
- .level = 5,
+ .level = 10,
.vendor = CPUID_VENDOR_INTEL,
.family = 6,
.model = 28,
CPUID_EXT2_NX,
.features[FEAT_8000_0001_ECX] =
CPUID_EXT3_LAHF_LM,
- .xlevel = 0x8000000A,
+ .xlevel = 0x80000008,
.model_id = "Intel(R) Atom(TM) CPU N270 @ 1.60GHz",
},
{
.name = "Conroe",
- .level = 4,
+ .level = 10,
.vendor = CPUID_VENDOR_INTEL,
.family = 6,
.model = 15,
CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL,
.features[FEAT_8000_0001_ECX] =
CPUID_EXT3_LAHF_LM,
- .xlevel = 0x8000000A,
+ .xlevel = 0x80000008,
.model_id = "Intel Celeron_4x0 (Conroe/Merom Class Core 2)",
},
{
.name = "Penryn",
- .level = 4,
+ .level = 10,
.vendor = CPUID_VENDOR_INTEL,
.family = 6,
.model = 23,
CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL,
.features[FEAT_8000_0001_ECX] =
CPUID_EXT3_LAHF_LM,
- .xlevel = 0x8000000A,
+ .xlevel = 0x80000008,
.model_id = "Intel Core 2 Duo P9xxx (Penryn Class Core 2)",
},
{
.name = "Nehalem",
- .level = 4,
+ .level = 11,
.vendor = CPUID_VENDOR_INTEL,
.family = 6,
.model = 26,
CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
.features[FEAT_8000_0001_ECX] =
CPUID_EXT3_LAHF_LM,
- .xlevel = 0x8000000A,
+ .xlevel = 0x80000008,
.model_id = "Intel Core i7 9xx (Nehalem Class Core i7)",
},
{
CPUID_EXT3_LAHF_LM,
.features[FEAT_6_EAX] =
CPUID_6_EAX_ARAT,
- .xlevel = 0x8000000A,
+ .xlevel = 0x80000008,
.model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)",
},
{
CPUID_XSAVE_XSAVEOPT,
.features[FEAT_6_EAX] =
CPUID_6_EAX_ARAT,
- .xlevel = 0x8000000A,
+ .xlevel = 0x80000008,
.model_id = "Intel Xeon E312xx (Sandy Bridge)",
},
{
CPUID_XSAVE_XSAVEOPT,
.features[FEAT_6_EAX] =
CPUID_6_EAX_ARAT,
- .xlevel = 0x8000000A,
+ .xlevel = 0x80000008,
.model_id = "Intel Xeon E3-12xx v2 (Ivy Bridge)",
},
{
CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
CPUID_EXT2_SYSCALL,
.features[FEAT_8000_0001_ECX] =
- CPUID_EXT3_LAHF_LM,
+ CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM,
.features[FEAT_7_0_EBX] =
CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
CPUID_XSAVE_XSAVEOPT,
.features[FEAT_6_EAX] =
CPUID_6_EAX_ARAT,
- .xlevel = 0x8000000A,
+ .xlevel = 0x80000008,
.model_id = "Intel Core Processor (Haswell, no TSX)",
}, {
.name = "Haswell",
CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
CPUID_EXT2_SYSCALL,
.features[FEAT_8000_0001_ECX] =
- CPUID_EXT3_LAHF_LM,
+ CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM,
.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_XSAVE_XSAVEOPT,
.features[FEAT_6_EAX] =
CPUID_6_EAX_ARAT,
- .xlevel = 0x8000000A,
+ .xlevel = 0x80000008,
.model_id = "Intel Core Processor (Haswell)",
},
{
CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
CPUID_EXT2_SYSCALL,
.features[FEAT_8000_0001_ECX] =
- CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH,
+ 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_AVX2 | CPUID_7_0_EBX_SMEP |
CPUID_XSAVE_XSAVEOPT,
.features[FEAT_6_EAX] =
CPUID_6_EAX_ARAT,
- .xlevel = 0x8000000A,
+ .xlevel = 0x80000008,
.model_id = "Intel Core Processor (Broadwell, no TSX)",
},
{
CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
CPUID_EXT2_SYSCALL,
.features[FEAT_8000_0001_ECX] =
- CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH,
+ 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_XSAVE_XSAVEOPT,
.features[FEAT_6_EAX] =
CPUID_6_EAX_ARAT,
- .xlevel = 0x8000000A,
+ .xlevel = 0x80000008,
.model_id = "Intel Core Processor (Broadwell)",
},
{
CPUID_DE | CPUID_FP87,
.features[FEAT_1_ECX] =
CPUID_EXT_CX16 | CPUID_EXT_SSE3,
+ /* Missing: CPUID_EXT2_RDTSCP */
.features[FEAT_8000_0001_EDX] =
- CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_FXSR |
+ CPUID_EXT2_LM | CPUID_EXT2_FXSR |
CPUID_EXT2_MMX | CPUID_EXT2_NX | CPUID_EXT2_PSE36 |
CPUID_EXT2_PAT | CPUID_EXT2_CMOV | CPUID_EXT2_MCA |
CPUID_EXT2_PGE | CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL |
.features[FEAT_1_ECX] =
CPUID_EXT_POPCNT | CPUID_EXT_CX16 | CPUID_EXT_MONITOR |
CPUID_EXT_SSE3,
+ /* Missing: CPUID_EXT2_RDTSCP */
.features[FEAT_8000_0001_EDX] =
- CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_FXSR |
+ CPUID_EXT2_LM | CPUID_EXT2_FXSR |
CPUID_EXT2_MMX | CPUID_EXT2_NX | CPUID_EXT2_PSE36 |
CPUID_EXT2_PAT | CPUID_EXT2_CMOV | CPUID_EXT2_MCA |
CPUID_EXT2_PGE | CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL |
CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ |
CPUID_EXT_SSE3,
+ /* Missing: CPUID_EXT2_RDTSCP */
.features[FEAT_8000_0001_EDX] =
- CPUID_EXT2_LM | CPUID_EXT2_RDTSCP |
+ CPUID_EXT2_LM |
CPUID_EXT2_PDPE1GB | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT |
CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE |
CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 |
CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_FMA |
CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3,
+ /* Missing: CPUID_EXT2_RDTSCP */
.features[FEAT_8000_0001_EDX] =
- CPUID_EXT2_LM | CPUID_EXT2_RDTSCP |
+ CPUID_EXT2_LM |
CPUID_EXT2_PDPE1GB | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT |
CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE |
},
};
-/**
- * x86_cpu_compat_set_features:
- * @cpu_model: CPU model name to be changed. If NULL, all CPU models are changed
- * @w: Identifies the feature word to be changed.
- * @feat_add: Feature bits to be added to feature word
- * @feat_remove: Feature bits to be removed from feature word
- *
- * Change CPU model feature bits for compatibility.
- *
- * This function may be used by machine-type compatibility functions
- * to enable or disable feature bits on specific CPU models.
+typedef struct PropValue {
+ const char *prop, *value;
+} PropValue;
+
+/* KVM-specific features that are automatically added/removed
+ * from all CPU models when KVM is enabled.
*/
-void x86_cpu_compat_set_features(const char *cpu_model, FeatureWord w,
- uint32_t feat_add, uint32_t feat_remove)
+static PropValue kvm_default_props[] = {
+ { "kvmclock", "on" },
+ { "kvm-nopiodelay", "on" },
+ { "kvm-asyncpf", "on" },
+ { "kvm-steal-time", "on" },
+ { "kvm-pv-eoi", "on" },
+ { "kvmclock-stable-bit", "on" },
+ { "x2apic", "on" },
+ { "acpi", "off" },
+ { "monitor", "off" },
+ { "svm", "off" },
+ { NULL, NULL },
+};
+
+void x86_cpu_change_kvm_default(const char *prop, const char *value)
{
- X86CPUDefinition *def;
- int i;
- for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) {
- def = &builtin_x86_defs[i];
- if (!cpu_model || !strcmp(cpu_model, def->name)) {
- def->features[w] |= feat_add;
- def->features[w] &= ~feat_remove;
+ PropValue *pv;
+ for (pv = kvm_default_props; pv->prop; pv++) {
+ if (!strcmp(pv->prop, prop)) {
+ pv->value = value;
+ break;
}
}
+
+ /* It is valid to call this function only for properties that
+ * are already present in the kvm_default_props table.
+ */
+ assert(pv->prop);
}
static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w,
static Property host_x86_cpu_properties[] = {
DEFINE_PROP_BOOL("migratable", X86CPU, migratable, true),
+ DEFINE_PROP_BOOL("host-cache-info", X86CPU, cache_info_passthrough, false),
DEFINE_PROP_END_OF_LIST()
};
cpu_x86_fill_model_id(host_cpudef.model_id);
xcc->cpu_def = &host_cpudef;
- host_cpudef.cache_info_passthrough = true;
/* level, xlevel, xlevel2, and the feature words are initialized on
* instance_init, because they require KVM to be initialized.
*/
dc->props = host_x86_cpu_properties;
+ /* Reason: host_x86_cpu_initfn() dies when !kvm_enabled() */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static void host_x86_cpu_initfn(Object *obj)
int i;
for (i = 0; i < 32; ++i) {
- if (1 << i & mask) {
+ if ((1UL << i) & mask) {
const char *reg = get_register_name_32(f->cpuid_reg);
assert(reg);
fprintf(stderr, "warning: %s doesn't support requested feature: "
}
}
-static void x86_cpuid_version_get_family(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
+static void x86_cpuid_version_get_family(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
{
X86CPU *cpu = X86_CPU(obj);
CPUX86State *env = &cpu->env;
if (value == 0xf) {
value += (env->cpuid_version >> 20) & 0xff;
}
- visit_type_int(v, &value, name, errp);
+ visit_type_int(v, name, &value, errp);
}
-static void x86_cpuid_version_set_family(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
+static void x86_cpuid_version_set_family(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
{
X86CPU *cpu = X86_CPU(obj);
CPUX86State *env = &cpu->env;
Error *local_err = NULL;
int64_t value;
- visit_type_int(v, &value, name, &local_err);
+ visit_type_int(v, name, &value, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
}
-static void x86_cpuid_version_get_model(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
+static void x86_cpuid_version_get_model(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
{
X86CPU *cpu = X86_CPU(obj);
CPUX86State *env = &cpu->env;
value = (env->cpuid_version >> 4) & 0xf;
value |= ((env->cpuid_version >> 16) & 0xf) << 4;
- visit_type_int(v, &value, name, errp);
+ visit_type_int(v, name, &value, errp);
}
-static void x86_cpuid_version_set_model(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
+static void x86_cpuid_version_set_model(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
{
X86CPU *cpu = X86_CPU(obj);
CPUX86State *env = &cpu->env;
Error *local_err = NULL;
int64_t value;
- visit_type_int(v, &value, name, &local_err);
+ visit_type_int(v, name, &value, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
static void x86_cpuid_version_get_stepping(Object *obj, Visitor *v,
- void *opaque, const char *name,
+ const char *name, void *opaque,
Error **errp)
{
X86CPU *cpu = X86_CPU(obj);
int64_t value;
value = env->cpuid_version & 0xf;
- visit_type_int(v, &value, name, errp);
+ visit_type_int(v, name, &value, errp);
}
static void x86_cpuid_version_set_stepping(Object *obj, Visitor *v,
- void *opaque, const char *name,
+ const char *name, void *opaque,
Error **errp)
{
X86CPU *cpu = X86_CPU(obj);
Error *local_err = NULL;
int64_t value;
- visit_type_int(v, &value, name, &local_err);
+ visit_type_int(v, name, &value, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
}
-static void x86_cpuid_get_tsc_freq(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
+static void x86_cpuid_get_tsc_freq(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
{
X86CPU *cpu = X86_CPU(obj);
int64_t value;
value = cpu->env.tsc_khz * 1000;
- visit_type_int(v, &value, name, errp);
+ visit_type_int(v, name, &value, errp);
}
-static void x86_cpuid_set_tsc_freq(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
+static void x86_cpuid_set_tsc_freq(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
{
X86CPU *cpu = X86_CPU(obj);
const int64_t min = 0;
Error *local_err = NULL;
int64_t value;
- visit_type_int(v, &value, name, &local_err);
+ visit_type_int(v, name, &value, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
return;
}
- cpu->env.tsc_khz = value / 1000;
+ cpu->env.tsc_khz = cpu->env.user_tsc_khz = value / 1000;
}
-static void x86_cpuid_get_apic_id(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
+static void x86_cpuid_get_apic_id(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
{
X86CPU *cpu = X86_CPU(obj);
int64_t value = cpu->apic_id;
- visit_type_int(v, &value, name, errp);
+ visit_type_int(v, name, &value, errp);
}
-static void x86_cpuid_set_apic_id(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
+static void x86_cpuid_set_apic_id(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
{
X86CPU *cpu = X86_CPU(obj);
DeviceState *dev = DEVICE(obj);
return;
}
- visit_type_int(v, &value, name, &error);
+ visit_type_int(v, name, &value, &error);
if (error) {
error_propagate(errp, error);
return;
}
/* Generic getter for "feature-words" and "filtered-features" properties */
-static void x86_cpu_get_feature_words(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
+static void x86_cpu_get_feature_words(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
{
uint32_t *array = (uint32_t *)opaque;
FeatureWord w;
list = &list_entries[w];
}
- visit_type_X86CPUFeatureWordInfoList(v, &list, "feature-words", &err);
+ visit_type_X86CPUFeatureWordInfoList(v, "feature-words", &list, &err);
error_propagate(errp, err);
}
-static void x86_get_hv_spinlocks(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
+static void x86_get_hv_spinlocks(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
{
X86CPU *cpu = X86_CPU(obj);
int64_t value = cpu->hyperv_spinlock_attempts;
- visit_type_int(v, &value, name, errp);
+ visit_type_int(v, name, &value, errp);
}
-static void x86_set_hv_spinlocks(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
+static void x86_set_hv_spinlocks(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
{
const int64_t min = 0xFFF;
const int64_t max = UINT_MAX;
Error *err = NULL;
int64_t value;
- visit_type_int(v, &value, name, &err);
+ visit_type_int(v, name, &value, &err);
if (err) {
error_propagate(errp, err);
return;
char *err;
char num[32];
- tsc_freq = strtosz_suffix_unit(val, &err,
- STRTOSZ_DEFSUFFIX_B, 1000);
+ 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;
return rv;
}
+static void x86_cpu_apply_props(X86CPU *cpu, PropValue *props)
+{
+ PropValue *pv;
+ for (pv = props; pv->prop; pv++) {
+ if (!pv->value) {
+ continue;
+ }
+ object_property_parse(OBJECT(cpu), pv->value, pv->prop,
+ &error_abort);
+ }
+}
+
/* Load data from X86CPUDefinition
*/
static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp)
object_property_set_int(OBJECT(cpu), def->stepping, "stepping", errp);
object_property_set_int(OBJECT(cpu), def->xlevel, "xlevel", errp);
object_property_set_int(OBJECT(cpu), def->xlevel2, "xlevel2", errp);
- cpu->cache_info_passthrough = def->cache_info_passthrough;
object_property_set_str(OBJECT(cpu), def->model_id, "model-id", errp);
for (w = 0; w < FEATURE_WORDS; w++) {
env->features[w] = def->features[w];
/* Special cases not set in the X86CPUDefinition structs: */
if (kvm_enabled()) {
- FeatureWord w;
- for (w = 0; w < FEATURE_WORDS; w++) {
- env->features[w] |= kvm_default_features[w];
- env->features[w] &= ~kvm_default_unset_features[w];
- }
+ x86_cpu_apply_props(cpu, kvm_default_props);
}
env->features[FEAT_1_ECX] |= CPUID_EXT_HYPERVISOR;
pstrcpy(def->model_id, sizeof(def->model_id),
"QEMU Virtual CPU version ");
pstrcat(def->model_id, sizeof(def->model_id),
- qemu_get_version());
+ qemu_hw_version());
break;
}
}
if (count == 0) {
*eax = 0; /* Maximum ECX value for sub-leaves */
*ebx = env->features[FEAT_7_0_EBX]; /* Feature flags */
- *ecx = 0; /* Reserved */
+ *ecx = env->features[FEAT_7_0_ECX]; /* Feature flags */
*edx = 0; /* Reserved */
} else {
*eax = 0;
#ifndef CONFIG_USER_ONLY
static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
{
- DeviceState *dev = DEVICE(cpu);
APICCommonState *apic;
const char *apic_type = "apic";
- if (kvm_irqchip_in_kernel()) {
+ if (kvm_apic_in_kernel()) {
apic_type = "kvm-apic";
} else if (xen_enabled()) {
apic_type = "xen-apic";
}
- cpu->apic_state = qdev_try_create(qdev_get_parent_bus(dev), apic_type);
- if (cpu->apic_state == NULL) {
- error_setg(errp, "APIC device '%s' could not be created", apic_type);
- return;
- }
+ cpu->apic_state = DEVICE(object_new(apic_type));
object_property_add_child(OBJECT(cpu), "apic",
OBJECT(cpu->apic_state), NULL);
/* TODO: convert to link<> */
apic = APIC_COMMON(cpu->apic_state);
apic->cpu = cpu;
+ apic->apicbase = APIC_DEFAULT_ADDRESS | MSR_IA32_APICBASE_ENABLE;
}
static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
{
+ APICCommonState *apic;
+ static bool apic_mmio_map_once;
+
if (cpu->apic_state == NULL) {
return;
}
object_property_set_bool(OBJECT(cpu->apic_state), true, "realized",
errp);
+
+ /* Map APIC MMIO area */
+ apic = APIC_COMMON(cpu->apic_state);
+ if (!apic_mmio_map_once) {
+ memory_region_add_subregion_overlap(get_system_memory(),
+ apic->apicbase &
+ MSR_IA32_APICBASE_BASE,
+ &apic->io_memory,
+ 0x1000);
+ apic_mmio_map_once = true;
+ }
}
static void x86_cpu_machine_done(Notifier *n, void *unused)
#ifndef CONFIG_USER_ONLY
if (tcg_enabled()) {
+ AddressSpace *newas = g_new(AddressSpace, 1);
+
cpu->cpu_as_mem = g_new(MemoryRegion, 1);
cpu->cpu_as_root = g_new(MemoryRegion, 1);
- cs->as = g_new(AddressSpace, 1);
/* Outer container... */
memory_region_init(cpu->cpu_as_root, OBJECT(cpu), "memory", ~0ull);
get_system_memory(), 0, ~0ull);
memory_region_add_subregion_overlap(cpu->cpu_as_root, 0, cpu->cpu_as_mem, 0);
memory_region_set_enabled(cpu->cpu_as_mem, true);
- address_space_init(cs->as, cpu->cpu_as_root, "CPU");
+ address_space_init(newas, cpu->cpu_as_root, "CPU");
+ cs->num_ases = 1;
+ cpu_address_space_init(cs, newas, 0);
/* ... SMRAM with higher priority, linked from /machine/smram. */
cpu->machine_done.notify = x86_cpu_machine_done;
uint32_t mask;
} BitProperty;
-static void x86_cpu_get_bit_prop(Object *obj,
- struct Visitor *v,
- void *opaque,
- const char *name,
- Error **errp)
+static void x86_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
{
BitProperty *fp = opaque;
bool value = (*fp->ptr & fp->mask) == fp->mask;
- visit_type_bool(v, &value, name, errp);
+ visit_type_bool(v, name, &value, errp);
}
-static void x86_cpu_set_bit_prop(Object *obj,
- struct Visitor *v,
- void *opaque,
- const char *name,
- Error **errp)
+static void x86_cpu_set_bit_prop(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
BitProperty *fp = opaque;
return;
}
- visit_type_bool(v, &value, name, &local_err);
+ visit_type_bool(v, name, &value, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
/* init various static tables used in TCG mode */
if (tcg_enabled() && !inited) {
inited = 1;
- optimize_flags_init();
+ tcg_x86_init();
}
}
X86CPU *cpu = X86_CPU(cs);
CPUX86State *env = &cpu->env;
-#if !defined(CONFIG_USER_ONLY)
- if (cs->interrupt_request & CPU_INTERRUPT_POLL) {
- apic_poll_irq(cpu->apic_state);
- cpu_reset_interrupt(cs, CPU_INTERRUPT_POLL);
- }
-#endif
-
- return ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
+ return ((cs->interrupt_request & (CPU_INTERRUPT_HARD |
+ CPU_INTERRUPT_POLL)) &&
(env->eflags & IF_MASK)) ||
(cs->interrupt_request & (CPU_INTERRUPT_NMI |
CPU_INTERRUPT_INIT |
DEFINE_PROP_BOOL("hv-relaxed", X86CPU, hyperv_relaxed_timing, false),
DEFINE_PROP_BOOL("hv-vapic", X86CPU, hyperv_vapic, false),
DEFINE_PROP_BOOL("hv-time", X86CPU, hyperv_time, false),
- DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, false),
+ DEFINE_PROP_BOOL("hv-crash", X86CPU, hyperv_crash, false),
+ DEFINE_PROP_BOOL("hv-reset", X86CPU, hyperv_reset, false),
+ DEFINE_PROP_BOOL("hv-vpindex", X86CPU, hyperv_vpindex, false),
+ DEFINE_PROP_BOOL("hv-runtime", X86CPU, hyperv_runtime, false),
+ DEFINE_PROP_BOOL("hv-synic", X86CPU, hyperv_synic, false),
+ DEFINE_PROP_BOOL("hv-stimer", X86CPU, hyperv_stimer, false),
+ DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, true),
DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false),
DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true),
DEFINE_PROP_UINT32("level", X86CPU, env.cpuid_level, 0),
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_END_OF_LIST()
};
xcc->parent_realize = dc->realize;
dc->realize = x86_cpu_realizefn;
- dc->bus_type = TYPE_ICC_BUS;
dc->props = x86_cpu_properties;
xcc->parent_reset = cc->reset;
#endif
cc->cpu_exec_enter = x86_cpu_exec_enter;
cc->cpu_exec_exit = x86_cpu_exec_exit;
+
+ /*
+ * Reason: x86_cpu_initfn() calls cpu_exec_init(), which saves the
+ * object in cpus -> dangling pointer after final object_unref().
+ */
+ dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo x86_cpu_type_info = {