diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2015-03-03 00:29:17 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2015-03-03 00:29:17 +0000 |
commit | 0856579cac2f1dacecd847cfcd89680d26ff78f5 (patch) | |
tree | 6ab14c4d57029b50bf6ec08b4b881bfad0625217 /target-i386/cpu.c | |
parent | b8a173b25c887a606681fc35a46702c164d5b2d0 (diff) |
Revert "Merge remote-tracking branch 'remotes/ehabkost/tags/x86-pull-request' into staging"
This reverts commit b8a173b25c887a606681fc35a46702c164d5b2d0, reversing
changes made to 5de090464f1ec5360c4f30faa01d8a9f8826cd58.
(I applied this pull request when I should not have done so, and
am now immediately reverting it.)
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target-i386/cpu.c')
-rw-r--r-- | target-i386/cpu.c | 146 |
1 files changed, 95 insertions, 51 deletions
diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 14c6c4abaf..d543e2b537 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -25,6 +25,7 @@ #include "sysemu/kvm.h" #include "sysemu/cpus.h" #include "kvm_i386.h" +#include "topology.h" #include "qemu/option.h" #include "qemu/config-file.h" @@ -1689,7 +1690,7 @@ static void x86_cpuid_get_apic_id(Object *obj, Visitor *v, void *opaque, const char *name, Error **errp) { X86CPU *cpu = X86_CPU(obj); - int64_t value = cpu->apic_id; + int64_t value = cpu->env.cpuid_apic_id; visit_type_int(v, &value, name, errp); } @@ -1722,11 +1723,11 @@ static void x86_cpuid_set_apic_id(Object *obj, Visitor *v, void *opaque, return; } - if ((value != cpu->apic_id) && cpu_exists(value)) { + if ((value != cpu->env.cpuid_apic_id) && cpu_exists(value)) { error_setg(errp, "CPU with APIC ID %" PRIi64 " exists", value); return; } - cpu->apic_id = value; + cpu->env.cpuid_apic_id = value; } /* Generic getter for "feature-words" and "filtered-features" properties */ @@ -1910,19 +1911,34 @@ static void x86_cpu_parse_featurestr(CPUState *cs, char *features, } } -/* Print all cpuid feature names in featureset +/* generate a composite string into buf of all cpuid names in featureset + * selected by fbits. indicate truncation at bufsize in the event of overflow. + * if flags, suppress names undefined in featureset. */ -static void listflags(FILE *f, fprintf_function print, const char **featureset) -{ - int bit; - bool first = true; - - for (bit = 0; bit < 32; bit++) { - if (featureset[bit]) { - print(f, "%s%s", first ? "" : " ", featureset[bit]); - first = false; +static void listflags(char *buf, int bufsize, uint32_t fbits, + const char **featureset, uint32_t flags) +{ + const char **p = &featureset[31]; + char *q, *b, bit; + int nc; + + b = 4 <= bufsize ? buf + (bufsize -= 3) - 1 : NULL; + *buf = '\0'; + for (q = buf, bit = 31; fbits && bufsize; --p, fbits &= ~(1 << bit), --bit) + if (fbits & 1 << bit && (*p || !flags)) { + if (*p) + nc = snprintf(q, bufsize, "%s%s", q == buf ? "" : " ", *p); + else + nc = snprintf(q, bufsize, "%s[%d]", q == buf ? "" : " ", bit); + if (bufsize <= nc) { + if (b) { + memcpy(b, "...", sizeof("...")); + } + return; + } + q += nc; + bufsize -= nc; } - } } /* generate CPU information. */ @@ -1947,9 +1963,8 @@ void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf) for (i = 0; i < ARRAY_SIZE(feature_word_info); i++) { FeatureWordInfo *fw = &feature_word_info[i]; - (*cpu_fprintf)(f, " "); - listflags(f, cpu_fprintf, fw->feat_names); - (*cpu_fprintf)(f, "\n"); + listflags(buf, sizeof(buf), (uint32_t)~0, fw->feat_names, 1); + (*cpu_fprintf)(f, " %s\n", buf); } } @@ -2134,35 +2149,27 @@ out: return cpu; } -CPUX86State *cpu_x86_init_user(const char *cpu_model) +X86CPU *cpu_x86_init(const char *cpu_model) { Error *error = NULL; X86CPU *cpu; cpu = cpu_x86_create(cpu_model, NULL, &error); if (error) { - goto error; - } - - object_property_set_int(OBJECT(cpu), CPU(cpu)->cpu_index, "apic-id", - &error); - if (error) { - goto error; + goto out; } object_property_set_bool(OBJECT(cpu), true, "realized", &error); - if (error) { - goto error; - } - return &cpu->env; - -error: - error_report_err(error); - if (cpu != NULL) { - object_unref(OBJECT(cpu)); +out: + if (error) { + error_report_err(error); + if (cpu != NULL) { + object_unref(OBJECT(cpu)); + cpu = NULL; + } } - return NULL; + return cpu; } static void x86_cpu_cpudef_class_init(ObjectClass *oc, void *data) @@ -2220,6 +2227,14 @@ void x86_cpudef_setup(void) } } +static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx, + uint32_t *ecx, uint32_t *edx) +{ + *ebx = env->cpuid_vendor1; + *edx = env->cpuid_vendor2; + *ecx = env->cpuid_vendor3; +} + void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) @@ -2253,14 +2268,11 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, switch(index) { case 0: *eax = env->cpuid_level; - *ebx = env->cpuid_vendor1; - *edx = env->cpuid_vendor2; - *ecx = env->cpuid_vendor3; + get_cpuid_vendor(env, ebx, ecx, edx); break; case 1: *eax = env->cpuid_version; - *ebx = (cpu->apic_id << 24) | - 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */ + *ebx = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */ *ecx = env->features[FEAT_1_ECX]; *edx = env->features[FEAT_1_EDX]; if (cs->nr_cores * cs->nr_threads > 1) { @@ -2449,9 +2461,11 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, * So dont set it here for Intel to make Linux guests happy. */ if (cs->nr_cores * cs->nr_threads > 1) { - if (env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1 || - env->cpuid_vendor2 != CPUID_VENDOR_INTEL_2 || - env->cpuid_vendor3 != CPUID_VENDOR_INTEL_3) { + uint32_t tebx, tecx, tedx; + get_cpuid_vendor(env, &tebx, &tecx, &tedx); + if (tebx != CPUID_VENDOR_INTEL_1 || + tedx != CPUID_VENDOR_INTEL_2 || + tecx != CPUID_VENDOR_INTEL_3) { *ecx |= 1 << 1; /* CmpLegacy bit */ } } @@ -2707,6 +2721,7 @@ static void mce_init(X86CPU *cpu) #ifndef CONFIG_USER_ONLY static void x86_cpu_apic_create(X86CPU *cpu, Error **errp) { + CPUX86State *env = &cpu->env; DeviceState *dev = DEVICE(cpu); APICCommonState *apic; const char *apic_type = "apic"; @@ -2725,7 +2740,7 @@ static void x86_cpu_apic_create(X86CPU *cpu, Error **errp) object_property_add_child(OBJECT(cpu), "apic", OBJECT(cpu->apic_state), NULL); - qdev_prop_set_uint8(cpu->apic_state, "id", cpu->apic_id); + qdev_prop_set_uint8(cpu->apic_state, "id", env->cpuid_apic_id); /* TODO: convert to link<> */ apic = APIC_COMMON(cpu->apic_state); apic->cpu = cpu; @@ -2765,11 +2780,6 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) Error *local_err = NULL; static bool ht_warned; - if (cpu->apic_id < 0) { - error_setg(errp, "apic-id property was not initialized properly"); - return; - } - if (env->features[FEAT_7_0_EBX] && env->cpuid_level < 7) { env->cpuid_level = 7; } @@ -2834,6 +2844,39 @@ out: } } +/* Enables contiguous-apic-ID mode, for compatibility */ +static bool compat_apic_id_mode; + +void enable_compat_apic_id_mode(void) +{ + compat_apic_id_mode = true; +} + +/* Calculates initial APIC ID for a specific CPU index + * + * Currently we need to be able to calculate the APIC ID from the CPU index + * alone (without requiring a CPU object), as the QEMU<->Seabios interfaces have + * no concept of "CPU index", and the NUMA tables on fw_cfg need the APIC ID of + * all CPUs up to max_cpus. + */ +uint32_t x86_cpu_apic_id_from_index(unsigned int cpu_index) +{ + uint32_t correct_id; + static bool warned; + + correct_id = x86_apicid_from_cpu_idx(smp_cores, smp_threads, cpu_index); + if (compat_apic_id_mode) { + if (cpu_index != correct_id && !warned) { + error_report("APIC IDs set in compatibility mode, " + "CPU topology won't match the configuration"); + warned = true; + } + return cpu_index; + } else { + return correct_id; + } +} + static void x86_cpu_initfn(Object *obj) { CPUState *cs = CPU(obj); @@ -2880,7 +2923,7 @@ static void x86_cpu_initfn(Object *obj) NULL, NULL, (void *)cpu->filtered_features, NULL); cpu->hyperv_spinlock_attempts = HYPERV_SPINLOCK_NEVER_RETRY; - cpu->apic_id = -1; + env->cpuid_apic_id = x86_cpu_apic_id_from_index(cs->cpu_index); x86_cpu_load_def(cpu, xcc->cpu_def, &error_abort); @@ -2894,8 +2937,9 @@ static void x86_cpu_initfn(Object *obj) static int64_t x86_cpu_get_arch_id(CPUState *cs) { X86CPU *cpu = X86_CPU(cs); + CPUX86State *env = &cpu->env; - return cpu->apic_id; + return env->cpuid_apic_id; } static bool x86_cpu_get_paging_enabled(const CPUState *cs) |