From patchwork Thu Oct 4 14:43:38 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Igor Mammedov X-Patchwork-Id: 189245 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id D6B762C03D0 for ; Fri, 5 Oct 2012 04:37:31 +1000 (EST) Received: from localhost ([::1]:45442 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TJqIb-0006CZ-Ct for incoming@patchwork.ozlabs.org; Thu, 04 Oct 2012 14:37:29 -0400 Received: from eggs.gnu.org ([208.118.235.92]:48413) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TJqIQ-0006BY-VP for qemu-devel@nongnu.org; Thu, 04 Oct 2012 14:37:22 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TJqIP-0002sY-2p for qemu-devel@nongnu.org; Thu, 04 Oct 2012 14:37:18 -0400 Received: from mx1.redhat.com ([209.132.183.28]:42787) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TJmeO-0005cj-3H for qemu-devel@nongnu.org; Thu, 04 Oct 2012 10:43:44 -0400 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q94EhgKE007226 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 4 Oct 2012 10:43:42 -0400 Received: from nial.brq.redhat.com (dhcp-1-247.brq.redhat.com [10.34.1.247]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q94EhdAk020964; Thu, 4 Oct 2012 10:43:39 -0400 From: Igor Mammedov To: qemu-devel@nongnu.org Date: Thu, 4 Oct 2012 16:43:38 +0200 Message-Id: <1349361818-15331-1-git-send-email-imammedo@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Cc: aliguori@us.ibm.com, ehabkost@redhat.com, gleb@redhat.com, Don@CloudSwitch.com, jan.kiszka@web.de, afaerber@suse.de Subject: [Qemu-devel] [PATCH] target-i386: initialize APIC at CPU level X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org (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() Git tree for testing: https://github.com/imammedo/qemu/tree/apic_in_cpu --- hw/pc.c | 56 +++++------------------------------------------------ target-i386/cpu.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 51 deletions(-) diff --git a/hw/pc.c b/hw/pc.c index 7e7e0e2..f4c0579 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -72,8 +72,6 @@ #define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3) #define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4) -#define MSI_ADDR_BASE 0xfee00000 - #define E820_NR_ENTRIES 16 struct e820_entry { @@ -847,35 +845,6 @@ DeviceState *cpu_get_current_apic(void) } } -static DeviceState *apic_init(void *env, uint8_t apic_id) -{ - DeviceState *dev; - static int apic_mapped; - - if (kvm_irqchip_in_kernel()) { - dev = qdev_create(NULL, "kvm-apic"); - } else if (xen_enabled()) { - dev = qdev_create(NULL, "xen-apic"); - } else { - dev = 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 == 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 = 1; - } - - return dev; -} - void pc_acpi_smi_interrupt(void *opaque, int irq, int level) { CPUX86State *s = opaque; @@ -885,24 +854,6 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level) } } -static X86CPU *pc_new_cpu(const char *cpu_model) -{ - X86CPU *cpu; - CPUX86State *env; - - cpu = cpu_x86_init(cpu_model); - if (cpu == NULL) { - fprintf(stderr, "Unable to find x86 CPU definition\n"); - exit(1); - } - env = &cpu->env; - if ((env->cpuid_features & CPUID_APIC) || smp_cpus > 1) { - env->apic_state = apic_init(env, env->cpuid_apic_id); - } - cpu_reset(CPU(cpu)); - return cpu; -} - void pc_cpus_init(const char *cpu_model) { int i; @@ -916,8 +867,11 @@ void pc_cpus_init(const char *cpu_model) #endif } - for(i = 0; i < smp_cpus; i++) { - pc_new_cpu(cpu_model); + for (i = 0; i < smp_cpus; i++) { + if (!cpu_x86_init(cpu_model)) { + fprintf(stderr, "Unable to find x86 CPU definition\n"); + exit(1); + } } } diff --git a/target-i386/cpu.c b/target-i386/cpu.c index bb1e44e..612ed5a 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -37,6 +37,12 @@ #include #endif +#include "sysemu.h" +#include "hw/xen.h" +#ifndef CONFIG_USER_ONLY +#include "hw/sysbus.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. @@ -1870,6 +1876,56 @@ static void mce_init(X86CPU *cpu) } } +#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 = &cpu->env; + const char *apic_type = "apic"; + + if (!(env->cpuid_features & CPUID_APIC || smp_cpus > 1)) { + return; + } + + if (kvm_irqchip_in_kernel()) { + apic_type = "kvm-apic"; + } else if (xen_enabled()) { + apic_type = "xen-apic"; + } + env->apic_state = qdev_create(NULL, apic_type); + + if (env->apic_state == NULL) { + error_set(errp, QERR_DEVICE_INIT_FAILED, 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<> */ + qdev_prop_set_ptr(env->apic_state, "cpu_env", env); + + if (qdev_init(env->apic_state)) { + error_set(errp, QERR_DEVICE_INIT_FAILED, + 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; + } + + return; +#endif +} + void x86_cpu_realize(Object *obj, Error **errp) { X86CPU *cpu = X86_CPU(obj); @@ -1878,6 +1934,8 @@ void x86_cpu_realize(Object *obj, Error **errp) qemu_register_reset(x86_cpu_machine_reset_cb, cpu); #endif + x86_cpu_apic_init(cpu, errp); + mce_init(cpu); qemu_init_vcpu(&cpu->env); cpu_reset(CPU(cpu));