From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:51276) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TM2Bi-0000Nq-F8 for qemu-devel@nongnu.org; Wed, 10 Oct 2012 15:43:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TM2Bg-0005cN-Sm for qemu-devel@nongnu.org; Wed, 10 Oct 2012 15:43:26 -0400 Received: from mx1.redhat.com ([209.132.183.28]:33522) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TM2Bg-0005cF-KF for qemu-devel@nongnu.org; Wed, 10 Oct 2012 15:43:24 -0400 From: Igor Mammedov Date: Wed, 10 Oct 2012 21:43:14 +0200 Message-Id: <1349898194-27140-1-git-send-email-imammedo@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [PATCH v4] target-i386: initialize APIC at CPU level List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: aliguori@us.ibm.com, ehabkost@redhat.com, jan.kiszka@siemens.com, Don@CloudSwitch.com, lcapitulino@redhat.com, afaerber@suse.de (L)APIC is a part of cpu [1] so move APIC initialization inside of x86_cpu object. Since cpu_model and override flags currently specify whether APIC should be created or not, APIC creation&initialization is moved into x86_cpu_apic_init() which is called from x86_cpu_realize(). [1] - all x86 cpus have integrated APIC if we overlook existence of i486, and it's more convenient to model after majority of them. Signed-off-by: Igor Mammedov --- v2: * init APIC mapping at cpu level, due to Peter's objection to putting it into APIC's initfn and Jan's suggestion to do it inside cpu. v3: * create APIC at realize time * rebased on top of current qemu tree * whitespace fix * ifdef only body of x86_cpu_apic_init() v4: * put hw/xen.h under #ifndef CONFIG_USER_ONLY * check for error after x86_cpu_apic_init() * remove unneeded 'return' v5: * use qdev_try_create() instead of qdev_create() to avoid abort at realize time. spotted-by: Andreas F=C3=A4rber v6: * use error_setg() instead of error_set() git tree for testing: https://github.com/imammedo/qemu/tree/apic_in_cpu.v4 --- hw/pc.c | 56 +++++--------------------------------------------= --- target-i386/cpu.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++= ++++++ 2 files changed, 64 insertions(+), 51 deletions(-) diff --git a/hw/pc.c b/hw/pc.c index 6c0722d..aa5abe0 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -70,8 +70,6 @@ #define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3) #define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4) =20 -#define MSI_ADDR_BASE 0xfee00000 - #define E820_NR_ENTRIES 16 =20 struct e820_entry { @@ -845,35 +843,6 @@ DeviceState *cpu_get_current_apic(void) } } =20 -static DeviceState *apic_init(void *env, uint8_t apic_id) -{ - DeviceState *dev; - static int apic_mapped; - - if (kvm_irqchip_in_kernel()) { - dev =3D qdev_create(NULL, "kvm-apic"); - } else if (xen_enabled()) { - dev =3D qdev_create(NULL, "xen-apic"); - } else { - dev =3D qdev_create(NULL, "apic"); - } - - qdev_prop_set_uint8(dev, "id", apic_id); - qdev_prop_set_ptr(dev, "cpu_env", env); - qdev_init_nofail(dev); - - /* XXX: mapping more APICs at the same memory location */ - if (apic_mapped =3D=3D 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(dev), 0, MSI_ADDR_BASE); - apic_mapped =3D 1; - } - - return dev; -} - void pc_acpi_smi_interrupt(void *opaque, int irq, int level) { CPUX86State *s =3D opaque; @@ -883,24 +852,6 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, in= t level) } } =20 -static X86CPU *pc_new_cpu(const char *cpu_model) -{ - X86CPU *cpu; - CPUX86State *env; - - cpu =3D cpu_x86_init(cpu_model); - if (cpu =3D=3D NULL) { - fprintf(stderr, "Unable to find x86 CPU definition\n"); - exit(1); - } - env =3D &cpu->env; - if ((env->cpuid_features & CPUID_APIC) || smp_cpus > 1) { - env->apic_state =3D apic_init(env, env->cpuid_apic_id); - } - cpu_reset(CPU(cpu)); - return cpu; -} - void pc_cpus_init(const char *cpu_model) { int i; @@ -914,8 +865,11 @@ void pc_cpus_init(const char *cpu_model) #endif } =20 - for(i =3D 0; i < smp_cpus; i++) { - pc_new_cpu(cpu_model); + for (i =3D 0; i < smp_cpus; i++) { + if (!cpu_x86_init(cpu_model)) { + fprintf(stderr, "Unable to find x86 CPU definition\n"); + exit(1); + } } } =20 diff --git a/target-i386/cpu.c b/target-i386/cpu.c index f3708e6..0f21fc5 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -37,6 +37,12 @@ #include #endif =20 +#include "sysemu.h" +#ifndef CONFIG_USER_ONLY +#include "hw/xen.h" +#include "hw/sysbus.h" +#endif + /* feature flags taken from "Intel Processor Identification and the CPUI= D * Instruction" and AMD's "CPUID Specification". In cases of disagreeme= nt * between feature naming conventions, aliases may be added. @@ -1870,14 +1876,67 @@ static void mce_init(X86CPU *cpu) } } =20 +#define MSI_ADDR_BASE 0xfee00000 + +static void x86_cpu_apic_init(X86CPU *cpu, Error **errp) +{ +#ifndef CONFIG_USER_ONLY + static int apic_mapped; + CPUX86State *env =3D &cpu->env; + const char *apic_type =3D "apic"; + + if (kvm_irqchip_in_kernel()) { + apic_type =3D "kvm-apic"; + } else if (xen_enabled()) { + apic_type =3D "xen-apic"; + } + + env->apic_state =3D qdev_try_create(NULL, apic_type); + if (env->apic_state =3D=3D NULL) { + error_setg(errp, "APIC device '%s' could not be created", apic_t= ype); + 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<> */ + qdev_prop_set_ptr(env->apic_state, "cpu_env", env); + + 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 =3D=3D 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_B= ASE); + apic_mapped =3D 1; + } +#endif +} + void x86_cpu_realize(Object *obj, Error **errp) { X86CPU *cpu =3D X86_CPU(obj); + CPUX86State *env =3D &cpu->env; =20 #ifndef CONFIG_USER_ONLY qemu_register_reset(x86_cpu_machine_reset_cb, cpu); #endif =20 + if (env->cpuid_features & CPUID_APIC || smp_cpus > 1) { + x86_cpu_apic_init(cpu, errp); + } + + if (error_is_set(errp)) { + return; + } + mce_init(cpu); qemu_init_vcpu(&cpu->env); cpu_reset(CPU(cpu)); --=20 1.7.11.4