aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2013-01-08 15:15:57 -0600
committerAnthony Liguori <aliguori@us.ibm.com>2013-01-08 15:15:57 -0600
commit4b274b1603e1d15ef51aedc8b6b7ebbae0b555ce (patch)
tree8fb03bac9a2c9988f97909f150c27df511b472de
parent560c30b1db1d40fe45c5104185367c4de43399d3 (diff)
parentebe8b9c6eb6e425d44805288b6b5dabd69368f46 (diff)
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>
-rw-r--r--Makefile.objs8
-rw-r--r--hw/Makefile.objs9
-rw-r--r--hw/qdev.c8
-rw-r--r--include/qemu-common.h4
-rw-r--r--include/qom/cpu.h6
-rw-r--r--qom/cpu.c6
-rw-r--r--stubs/Makefile.objs3
-rw-r--r--stubs/reset.c13
-rw-r--r--stubs/sysbus.c6
-rw-r--r--stubs/vmstate.c17
-rw-r--r--target-alpha/cpu.c2
-rw-r--r--target-i386/cpu.c153
-rw-r--r--target-i386/cpu.h3
13 files changed, 171 insertions, 67 deletions
diff --git a/Makefile.objs b/Makefile.objs
index a3eab4b410..12a314e3fb 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -22,6 +22,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
oslib-obj-$(CONFIG_WIN32) += oslib-win32.o qemu-thread-win32.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)
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index b8bbed39c1..6b8a68c504 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -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
diff --git a/hw/qdev.c b/hw/qdev.c
index f2c248451c..e2a5c5735b 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -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)
diff --git a/include/qemu-common.h b/include/qemu-common.h
index 2b83de395c..ca464bb367 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -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
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 3e9fc3aca5..fbacb2756b 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -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;
diff --git a/qom/cpu.c b/qom/cpu.c
index d4d436f80a..49e5134ea1 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -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),
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index 035b29a1f3..7672c69a29 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -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
diff --git a/stubs/reset.c b/stubs/reset.c
new file mode 100644
index 0000000000..ad287251ed
--- /dev/null
+++ b/stubs/reset.c
@@ -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)
+{
+}
diff --git a/stubs/sysbus.c b/stubs/sysbus.c
new file mode 100644
index 0000000000..e13496582b
--- /dev/null
+++ b/stubs/sysbus.c
@@ -0,0 +1,6 @@
+#include "hw/qdev-core.h"
+
+BusState *sysbus_get_default(void)
+{
+ return NULL;
+}
diff --git a/stubs/vmstate.c b/stubs/vmstate.c
new file mode 100644
index 0000000000..3682af599e
--- /dev/null
+++ b/stubs/vmstate.c
@@ -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)
+{
+}
diff --git a/target-alpha/cpu.c b/target-alpha/cpu.c
index 212a6250ba..40e980933f 100644
--- a/target-alpha/cpu.c
+++ b/target-alpha/cpu.c
@@ -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. */
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 82685dc3f5..78bd61e18f 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -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);
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 1283537108..e56921bbe3 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -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 */