Merge remote-tracking branch 'afaerber/qom-cpu' into staging

# By Igor Mammedov (8) and others
# Via Andreas Färber
* afaerber/qom-cpu:
  target-cris: Override do_interrupt for pre-v32 CPU cores
  qdev: Set device's parent before calling realize() down inheritance chain
  cpu: Pass CPUState to *cpu_synchronize_post*()
  target-i386: Split out CPU creation and features parsing
  target-i386/cpu.c: Coding style fixes
  ioapic: Replace FROM_SYSBUS() with QOM type cast
  kvmvapic: Replace FROM_SYSBUS() with QOM type cast
  target-i386: Split APIC creation from initialization in x86_cpu_realizefn()
  target-i386: Consolidate error propagation in x86_cpu_realizefn()
  qdev: Add qdev property for bool type
  target-i386: Improve -cpu ? features output
  target-i386: Fix including "host" in -cpu ? output
This commit is contained in:
Anthony Liguori 2013-04-16 10:28:36 -05:00
commit 398973fe1f
14 changed files with 145 additions and 56 deletions

4
cpus.c
View file

@ -419,7 +419,7 @@ void cpu_synchronize_all_post_reset(void)
CPUArchState *cpu;
for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) {
cpu_synchronize_post_reset(cpu);
cpu_synchronize_post_reset(ENV_GET_CPU(cpu));
}
}
@ -428,7 +428,7 @@ void cpu_synchronize_all_post_init(void)
CPUArchState *cpu;
for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) {
cpu_synchronize_post_init(cpu);
cpu_synchronize_post_init(ENV_GET_CPU(cpu));
}
}

View file

@ -120,6 +120,39 @@ PropertyInfo qdev_prop_bit = {
.set = set_bit,
};
/* --- bool --- */
static void get_bool(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
bool *ptr = qdev_get_prop_ptr(dev, prop);
visit_type_bool(v, ptr, name, errp);
}
static void set_bool(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
bool *ptr = qdev_get_prop_ptr(dev, prop);
if (dev->realized) {
qdev_prop_set_after_realize(dev, name, errp);
return;
}
visit_type_bool(v, ptr, name, errp);
}
PropertyInfo qdev_prop_bool = {
.name = "boolean",
.get = get_bool,
.set = set_bool,
};
/* --- 8bit integer --- */
static void get_uint8(Object *obj, Visitor *v, void *opaque,

View file

@ -684,10 +684,6 @@ static void device_set_realized(Object *obj, bool value, Error **err)
Error *local_err = NULL;
if (value && !dev->realized) {
if (dc->realize) {
dc->realize(dev, &local_err);
}
if (!obj->parent && local_err == NULL) {
static int unattached_count;
gchar *name = g_strdup_printf("device[%d]", unattached_count++);
@ -698,6 +694,10 @@ static void device_set_realized(Object *obj, bool value, Error **err)
g_free(name);
}
if (dc->realize) {
dc->realize(dev, &local_err);
}
if (qdev_get_vmsd(dev) && local_err == NULL) {
vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
dev->instance_id_alias,

View file

@ -60,6 +60,9 @@ typedef struct VAPICROMState {
bool rom_mapped_writable;
} VAPICROMState;
#define TYPE_VAPIC "kvmvapic"
#define VAPIC(obj) OBJECT_CHECK(VAPICROMState, (obj), TYPE_VAPIC)
#define TPR_INSTR_ABS_MODRM 0x1
#define TPR_INSTR_MATCH_MODRM_REG 0x2
@ -690,7 +693,7 @@ static const MemoryRegionOps vapic_ops = {
static int vapic_init(SysBusDevice *dev)
{
VAPICROMState *s = FROM_SYSBUS(VAPICROMState, dev);
VAPICROMState *s = VAPIC(dev);
memory_region_init_io(&s->io, &vapic_ops, s, "kvmvapic", 2);
sysbus_add_io(dev, VAPIC_IO_PORT, &s->io);
@ -806,7 +809,7 @@ static void vapic_class_init(ObjectClass *klass, void *data)
}
static const TypeInfo vapic_type = {
.name = "kvmvapic",
.name = TYPE_VAPIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(VAPICROMState),
.class_init = vapic_class_init,

View file

@ -59,7 +59,7 @@ static int ioapic_dispatch_post_load(void *opaque, int version_id)
static int ioapic_init_common(SysBusDevice *dev)
{
IOAPICCommonState *s = FROM_SYSBUS(IOAPICCommonState, dev);
IOAPICCommonState *s = IOAPIC_COMMON(dev);
IOAPICCommonClass *info;
static int ioapic_no;

View file

@ -6,6 +6,7 @@
/*** qdev-properties.c ***/
extern PropertyInfo qdev_prop_bit;
extern PropertyInfo qdev_prop_bool;
extern PropertyInfo qdev_prop_uint8;
extern PropertyInfo qdev_prop_uint16;
extern PropertyInfo qdev_prop_uint32;
@ -52,6 +53,15 @@ extern PropertyInfo qdev_prop_arraylen;
.defval = (bool)_defval, \
}
#define DEFINE_PROP_BOOL(_name, _state, _field, _defval) { \
.name = (_name), \
.info = &(qdev_prop_bool), \
.offset = offsetof(_state, _field) \
+ type_check(bool, typeof_field(_state, _field)), \
.qtype = QTYPE_QBOOL, \
.defval = (bool)_defval, \
}
#define PROP_ARRAY_LEN_PREFIX "len-"
/**

View file

@ -250,8 +250,8 @@ int kvm_check_extension(KVMState *s, unsigned int extension);
uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function,
uint32_t index, int reg);
void kvm_cpu_synchronize_state(CPUArchState *env);
void kvm_cpu_synchronize_post_reset(CPUArchState *env);
void kvm_cpu_synchronize_post_init(CPUArchState *env);
void kvm_cpu_synchronize_post_reset(CPUState *cpu);
void kvm_cpu_synchronize_post_init(CPUState *cpu);
/* generic hooks - to be moved/refactored once there are more users */
@ -262,17 +262,17 @@ static inline void cpu_synchronize_state(CPUArchState *env)
}
}
static inline void cpu_synchronize_post_reset(CPUArchState *env)
static inline void cpu_synchronize_post_reset(CPUState *cpu)
{
if (kvm_enabled()) {
kvm_cpu_synchronize_post_reset(env);
kvm_cpu_synchronize_post_reset(cpu);
}
}
static inline void cpu_synchronize_post_init(CPUArchState *env)
static inline void cpu_synchronize_post_init(CPUState *cpu)
{
if (kvm_enabled()) {
kvm_cpu_synchronize_post_init(env);
kvm_cpu_synchronize_post_init(cpu);
}
}

View file

@ -1510,18 +1510,14 @@ void kvm_cpu_synchronize_state(CPUArchState *env)
}
}
void kvm_cpu_synchronize_post_reset(CPUArchState *env)
void kvm_cpu_synchronize_post_reset(CPUState *cpu)
{
CPUState *cpu = ENV_GET_CPU(env);
kvm_arch_put_registers(cpu, KVM_PUT_RESET_STATE);
cpu->kvm_vcpu_dirty = false;
}
void kvm_cpu_synchronize_post_init(CPUArchState *env)
void kvm_cpu_synchronize_post_init(CPUState *cpu)
{
CPUState *cpu = ENV_GET_CPU(env);
kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE);
cpu->kvm_vcpu_dirty = false;
}

View file

@ -41,11 +41,11 @@ void kvm_cpu_synchronize_state(CPUArchState *env)
{
}
void kvm_cpu_synchronize_post_reset(CPUArchState *env)
void kvm_cpu_synchronize_post_reset(CPUState *cpu)
{
}
void kvm_cpu_synchronize_post_init(CPUArchState *env)
void kvm_cpu_synchronize_post_init(CPUState *cpu)
{
}

View file

@ -74,5 +74,6 @@ static inline CRISCPU *cris_env_get_cpu(CPUCRISState *env)
#define ENV_OFFSET offsetof(CRISCPU, env)
void cris_cpu_do_interrupt(CPUState *cpu);
void crisv10_cpu_do_interrupt(CPUState *cpu);
#endif

View file

@ -169,30 +169,38 @@ static void cris_cpu_initfn(Object *obj)
static void crisv8_cpu_class_init(ObjectClass *oc, void *data)
{
CPUClass *cc = CPU_CLASS(oc);
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
ccc->vr = 8;
cc->do_interrupt = crisv10_cpu_do_interrupt;
}
static void crisv9_cpu_class_init(ObjectClass *oc, void *data)
{
CPUClass *cc = CPU_CLASS(oc);
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
ccc->vr = 9;
cc->do_interrupt = crisv10_cpu_do_interrupt;
}
static void crisv10_cpu_class_init(ObjectClass *oc, void *data)
{
CPUClass *cc = CPU_CLASS(oc);
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
ccc->vr = 10;
cc->do_interrupt = crisv10_cpu_do_interrupt;
}
static void crisv11_cpu_class_init(ObjectClass *oc, void *data)
{
CPUClass *cc = CPU_CLASS(oc);
CRISCPUClass *ccc = CRIS_CPU_CLASS(oc);
ccc->vr = 11;
cc->do_interrupt = crisv10_cpu_do_interrupt;
}
static void crisv32_cpu_class_init(ObjectClass *oc, void *data)

View file

@ -45,6 +45,11 @@ void cris_cpu_do_interrupt(CPUState *cs)
env->pregs[PR_ERP] = env->pc;
}
void crisv10_cpu_do_interrupt(CPUState *cs)
{
cris_cpu_do_interrupt(cs);
}
int cpu_cris_handle_mmu_fault(CPUCRISState * env, target_ulong address, int rw,
int mmu_idx)
{
@ -109,9 +114,10 @@ int cpu_cris_handle_mmu_fault(CPUCRISState *env, target_ulong address, int rw,
return r;
}
static void do_interruptv10(CPUCRISState *env)
void crisv10_cpu_do_interrupt(CPUState *cs)
{
D(CPUState *cs = CPU(cris_env_get_cpu(env)));
CRISCPU *cpu = CRIS_CPU(cs);
CPUCRISState *env = &cpu->env;
int ex_vec = -1;
D_LOG("exception index=%d interrupt_req=%d\n",
@ -171,10 +177,6 @@ void cris_cpu_do_interrupt(CPUState *cs)
CPUCRISState *env = &cpu->env;
int ex_vec = -1;
if (env->pregs[PR_VR] < 32) {
return do_interruptv10(env);
}
D_LOG("exception index=%d interrupt_req=%d\n",
env->exception_index,
cs->interrupt_request);

View file

@ -1463,18 +1463,19 @@ void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf)
snprintf(buf, sizeof(buf), "%s", def->name);
(*cpu_fprintf)(f, "x86 %16s %-48s\n", buf, def->model_id);
}
if (kvm_enabled()) {
(*cpu_fprintf)(f, "x86 %16s\n", "[host]");
}
#ifdef CONFIG_KVM
(*cpu_fprintf)(f, "x86 %16s %-48s\n", "host",
"KVM processor with all supported host features "
"(only available in KVM mode)");
#endif
(*cpu_fprintf)(f, "\nRecognized CPUID flags:\n");
listflags(buf, sizeof(buf), (uint32_t)~0, feature_name, 1);
(*cpu_fprintf)(f, " %s\n", buf);
listflags(buf, sizeof(buf), (uint32_t)~0, ext_feature_name, 1);
(*cpu_fprintf)(f, " %s\n", buf);
listflags(buf, sizeof(buf), (uint32_t)~0, ext2_feature_name, 1);
(*cpu_fprintf)(f, " %s\n", buf);
listflags(buf, sizeof(buf), (uint32_t)~0, ext3_feature_name, 1);
(*cpu_fprintf)(f, " %s\n", buf);
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);
}
}
CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
@ -1562,7 +1563,7 @@ static void cpu_x86_register(X86CPU *cpu, const char *name, Error **errp)
object_property_set_str(OBJECT(cpu), def->model_id, "model-id", errp);
}
X86CPU *cpu_x86_init(const char *cpu_model)
X86CPU *cpu_x86_create(const char *cpu_model, Error **errp)
{
X86CPU *cpu = NULL;
CPUX86State *env;
@ -1592,13 +1593,25 @@ X86CPU *cpu_x86_init(const char *cpu_model)
goto out;
}
object_property_set_bool(OBJECT(cpu), true, "realized", &error);
out:
error_propagate(errp, error);
g_strfreev(model_pieces);
return cpu;
}
X86CPU *cpu_x86_init(const char *cpu_model)
{
Error *error = NULL;
X86CPU *cpu;
cpu = cpu_x86_create(cpu_model, &error);
if (error) {
goto out;
}
object_property_set_bool(OBJECT(cpu), true, "realized", &error);
out:
g_strfreev(model_pieces);
if (error) {
fprintf(stderr, "%s\n", error_get_pretty(error));
error_free(error);
@ -1868,12 +1881,13 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
if (env->cpuid_ext2_features & CPUID_EXT2_LM) {
/* 64 bit processor */
/* XXX: The physical address space is limited to 42 bits in exec.c. */
*eax = 0x00003028; /* 48 bits virtual, 40 bits physical */
*eax = 0x00003028; /* 48 bits virtual, 40 bits physical */
} else {
if (env->cpuid_features & CPUID_PSE36)
if (env->cpuid_features & CPUID_PSE36) {
*eax = 0x00000024; /* 36 bits physical */
else
} else {
*eax = 0x00000020; /* 32 bits physical */
}
}
*ebx = 0;
*ecx = 0;
@ -2049,9 +2063,8 @@ static void mce_init(X86CPU *cpu)
}
#ifndef CONFIG_USER_ONLY
static void x86_cpu_apic_init(X86CPU *cpu, Error **errp)
static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
{
static int apic_mapped;
CPUX86State *env = &cpu->env;
APICCommonState *apic;
const char *apic_type = "apic";
@ -2074,6 +2087,16 @@ static void x86_cpu_apic_init(X86CPU *cpu, Error **errp)
/* TODO: convert to link<> */
apic = APIC_COMMON(env->apic_state);
apic->cpu = cpu;
}
static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
{
CPUX86State *env = &cpu->env;
static int apic_mapped;
if (env->apic_state == NULL) {
return;
}
if (qdev_init(env->apic_state)) {
error_setg(errp, "APIC device '%s' could not be initialized",
@ -2091,6 +2114,10 @@ static void x86_cpu_apic_init(X86CPU *cpu, Error **errp)
apic_mapped = 1;
}
}
#else
static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
{
}
#endif
static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
@ -2098,9 +2125,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
X86CPU *cpu = X86_CPU(dev);
X86CPUClass *xcc = X86_CPU_GET_CLASS(dev);
CPUX86State *env = &cpu->env;
#ifndef CONFIG_USER_ONLY
Error *local_err = NULL;
#endif
if (env->cpuid_7_0_ebx_features && env->cpuid_level < 7) {
env->cpuid_level = 7;
@ -2130,8 +2155,9 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
} else {
if (check_cpuid && kvm_check_features_against_host(cpu)
&& enforce_cpuid) {
error_setg(errp, "Host's CPU doesn't support requested features");
return;
error_setg(&local_err,
"Host's CPU doesn't support requested features");
goto out;
}
#ifdef CONFIG_KVM
filter_features_for_kvm(cpu);
@ -2142,19 +2168,28 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
qemu_register_reset(x86_cpu_machine_reset_cb, cpu);
if (cpu->env.cpuid_features & CPUID_APIC || smp_cpus > 1) {
x86_cpu_apic_init(cpu, &local_err);
x86_cpu_apic_create(cpu, &local_err);
if (local_err != NULL) {
error_propagate(errp, local_err);
return;
goto out;
}
}
#endif
mce_init(cpu);
qemu_init_vcpu(&cpu->env);
x86_cpu_apic_realize(cpu, &local_err);
if (local_err != NULL) {
goto out;
}
cpu_reset(CPU(cpu));
xcc->parent_realize(dev, errp);
xcc->parent_realize(dev, &local_err);
out:
if (local_err != NULL) {
error_propagate(errp, local_err);
return;
}
}
/* Enables contiguous-apic-ID mode, for compatibility */

View file

@ -896,6 +896,7 @@ typedef struct CPUX86State {
#include "cpu-qom.h"
X86CPU *cpu_x86_init(const char *cpu_model);
X86CPU *cpu_x86_create(const char *cpu_model, Error **errp);
int cpu_x86_exec(CPUX86State *s);
void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf);
void x86_cpudef_setup(void);