diff options
| author | Anthony Liguori <aliguori@us.ibm.com> | 2012-11-01 11:12:32 -0500 |
|---|---|---|
| committer | Anthony Liguori <aliguori@us.ibm.com> | 2012-11-01 11:12:32 -0500 |
| commit | 98c8a73b2e82eecac359b0b55a2d9d69f0a916ff (patch) | |
| tree | 83411ea890eb54266773ad4337fc91c49dd36999 /target-i386/cpu.c | |
| parent | fc53b7d4b7fe409acae7d8d55a868eb5c696d71c (diff) | |
| parent | 839b5630cd4f49ce10618a7bf0b705b76f3a01ca (diff) | |
| download | focaccia-qemu-98c8a73b2e82eecac359b0b55a2d9d69f0a916ff.tar.gz focaccia-qemu-98c8a73b2e82eecac359b0b55a2d9d69f0a916ff.zip | |
Merge remote-tracking branch 'afaerber/qom-cpu' into staging
* afaerber/qom-cpu: (35 commits)
target-i386: Pass X86CPU to kvm_handle_halt()
target-i386: Pass X86CPU to kvm_get_mp_state()
cpu: Move thread_id to CPUState
cpus: Pass CPUState to run_on_cpu()
target-i386: Pass X86CPU to cpu_x86_inject_mce()
target-i386: Pass X86CPU to kvm_mce_inject()
cpus: Pass CPUState to [qemu_]cpu_has_work()
spapr: Pass PowerPCCPU to hypercalls
spapr: Pass PowerPCCPU to spapr_hypercall()
target-ppc: Pass PowerPCCPU to cpu_ppc_hypercall
target-ppc: Pass PowerPCCPU to powerpc_excp()
xtensa_pic: Pass XtensaCPU to xtensa_ccompare_cb()
cpus: Pass CPUState to qemu_wait_io_event_common()
cpus: Pass CPUState to flush_queued_work()
cpu: Move queued_work_{first,last} to CPUState
cpus: Pass CPUState to qemu_cpu_kick()
target-ppc: Rename kvm_kick_{env => cpu} and pass PowerPCCPU
ppc: Pass PowerPCCPU to {ppc6xx,ppc970,power7,ppc40x,ppce500}_set_irq()
cpus: Pass CPUState to qemu_tcg_init_vcpu()
cpus: Pass CPUState to qemu_tcg_cpu_thread_fn
...
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'target-i386/cpu.c')
| -rw-r--r-- | target-i386/cpu.c | 63 |
1 files changed, 62 insertions, 1 deletions
diff --git a/target-i386/cpu.c b/target-i386/cpu.c index d4f2e65cd9..156e9199ed 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -37,6 +37,13 @@ #include <linux/kvm_para.h> #endif +#include "sysemu.h" +#ifndef CONFIG_USER_ONLY +#include "hw/xen.h" +#include "hw/sysbus.h" +#include "hw/apic_internal.h" +#endif + /* feature flags taken from "Intel Processor Identification and the CPUID * Instruction" and AMD's "CPUID Specification". In cases of disagreement * between feature naming conventions, aliases may be added. @@ -1427,7 +1434,8 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) env->cpuid_svm_features &= TCG_SVM_FEATURES; } object_property_set_str(OBJECT(cpu), def->model_id, "model-id", &error); - if (error_is_set(&error)) { + if (error) { + fprintf(stderr, "%s\n", error_get_pretty(error)); error_free(error); return -1; } @@ -1878,12 +1886,65 @@ static void mce_init(X86CPU *cpu) } } +#define MSI_ADDR_BASE 0xfee00000 + +#ifndef CONFIG_USER_ONLY +static void x86_cpu_apic_init(X86CPU *cpu, Error **errp) +{ + static int apic_mapped; + CPUX86State *env = &cpu->env; + APICCommonState *apic; + const char *apic_type = "apic"; + + if (kvm_irqchip_in_kernel()) { + apic_type = "kvm-apic"; + } else if (xen_enabled()) { + apic_type = "xen-apic"; + } + + env->apic_state = qdev_try_create(NULL, apic_type); + if (env->apic_state == NULL) { + error_setg(errp, "APIC device '%s' could not be created", apic_type); + return; + } + + object_property_add_child(OBJECT(cpu), "apic", + OBJECT(env->apic_state), NULL); + qdev_prop_set_uint8(env->apic_state, "id", env->cpuid_apic_id); + /* TODO: convert to link<> */ + apic = APIC_COMMON(env->apic_state); + apic->cpu = cpu; + + if (qdev_init(env->apic_state)) { + error_setg(errp, "APIC device '%s' could not be initialized", + object_get_typename(OBJECT(env->apic_state))); + return; + } + + /* XXX: mapping more APICs at the same memory location */ + if (apic_mapped == 0) { + /* NOTE: the APIC is directly connected to the CPU - it is not + on the global memory bus. */ + /* XXX: what if the base changes? */ + sysbus_mmio_map(sysbus_from_qdev(env->apic_state), 0, MSI_ADDR_BASE); + apic_mapped = 1; + } +} +#endif + void x86_cpu_realize(Object *obj, Error **errp) { X86CPU *cpu = X86_CPU(obj); #ifndef CONFIG_USER_ONLY qemu_register_reset(x86_cpu_machine_reset_cb, cpu); + + if (cpu->env.cpuid_features & CPUID_APIC || smp_cpus > 1) { + x86_cpu_apic_init(cpu, errp); + if (error_is_set(errp)) { + return; + } + } #endif mce_init(cpu); |