summaryrefslogtreecommitdiff
path: root/target-i386/cpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-i386/cpu.c')
-rw-r--r--target-i386/cpu.c108
1 files changed, 64 insertions, 44 deletions
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index bb98f6defc..967529a46f 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -354,9 +354,6 @@ typedef struct model_features_t {
FeatureWord feat_word;
} model_features_t;
-int check_cpuid = 0;
-int enforce_cpuid = 0;
-
static uint32_t kvm_default_features = (1 << KVM_FEATURE_CLOCKSOURCE) |
(1 << KVM_FEATURE_NOP_IO_DELAY) |
(1 << KVM_FEATURE_CLOCKSOURCE2) |
@@ -1596,6 +1593,46 @@ static void x86_cpu_get_feature_words(Object *obj, Visitor *v, void *opaque,
error_propagate(errp, err);
}
+static void x86_get_hv_spinlocks(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ X86CPU *cpu = X86_CPU(obj);
+ int64_t value = cpu->hyperv_spinlock_attempts;
+
+ visit_type_int(v, &value, name, errp);
+}
+
+static void x86_set_hv_spinlocks(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ const int64_t min = 0xFFF;
+ const int64_t max = UINT_MAX;
+ X86CPU *cpu = X86_CPU(obj);
+ Error *err = NULL;
+ int64_t value;
+
+ visit_type_int(v, &value, name, &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ if (value < min || value > max) {
+ error_setg(errp, "Property %s.%s doesn't take value %" PRId64
+ " (minimum: %" PRId64 ", maximum: %" PRId64 ")",
+ object_get_typename(obj), name ? name : "null",
+ value, min, max);
+ return;
+ }
+ cpu->hyperv_spinlock_attempts = value;
+}
+
+static PropertyInfo qdev_prop_spinlocks = {
+ .name = "int",
+ .get = x86_get_hv_spinlocks,
+ .set = x86_set_hv_spinlocks,
+};
+
static int cpu_x86_find_by_name(X86CPU *cpu, x86_def_t *x86_cpu_def,
const char *name)
{
@@ -1669,15 +1706,7 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp)
} else if ((val = strchr(featurestr, '='))) {
*val = 0; val++;
feat2prop(featurestr);
- if (!strcmp(featurestr, "family")) {
- object_property_parse(OBJECT(cpu), val, featurestr, errp);
- } else if (!strcmp(featurestr, "model")) {
- object_property_parse(OBJECT(cpu), val, featurestr, errp);
- } else if (!strcmp(featurestr, "stepping")) {
- object_property_parse(OBJECT(cpu), val, featurestr, errp);
- } else if (!strcmp(featurestr, "level")) {
- object_property_parse(OBJECT(cpu), val, featurestr, errp);
- } else if (!strcmp(featurestr, "xlevel")) {
+ if (!strcmp(featurestr, "xlevel")) {
char *err;
char num[32];
@@ -1693,10 +1722,6 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp)
}
snprintf(num, sizeof(num), "%" PRIu32, numvalue);
object_property_parse(OBJECT(cpu), num, featurestr, errp);
- } else if (!strcmp(featurestr, "vendor")) {
- object_property_parse(OBJECT(cpu), val, featurestr, errp);
- } else if (!strcmp(featurestr, "model-id")) {
- object_property_parse(OBJECT(cpu), val, featurestr, errp);
} else if (!strcmp(featurestr, "tsc-freq")) {
int64_t tsc_freq;
char *err;
@@ -1713,6 +1738,7 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp)
} 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);
@@ -1724,23 +1750,14 @@ static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp)
min);
numvalue = min;
}
- cpu->hyperv_spinlock_attempts = numvalue;
+ snprintf(num, sizeof(num), "%" PRId32, numvalue);
+ object_property_parse(OBJECT(cpu), num, featurestr, errp);
} else {
- error_setg(errp, "unrecognized feature %s", featurestr);
- goto out;
+ object_property_parse(OBJECT(cpu), val, featurestr, errp);
}
- } else if (!strcmp(featurestr, "check")) {
- check_cpuid = 1;
- } else if (!strcmp(featurestr, "enforce")) {
- check_cpuid = enforce_cpuid = 1;
- } else if (!strcmp(featurestr, "hv_relaxed")) {
- cpu->hyperv_relaxed_timing = true;
- } else if (!strcmp(featurestr, "hv_vapic")) {
- cpu->hyperv_vapic = true;
} else {
- error_setg(errp, "feature string `%s' not in format (+feature|"
- "-feature|feature=xyz)", featurestr);
- goto out;
+ feat2prop(featurestr);
+ object_property_parse(OBJECT(cpu), "on", featurestr, errp);
}
if (error_is_set(errp)) {
goto out;
@@ -2449,7 +2466,7 @@ static void x86_cpu_reset(CPUState *s)
#if !defined(CONFIG_USER_ONLY)
/* We hard-wire the BSP to the first CPU. */
if (s->cpu_index == 0) {
- apic_designate_bsp(env->apic_state);
+ apic_designate_bsp(cpu->apic_state);
}
s->halted = !cpu_is_bsp(cpu);
@@ -2459,7 +2476,7 @@ static void x86_cpu_reset(CPUState *s)
#ifndef CONFIG_USER_ONLY
bool cpu_is_bsp(X86CPU *cpu)
{
- return cpu_get_apic_base(cpu->env.apic_state) & MSR_IA32_APICBASE_BSP;
+ return cpu_get_apic_base(cpu->apic_state) & MSR_IA32_APICBASE_BSP;
}
/* TODO: remove me, when reset over QOM tree is implemented */
@@ -2500,31 +2517,29 @@ static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
apic_type = "xen-apic";
}
- env->apic_state = qdev_try_create(qdev_get_parent_bus(dev), apic_type);
- if (env->apic_state == NULL) {
+ 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;
}
object_property_add_child(OBJECT(cpu), "apic",
- OBJECT(env->apic_state), NULL);
- qdev_prop_set_uint8(env->apic_state, "id", env->cpuid_apic_id);
+ OBJECT(cpu->apic_state), NULL);
+ qdev_prop_set_uint8(cpu->apic_state, "id", env->cpuid_apic_id);
/* TODO: convert to link<> */
- apic = APIC_COMMON(env->apic_state);
+ apic = APIC_COMMON(cpu->apic_state);
apic->cpu = cpu;
}
static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
{
- CPUX86State *env = &cpu->env;
-
- if (env->apic_state == NULL) {
+ if (cpu->apic_state == NULL) {
return;
}
- if (qdev_init(env->apic_state)) {
+ if (qdev_init(cpu->apic_state)) {
error_setg(errp, "APIC device '%s' could not be initialized",
- object_get_typename(OBJECT(env->apic_state)));
+ object_get_typename(OBJECT(cpu->apic_state)));
return;
}
}
@@ -2568,8 +2583,8 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
env->features[FEAT_8000_0001_ECX] &= TCG_EXT3_FEATURES;
env->features[FEAT_SVM] &= TCG_SVM_FEATURES;
} else {
- if (check_cpuid && kvm_check_features_against_host(cpu)
- && enforce_cpuid) {
+ if ((cpu->check_cpuid || cpu->enforce_cpuid)
+ && kvm_check_features_against_host(cpu) && cpu->enforce_cpuid) {
error_setg(&local_err,
"Host's CPU doesn't support requested features");
goto out;
@@ -2728,6 +2743,11 @@ static void x86_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
static Property x86_cpu_properties[] = {
DEFINE_PROP_BOOL("pmu", X86CPU, enable_pmu, false),
+ { .name = "hv-spinlocks", .info = &qdev_prop_spinlocks },
+ DEFINE_PROP_BOOL("hv-relaxed", X86CPU, hyperv_relaxed_timing, false),
+ DEFINE_PROP_BOOL("hv-vapic", X86CPU, hyperv_vapic, false),
+ DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, false),
+ DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false),
DEFINE_PROP_END_OF_LIST()
};