diff --git a/cpus.c b/cpus.c index 97e9ab4c07..c15ff6c5fe 100644 --- a/cpus.c +++ b/cpus.c @@ -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)); } } diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index ddde18e6b4..ca1739ec84 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -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, diff --git a/hw/core/qdev.c b/hw/core/qdev.c index bab4ed7bf7..4eb01345df 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -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, diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c index ed9b448d07..3a10c0710c 100644 --- a/hw/i386/kvmvapic.c +++ b/hw/i386/kvmvapic.c @@ -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, diff --git a/hw/intc/ioapic_common.c b/hw/intc/ioapic_common.c index 42c7adc691..5c5bb3caaa 100644 --- a/hw/intc/ioapic_common.c +++ b/hw/intc/ioapic_common.c @@ -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; diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h index a37933998a..25dd1bb39a 100644 --- a/include/hw/qdev-properties.h +++ b/include/hw/qdev-properties.h @@ -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-" /** diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index f2d97b580d..495e6f8dbd 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -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); } } diff --git a/kvm-all.c b/kvm-all.c index 9b433d3163..fc4e17c8bb 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -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; } diff --git a/kvm-stub.c b/kvm-stub.c index f6137d343a..723a813735 100644 --- a/kvm-stub.c +++ b/kvm-stub.c @@ -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) { } diff --git a/target-cris/cpu-qom.h b/target-cris/cpu-qom.h index deea1d804b..03829bd243 100644 --- a/target-cris/cpu-qom.h +++ b/target-cris/cpu-qom.h @@ -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 diff --git a/target-cris/cpu.c b/target-cris/cpu.c index 95cbf399d9..67181e55a6 100644 --- a/target-cris/cpu.c +++ b/target-cris/cpu.c @@ -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) diff --git a/target-cris/helper.c b/target-cris/helper.c index e1ef7bcc0b..466cc2f9d5 100644 --- a/target-cris/helper.c +++ b/target-cris/helper.c @@ -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); diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 6dd993f847..e2302d8b05 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -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 */ diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 2b4e3193f3..cf1b05c28c 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -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);