mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-23 19:49:43 +00:00
X86 patches queued in the last few weeks. Mostly code cleanup and changes on
code assigning APIC ID. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJU/gVGAAoJECgHk2+YTcWmGmgQAKE/tDoKt2Uw5BjWxmmU0GFm r4m43rcR3xfHdQyEx3iNKSlAQvxcYd/eBM5kb6Ir7wjhqtDfoiVC+bui3VhAsQPk kaB+6ryyAGDV2xt1UtgfzEodXl9aw0zofFBafJrtArITAsO5UeuTQhxIuLHwzcF6 XKkpg7oz3bgRH57gZFi1y5PUdJUpmk4awipE/A4G/y5mERe2W30Ku4JSSxV7+shz MLOQF4GjfHBKnfA/PVQbtWQjbKVZRPbGrcg+TmEH+2TGzEMVXeXuqvAgbOGhhlcD uJyiCeXf1CD92JIU2JWXejd0SSLLJyf74TiBEhxfFil3gpS+d5RWSCkuR1mmtpR4 B5NPbhhPZmXJBMIQB9kM0fiW4I8+qPPqFatqEJ78OYhVqUHgY746hnJTc22jK/FK e1UxLBREMLAty4aVT3iAaPZo6hM/IMctEOgEhwH15NSQDNXFIqrlM/b5OJ9Iq01Y Ah838rv4kRiVQcKoa1Mg8rqBvmw4Cm1MKcYp4sOPhY4/bwx71qagbZG4EAfQ6DP6 uieN/4hMTuGqf4eHgIjrdAr/4sPPiszYjF6fVwJVh+pCbirWOsRQPx4NnSmIRveU CUJuuHCsqWjThMEWVNqe5bm1d32EI0o16ihEBuBl+MqivpmV+4p/bJYvyiC1vJw7 UatzprZMm2Az2RL6W6Mw =iDzB -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/ehabkost/tags/x86-pull-request' into staging X86 patches queued in the last few weeks. Mostly code cleanup and changes on code assigning APIC ID. # gpg: Signature made Mon Mar 9 20:40:38 2015 GMT using RSA key ID 984DC5A6 # gpg: Can't check signature: public key not found * remotes/ehabkost/tags/x86-pull-request: target-i386: Require APIC ID to be explicitly set before CPU realize target-i386: Move APIC ID compatibility code to pc.c target-i386: Move CPUX86State::cpuid_apic_id to X86CPU::apic_id target-i386: Remove unused APIC ID default code target-i386: Eliminate unnecessary get_cpuid_vendor() function target-i386: Simplify listflags() function target-i386: Move topology.h to include/hw/i386 Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
4841237141
35
hw/i386/pc.c
35
hw/i386/pc.c
@ -25,6 +25,8 @@
|
||||
#include "hw/i386/pc.h"
|
||||
#include "hw/char/serial.h"
|
||||
#include "hw/i386/apic.h"
|
||||
#include "hw/i386/topology.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "hw/block/fdc.h"
|
||||
#include "hw/ide.h"
|
||||
#include "hw/pci/pci.h"
|
||||
@ -629,6 +631,39 @@ bool e820_get_entry(int idx, uint32_t type, uint64_t *address, uint64_t *length)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
static 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;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculates the limit to CPU APIC ID values
|
||||
*
|
||||
* This function returns the limit for the APIC ID value, so that all
|
||||
|
@ -21,8 +21,8 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef TARGET_I386_TOPOLOGY_H
|
||||
#define TARGET_I386_TOPOLOGY_H
|
||||
#ifndef HW_I386_TOPOLOGY_H
|
||||
#define HW_I386_TOPOLOGY_H
|
||||
|
||||
/* This file implements the APIC-ID-based CPU topology enumeration logic,
|
||||
* documented at the following document:
|
||||
@ -131,4 +131,4 @@ static inline apic_id_t x86_apicid_from_cpu_idx(unsigned nr_cores,
|
||||
return apicid_from_topo_ids(nr_cores, nr_threads, pkg_id, core_id, smt_id);
|
||||
}
|
||||
|
||||
#endif /* TARGET_I386_TOPOLOGY_H */
|
||||
#endif /* HW_I386_TOPOLOGY_H */
|
@ -93,6 +93,7 @@ typedef struct X86CPU {
|
||||
bool expose_kvm;
|
||||
bool migratable;
|
||||
bool host_features;
|
||||
int64_t apic_id;
|
||||
|
||||
/* if true the CPUID code directly forward host cache leaves to the guest */
|
||||
bool cache_info_passthrough;
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "kvm_i386.h"
|
||||
#include "topology.h"
|
||||
|
||||
#include "qemu/option.h"
|
||||
#include "qemu/config-file.h"
|
||||
@ -1690,7 +1689,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->env.cpuid_apic_id;
|
||||
int64_t value = cpu->apic_id;
|
||||
|
||||
visit_type_int(v, &value, name, errp);
|
||||
}
|
||||
@ -1723,11 +1722,11 @@ static void x86_cpuid_set_apic_id(Object *obj, Visitor *v, void *opaque,
|
||||
return;
|
||||
}
|
||||
|
||||
if ((value != cpu->env.cpuid_apic_id) && cpu_exists(value)) {
|
||||
if ((value != cpu->apic_id) && cpu_exists(value)) {
|
||||
error_setg(errp, "CPU with APIC ID %" PRIi64 " exists", value);
|
||||
return;
|
||||
}
|
||||
cpu->env.cpuid_apic_id = value;
|
||||
cpu->apic_id = value;
|
||||
}
|
||||
|
||||
/* Generic getter for "feature-words" and "filtered-features" properties */
|
||||
@ -1911,34 +1910,19 @@ static void x86_cpu_parse_featurestr(CPUState *cs, char *features,
|
||||
}
|
||||
}
|
||||
|
||||
/* 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.
|
||||
/* Print all cpuid feature names in featureset
|
||||
*/
|
||||
static void listflags(char *buf, int bufsize, uint32_t fbits,
|
||||
const char **featureset, uint32_t flags)
|
||||
static void listflags(FILE *f, fprintf_function print, const char **featureset)
|
||||
{
|
||||
const char **p = &featureset[31];
|
||||
char *q, *b, bit;
|
||||
int nc;
|
||||
int bit;
|
||||
bool first = true;
|
||||
|
||||
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;
|
||||
for (bit = 0; bit < 32; bit++) {
|
||||
if (featureset[bit]) {
|
||||
print(f, "%s%s", first ? "" : " ", featureset[bit]);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* generate CPU information. */
|
||||
@ -1963,8 +1947,9 @@ 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];
|
||||
|
||||
listflags(buf, sizeof(buf), (uint32_t)~0, fw->feat_names, 1);
|
||||
(*cpu_fprintf)(f, " %s\n", buf);
|
||||
(*cpu_fprintf)(f, " ");
|
||||
listflags(f, cpu_fprintf, fw->feat_names);
|
||||
(*cpu_fprintf)(f, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -2227,14 +2212,6 @@ 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)
|
||||
@ -2268,11 +2245,14 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
||||
switch(index) {
|
||||
case 0:
|
||||
*eax = env->cpuid_level;
|
||||
get_cpuid_vendor(env, ebx, ecx, edx);
|
||||
*ebx = env->cpuid_vendor1;
|
||||
*edx = env->cpuid_vendor2;
|
||||
*ecx = env->cpuid_vendor3;
|
||||
break;
|
||||
case 1:
|
||||
*eax = env->cpuid_version;
|
||||
*ebx = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
|
||||
*ebx = (cpu->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) {
|
||||
@ -2461,11 +2441,9 @@ 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) {
|
||||
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) {
|
||||
if (env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1 ||
|
||||
env->cpuid_vendor2 != CPUID_VENDOR_INTEL_2 ||
|
||||
env->cpuid_vendor3 != CPUID_VENDOR_INTEL_3) {
|
||||
*ecx |= 1 << 1; /* CmpLegacy bit */
|
||||
}
|
||||
}
|
||||
@ -2721,7 +2699,6 @@ 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";
|
||||
@ -2740,7 +2717,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", env->cpuid_apic_id);
|
||||
qdev_prop_set_uint8(cpu->apic_state, "id", cpu->apic_id);
|
||||
/* TODO: convert to link<> */
|
||||
apic = APIC_COMMON(cpu->apic_state);
|
||||
apic->cpu = cpu;
|
||||
@ -2780,6 +2757,11 @@ 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;
|
||||
}
|
||||
@ -2844,39 +2826,6 @@ 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);
|
||||
@ -2923,7 +2872,11 @@ static void x86_cpu_initfn(Object *obj)
|
||||
NULL, NULL, (void *)cpu->filtered_features, NULL);
|
||||
|
||||
cpu->hyperv_spinlock_attempts = HYPERV_SPINLOCK_NEVER_RETRY;
|
||||
env->cpuid_apic_id = x86_cpu_apic_id_from_index(cs->cpu_index);
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/* Any code creating new X86CPU objects have to set apic-id explicitly */
|
||||
cpu->apic_id = -1;
|
||||
#endif
|
||||
|
||||
x86_cpu_load_def(cpu, xcc->cpu_def, &error_abort);
|
||||
|
||||
@ -2937,9 +2890,8 @@ 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 env->cpuid_apic_id;
|
||||
return cpu->apic_id;
|
||||
}
|
||||
|
||||
static bool x86_cpu_get_paging_enabled(const CPUState *cs)
|
||||
|
@ -944,7 +944,6 @@ typedef struct CPUX86State {
|
||||
uint32_t cpuid_version;
|
||||
FeatureWordArray features;
|
||||
uint32_t cpuid_model[12];
|
||||
uint32_t cpuid_apic_id;
|
||||
|
||||
/* MTRRs */
|
||||
uint64_t mtrr_fixed[11];
|
||||
@ -1329,7 +1328,6 @@ void x86_cpu_compat_kvm_no_autodisable(FeatureWord w, uint32_t features);
|
||||
/* Return name of 32-bit register, from a R_* constant */
|
||||
const char *get_register_name_32(unsigned int reg);
|
||||
|
||||
uint32_t x86_cpu_apic_id_from_index(unsigned int cpu_index);
|
||||
void enable_compat_apic_id_mode(void);
|
||||
|
||||
#define APIC_DEFAULT_ADDRESS 0xfee00000
|
||||
|
@ -430,7 +430,7 @@ static void cpu_update_state(void *opaque, int running, RunState state)
|
||||
unsigned long kvm_arch_vcpu_id(CPUState *cs)
|
||||
{
|
||||
X86CPU *cpu = X86_CPU(cs);
|
||||
return cpu->env.cpuid_apic_id;
|
||||
return cpu->apic_id;
|
||||
}
|
||||
|
||||
#ifndef KVM_CPUID_SIGNATURE_NEXT
|
||||
|
@ -241,8 +241,6 @@ $(test-obj-y): QEMU_INCLUDES += -Itests
|
||||
QEMU_CFLAGS += -I$(SRC_PATH)/tests
|
||||
qom-core-obj = qom/object.o qom/qom-qobject.o qom/container.o
|
||||
|
||||
tests/test-x86-cpuid.o: QEMU_INCLUDES += -I$(SRC_PATH)/target-i386
|
||||
|
||||
tests/check-qint$(EXESUF): tests/check-qint.o libqemuutil.a
|
||||
tests/check-qstring$(EXESUF): tests/check-qstring.o libqemuutil.a
|
||||
tests/check-qdict$(EXESUF): tests/check-qdict.o libqemuutil.a
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "topology.h"
|
||||
#include "hw/i386/topology.h"
|
||||
|
||||
static void test_topo_bits(void)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user