Merge remote-tracking branch 'afaerber/qom-cpu' into staging
* afaerber/qom-cpu: target-i386: Explicitly set vendor for each built-in cpudef target-i386: Sanitize AMD's ext2_features at realize time target-i386: Filter out unsupported features at realize time qemu-common.h: Make qemu_init_vcpu() stub static inline target-i386: check/enforce: Eliminate check_feat field target-i386: check/enforce: Check SVM flag support as well target-i386: check/enforce: Check all CPUID.80000001H.EDX bits target-i386: check/enforce: Do not ignore "hypervisor" flag target-i386: check/enforce: Fix CPUID leaf numbers on error messages target-i386: kvm: Enable all supported KVM features for -cpu host target-i386: kvm: -cpu host: Use GET_SUPPORTED_CPUID for SVM features cpu: Change parent type to Device qdev: Don't assume existence of parent bus on unparenting qdev: Include qdev code into *-user, too libqemustub: sysbus_get_default() stub libqemustub: vmstate register/unregister stubs libqemustub: Add qemu_[un]register_reset() stubs Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
commit
4b274b1603
@ -21,6 +21,13 @@ qom-obj-y = qom/
|
||||
|
||||
universal-obj-y += $(qom-obj-y)
|
||||
|
||||
#######################################################################
|
||||
# Core hw code (qdev core)
|
||||
hw-core-obj-y += hw/
|
||||
hw-core-obj-y += qemu-option.o
|
||||
|
||||
universal-obj-y += $(hw-core-obj-y)
|
||||
|
||||
#######################################################################
|
||||
# oslib-obj-y is code depending on the OS (win32 vs posix)
|
||||
oslib-obj-y = osdep.o cutils.o qemu-timer-common.o
|
||||
@ -182,6 +189,7 @@ nested-vars += \
|
||||
user-obj-y \
|
||||
common-obj-y \
|
||||
universal-obj-y \
|
||||
hw-core-obj-y \
|
||||
extra-obj-y \
|
||||
trace-obj-y
|
||||
dummy := $(call unnest-vars)
|
||||
|
@ -1,3 +1,9 @@
|
||||
# core qdev-related obj files, also used by *-user:
|
||||
hw-core-obj-y += qdev.o qdev-properties.o
|
||||
# irq.o needed for qdev GPIO handling:
|
||||
hw-core-obj-y += irq.o
|
||||
|
||||
|
||||
common-obj-y = usb/ ide/ pci/
|
||||
common-obj-y += loader.o
|
||||
common-obj-$(CONFIG_VIRTIO) += virtio-console.o
|
||||
@ -154,7 +160,6 @@ common-obj-$(CONFIG_SOUND) += $(sound-obj-y)
|
||||
common-obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/
|
||||
|
||||
common-obj-y += usb/
|
||||
common-obj-y += irq.o
|
||||
common-obj-$(CONFIG_PTIMER) += ptimer.o
|
||||
common-obj-$(CONFIG_MAX7310) += max7310.o
|
||||
common-obj-$(CONFIG_WM8750) += wm8750.o
|
||||
@ -180,7 +185,7 @@ common-obj-$(CONFIG_SD) += sd.o
|
||||
common-obj-y += bt.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o
|
||||
common-obj-y += bt-hci-csr.o
|
||||
common-obj-y += msmouse.o ps2.o
|
||||
common-obj-y += qdev.o qdev-properties.o qdev-monitor.o
|
||||
common-obj-y += qdev-monitor.o
|
||||
common-obj-y += qdev-properties-system.o
|
||||
common-obj-$(CONFIG_BRLAPI) += baum.o
|
||||
|
||||
|
@ -698,16 +698,18 @@ static void device_class_base_init(ObjectClass *class, void *data)
|
||||
klass->props = NULL;
|
||||
}
|
||||
|
||||
static void qdev_remove_from_bus(Object *obj)
|
||||
static void device_unparent(Object *obj)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
|
||||
bus_remove_child(dev->parent_bus, dev);
|
||||
if (dev->parent_bus != NULL) {
|
||||
bus_remove_child(dev->parent_bus, dev);
|
||||
}
|
||||
}
|
||||
|
||||
static void device_class_init(ObjectClass *class, void *data)
|
||||
{
|
||||
class->unparent = qdev_remove_from_bus;
|
||||
class->unparent = device_unparent;
|
||||
}
|
||||
|
||||
void device_reset(DeviceState *dev)
|
||||
|
@ -288,7 +288,9 @@ struct qemu_work_item {
|
||||
};
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
#define qemu_init_vcpu(env) do { } while (0)
|
||||
static inline void qemu_init_vcpu(void *env)
|
||||
{
|
||||
}
|
||||
#else
|
||||
void qemu_init_vcpu(void *env);
|
||||
#endif
|
||||
|
@ -20,7 +20,7 @@
|
||||
#ifndef QEMU_CPU_H
|
||||
#define QEMU_CPU_H
|
||||
|
||||
#include "qom/object.h"
|
||||
#include "hw/qdev-core.h"
|
||||
#include "qemu/thread.h"
|
||||
|
||||
/**
|
||||
@ -46,7 +46,7 @@ typedef struct CPUState CPUState;
|
||||
*/
|
||||
typedef struct CPUClass {
|
||||
/*< private >*/
|
||||
ObjectClass parent_class;
|
||||
DeviceClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
void (*reset)(CPUState *cpu);
|
||||
@ -66,7 +66,7 @@ struct kvm_run;
|
||||
*/
|
||||
struct CPUState {
|
||||
/*< private >*/
|
||||
Object parent_obj;
|
||||
DeviceState parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
struct QemuThread *thread;
|
||||
|
@ -36,14 +36,16 @@ static void cpu_common_reset(CPUState *cpu)
|
||||
|
||||
static void cpu_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
CPUClass *k = CPU_CLASS(klass);
|
||||
|
||||
k->reset = cpu_common_reset;
|
||||
dc->no_user = 1;
|
||||
}
|
||||
|
||||
static TypeInfo cpu_type_info = {
|
||||
static const TypeInfo cpu_type_info = {
|
||||
.name = TYPE_CPU,
|
||||
.parent = TYPE_OBJECT,
|
||||
.parent = TYPE_DEVICE,
|
||||
.instance_size = sizeof(CPUState),
|
||||
.abstract = true,
|
||||
.class_size = sizeof(CPUClass),
|
||||
|
@ -5,4 +5,7 @@ stub-obj-y += fdset-get-fd.o
|
||||
stub-obj-y += fdset-remove-fd.o
|
||||
stub-obj-y += get-fd.o
|
||||
stub-obj-y += set-fd-handler.o
|
||||
stub-obj-y += reset.o
|
||||
stub-obj-y += vmstate.o
|
||||
stub-obj-y += sysbus.o
|
||||
stub-obj-$(CONFIG_WIN32) += fd-register.o
|
||||
|
13
stubs/reset.c
Normal file
13
stubs/reset.c
Normal file
@ -0,0 +1,13 @@
|
||||
#include "hw/hw.h"
|
||||
|
||||
/* Stub functions for binaries that never call qemu_devices_reset(),
|
||||
* and don't need to keep track of the reset handler list.
|
||||
*/
|
||||
|
||||
void qemu_register_reset(QEMUResetHandler *func, void *opaque)
|
||||
{
|
||||
}
|
||||
|
||||
void qemu_unregister_reset(QEMUResetHandler *func, void *opaque)
|
||||
{
|
||||
}
|
6
stubs/sysbus.c
Normal file
6
stubs/sysbus.c
Normal file
@ -0,0 +1,6 @@
|
||||
#include "hw/qdev-core.h"
|
||||
|
||||
BusState *sysbus_get_default(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
17
stubs/vmstate.c
Normal file
17
stubs/vmstate.c
Normal file
@ -0,0 +1,17 @@
|
||||
#include "qemu-common.h"
|
||||
#include "migration/vmstate.h"
|
||||
|
||||
int vmstate_register_with_alias_id(DeviceState *dev,
|
||||
int instance_id,
|
||||
const VMStateDescription *vmsd,
|
||||
void *base, int alias_id,
|
||||
int required_for_version)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vmstate_unregister(DeviceState *dev,
|
||||
const VMStateDescription *vmsd,
|
||||
void *opaque)
|
||||
{
|
||||
}
|
@ -26,11 +26,9 @@
|
||||
|
||||
static void alpha_cpu_realize(Object *obj, Error **errp)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
AlphaCPU *cpu = ALPHA_CPU(obj);
|
||||
|
||||
qemu_init_vcpu(&cpu->env);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Sort alphabetically by type name. */
|
||||
|
@ -124,15 +124,34 @@ static const char *cpuid_7_0_ebx_feature_name[] = {
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
};
|
||||
|
||||
const char *get_register_name_32(unsigned int reg)
|
||||
{
|
||||
static const char *reg_names[CPU_NB_REGS32] = {
|
||||
[R_EAX] = "EAX",
|
||||
[R_ECX] = "ECX",
|
||||
[R_EDX] = "EDX",
|
||||
[R_EBX] = "EBX",
|
||||
[R_ESP] = "ESP",
|
||||
[R_EBP] = "EBP",
|
||||
[R_ESI] = "ESI",
|
||||
[R_EDI] = "EDI",
|
||||
};
|
||||
|
||||
if (reg > CPU_NB_REGS32) {
|
||||
return NULL;
|
||||
}
|
||||
return reg_names[reg];
|
||||
}
|
||||
|
||||
/* collects per-function cpuid data
|
||||
*/
|
||||
typedef struct model_features_t {
|
||||
uint32_t *guest_feat;
|
||||
uint32_t *host_feat;
|
||||
uint32_t check_feat;
|
||||
const char **flag_names;
|
||||
uint32_t cpuid;
|
||||
} model_features_t;
|
||||
int reg;
|
||||
} model_features_t;
|
||||
|
||||
int check_cpuid = 0;
|
||||
int enforce_cpuid = 0;
|
||||
@ -388,6 +407,9 @@ static x86_def_t builtin_x86_defs[] = {
|
||||
{
|
||||
.name = "core2duo",
|
||||
.level = 10,
|
||||
.vendor1 = CPUID_VENDOR_INTEL_1,
|
||||
.vendor2 = CPUID_VENDOR_INTEL_2,
|
||||
.vendor3 = CPUID_VENDOR_INTEL_3,
|
||||
.family = 6,
|
||||
.model = 15,
|
||||
.stepping = 11,
|
||||
@ -432,6 +454,9 @@ static x86_def_t builtin_x86_defs[] = {
|
||||
{
|
||||
.name = "qemu32",
|
||||
.level = 4,
|
||||
.vendor1 = CPUID_VENDOR_INTEL_1,
|
||||
.vendor2 = CPUID_VENDOR_INTEL_2,
|
||||
.vendor3 = CPUID_VENDOR_INTEL_3,
|
||||
.family = 6,
|
||||
.model = 3,
|
||||
.stepping = 3,
|
||||
@ -442,6 +467,9 @@ static x86_def_t builtin_x86_defs[] = {
|
||||
{
|
||||
.name = "kvm32",
|
||||
.level = 5,
|
||||
.vendor1 = CPUID_VENDOR_INTEL_1,
|
||||
.vendor2 = CPUID_VENDOR_INTEL_2,
|
||||
.vendor3 = CPUID_VENDOR_INTEL_3,
|
||||
.family = 15,
|
||||
.model = 6,
|
||||
.stepping = 1,
|
||||
@ -456,6 +484,9 @@ static x86_def_t builtin_x86_defs[] = {
|
||||
{
|
||||
.name = "coreduo",
|
||||
.level = 10,
|
||||
.vendor1 = CPUID_VENDOR_INTEL_1,
|
||||
.vendor2 = CPUID_VENDOR_INTEL_2,
|
||||
.vendor3 = CPUID_VENDOR_INTEL_3,
|
||||
.family = 6,
|
||||
.model = 14,
|
||||
.stepping = 8,
|
||||
@ -471,6 +502,9 @@ static x86_def_t builtin_x86_defs[] = {
|
||||
{
|
||||
.name = "486",
|
||||
.level = 1,
|
||||
.vendor1 = CPUID_VENDOR_INTEL_1,
|
||||
.vendor2 = CPUID_VENDOR_INTEL_2,
|
||||
.vendor3 = CPUID_VENDOR_INTEL_3,
|
||||
.family = 4,
|
||||
.model = 0,
|
||||
.stepping = 0,
|
||||
@ -480,6 +514,9 @@ static x86_def_t builtin_x86_defs[] = {
|
||||
{
|
||||
.name = "pentium",
|
||||
.level = 1,
|
||||
.vendor1 = CPUID_VENDOR_INTEL_1,
|
||||
.vendor2 = CPUID_VENDOR_INTEL_2,
|
||||
.vendor3 = CPUID_VENDOR_INTEL_3,
|
||||
.family = 5,
|
||||
.model = 4,
|
||||
.stepping = 3,
|
||||
@ -489,6 +526,9 @@ static x86_def_t builtin_x86_defs[] = {
|
||||
{
|
||||
.name = "pentium2",
|
||||
.level = 2,
|
||||
.vendor1 = CPUID_VENDOR_INTEL_1,
|
||||
.vendor2 = CPUID_VENDOR_INTEL_2,
|
||||
.vendor3 = CPUID_VENDOR_INTEL_3,
|
||||
.family = 6,
|
||||
.model = 5,
|
||||
.stepping = 2,
|
||||
@ -498,6 +538,9 @@ static x86_def_t builtin_x86_defs[] = {
|
||||
{
|
||||
.name = "pentium3",
|
||||
.level = 2,
|
||||
.vendor1 = CPUID_VENDOR_INTEL_1,
|
||||
.vendor2 = CPUID_VENDOR_INTEL_2,
|
||||
.vendor3 = CPUID_VENDOR_INTEL_3,
|
||||
.family = 6,
|
||||
.model = 7,
|
||||
.stepping = 3,
|
||||
@ -523,6 +566,9 @@ static x86_def_t builtin_x86_defs[] = {
|
||||
.name = "n270",
|
||||
/* original is on level 10 */
|
||||
.level = 5,
|
||||
.vendor1 = CPUID_VENDOR_INTEL_1,
|
||||
.vendor2 = CPUID_VENDOR_INTEL_2,
|
||||
.vendor3 = CPUID_VENDOR_INTEL_3,
|
||||
.family = 6,
|
||||
.model = 28,
|
||||
.stepping = 2,
|
||||
@ -897,13 +943,12 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Every SVM feature requires emulation support in KVM - so we can't just
|
||||
* read the host features here. KVM might even support SVM features not
|
||||
* available on the host hardware. Just set all bits and mask out the
|
||||
* unsupported ones later.
|
||||
*/
|
||||
x86_cpu_def->svm_features = -1;
|
||||
/* Other KVM-specific feature fields: */
|
||||
x86_cpu_def->svm_features =
|
||||
kvm_arch_get_supported_cpuid(s, 0x8000000A, 0, R_EDX);
|
||||
x86_cpu_def->kvm_features =
|
||||
kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX);
|
||||
|
||||
#endif /* CONFIG_KVM */
|
||||
}
|
||||
|
||||
@ -913,18 +958,20 @@ static int unavailable_host_feature(struct model_features_t *f, uint32_t mask)
|
||||
|
||||
for (i = 0; i < 32; ++i)
|
||||
if (1 << i & mask) {
|
||||
fprintf(stderr, "warning: host cpuid %04x_%04x lacks requested"
|
||||
" flag '%s' [0x%08x]\n",
|
||||
f->cpuid >> 16, f->cpuid & 0xffff,
|
||||
f->flag_names[i] ? f->flag_names[i] : "[reserved]", mask);
|
||||
const char *reg = get_register_name_32(f->reg);
|
||||
assert(reg);
|
||||
fprintf(stderr, "warning: host doesn't support requested feature: "
|
||||
"CPUID.%02XH:%s%s%s [bit %d]\n",
|
||||
f->cpuid, reg,
|
||||
f->flag_names[i] ? "." : "",
|
||||
f->flag_names[i] ? f->flag_names[i] : "", i);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* best effort attempt to inform user requested cpu flags aren't making
|
||||
* their way to the guest. Note: ft[].check_feat ideally should be
|
||||
* specified via a guest_def field to suppress report of extraneous flags.
|
||||
* their way to the guest.
|
||||
*
|
||||
* This function may be called only if KVM is enabled.
|
||||
*/
|
||||
@ -935,20 +982,21 @@ static int kvm_check_features_against_host(x86_def_t *guest_def)
|
||||
int rv, i;
|
||||
struct model_features_t ft[] = {
|
||||
{&guest_def->features, &host_def.features,
|
||||
~0, feature_name, 0x00000000},
|
||||
feature_name, 0x00000001, R_EDX},
|
||||
{&guest_def->ext_features, &host_def.ext_features,
|
||||
~CPUID_EXT_HYPERVISOR, ext_feature_name, 0x00000001},
|
||||
ext_feature_name, 0x00000001, R_ECX},
|
||||
{&guest_def->ext2_features, &host_def.ext2_features,
|
||||
~PPRO_FEATURES, ext2_feature_name, 0x80000000},
|
||||
ext2_feature_name, 0x80000001, R_EDX},
|
||||
{&guest_def->ext3_features, &host_def.ext3_features,
|
||||
~CPUID_EXT3_SVM, ext3_feature_name, 0x80000001}};
|
||||
ext3_feature_name, 0x80000001, R_ECX}
|
||||
};
|
||||
|
||||
assert(kvm_enabled());
|
||||
|
||||
kvm_cpu_fill_host(&host_def);
|
||||
for (rv = 0, i = 0; i < ARRAY_SIZE(ft); ++i)
|
||||
for (mask = 1; mask; mask <<= 1)
|
||||
if (ft[i].check_feat & mask && *ft[i].guest_feat & mask &&
|
||||
if (*ft[i].guest_feat & mask &&
|
||||
!(*ft[i].host_feat & mask)) {
|
||||
unavailable_host_feature(&ft[i], mask);
|
||||
rv = 1;
|
||||
@ -1513,15 +1561,10 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model)
|
||||
if (cpu_x86_parse_featurestr(def, features) < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (def->vendor1) {
|
||||
env->cpuid_vendor1 = def->vendor1;
|
||||
env->cpuid_vendor2 = def->vendor2;
|
||||
env->cpuid_vendor3 = def->vendor3;
|
||||
} else {
|
||||
env->cpuid_vendor1 = CPUID_VENDOR_INTEL_1;
|
||||
env->cpuid_vendor2 = CPUID_VENDOR_INTEL_2;
|
||||
env->cpuid_vendor3 = CPUID_VENDOR_INTEL_3;
|
||||
}
|
||||
assert(def->vendor1);
|
||||
env->cpuid_vendor1 = def->vendor1;
|
||||
env->cpuid_vendor2 = def->vendor2;
|
||||
env->cpuid_vendor3 = def->vendor3;
|
||||
env->cpuid_vendor_override = def->vendor_override;
|
||||
object_property_set_int(OBJECT(cpu), def->level, "level", &error);
|
||||
object_property_set_int(OBJECT(cpu), def->family, "family", &error);
|
||||
@ -1540,31 +1583,6 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model)
|
||||
object_property_set_int(OBJECT(cpu), (int64_t)def->tsc_khz * 1000,
|
||||
"tsc-frequency", &error);
|
||||
|
||||
/* On AMD CPUs, some CPUID[8000_0001].EDX bits must match the bits on
|
||||
* CPUID[1].EDX.
|
||||
*/
|
||||
if (env->cpuid_vendor1 == CPUID_VENDOR_AMD_1 &&
|
||||
env->cpuid_vendor2 == CPUID_VENDOR_AMD_2 &&
|
||||
env->cpuid_vendor3 == CPUID_VENDOR_AMD_3) {
|
||||
env->cpuid_ext2_features &= ~CPUID_EXT2_AMD_ALIASES;
|
||||
env->cpuid_ext2_features |= (def->features & CPUID_EXT2_AMD_ALIASES);
|
||||
}
|
||||
|
||||
if (!kvm_enabled()) {
|
||||
env->cpuid_features &= TCG_FEATURES;
|
||||
env->cpuid_ext_features &= TCG_EXT_FEATURES;
|
||||
env->cpuid_ext2_features &= (TCG_EXT2_FEATURES
|
||||
#ifdef TARGET_X86_64
|
||||
| CPUID_EXT2_SYSCALL | CPUID_EXT2_LM
|
||||
#endif
|
||||
);
|
||||
env->cpuid_ext3_features &= TCG_EXT3_FEATURES;
|
||||
env->cpuid_svm_features &= TCG_SVM_FEATURES;
|
||||
} else {
|
||||
#ifdef CONFIG_KVM
|
||||
filter_features_for_kvm(cpu);
|
||||
#endif
|
||||
}
|
||||
object_property_set_str(OBJECT(cpu), def->model_id, "model-id", &error);
|
||||
if (error) {
|
||||
fprintf(stderr, "%s\n", error_get_pretty(error));
|
||||
@ -2085,6 +2103,33 @@ void x86_cpu_realize(Object *obj, Error **errp)
|
||||
env->cpuid_level = 7;
|
||||
}
|
||||
|
||||
/* On AMD CPUs, some CPUID[8000_0001].EDX bits must match the bits on
|
||||
* CPUID[1].EDX.
|
||||
*/
|
||||
if (env->cpuid_vendor1 == CPUID_VENDOR_AMD_1 &&
|
||||
env->cpuid_vendor2 == CPUID_VENDOR_AMD_2 &&
|
||||
env->cpuid_vendor3 == CPUID_VENDOR_AMD_3) {
|
||||
env->cpuid_ext2_features &= ~CPUID_EXT2_AMD_ALIASES;
|
||||
env->cpuid_ext2_features |= (env->cpuid_features
|
||||
& CPUID_EXT2_AMD_ALIASES);
|
||||
}
|
||||
|
||||
if (!kvm_enabled()) {
|
||||
env->cpuid_features &= TCG_FEATURES;
|
||||
env->cpuid_ext_features &= TCG_EXT_FEATURES;
|
||||
env->cpuid_ext2_features &= (TCG_EXT2_FEATURES
|
||||
#ifdef TARGET_X86_64
|
||||
| CPUID_EXT2_SYSCALL | CPUID_EXT2_LM
|
||||
#endif
|
||||
);
|
||||
env->cpuid_ext3_features &= TCG_EXT3_FEATURES;
|
||||
env->cpuid_svm_features &= TCG_SVM_FEATURES;
|
||||
} else {
|
||||
#ifdef CONFIG_KVM
|
||||
filter_features_for_kvm(cpu);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
qemu_register_reset(x86_cpu_machine_reset_cb, cpu);
|
||||
|
||||
|
@ -1220,4 +1220,7 @@ void cpu_report_tpr_access(CPUX86State *env, TPRAccess access);
|
||||
|
||||
void enable_kvm_pv_eoi(void);
|
||||
|
||||
/* Return name of 32-bit register, from a R_* constant */
|
||||
const char *get_register_name_32(unsigned int reg);
|
||||
|
||||
#endif /* CPU_I386_H */
|
||||
|
Loading…
Reference in New Issue
Block a user