From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1MEN6v-0004zU-0W for qemu-devel@nongnu.org; Wed, 10 Jun 2009 08:40:57 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1MEN6q-0004xR-0q for qemu-devel@nongnu.org; Wed, 10 Jun 2009 08:40:56 -0400 Received: from [199.232.76.173] (port=41154 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MEN6p-0004xE-SJ for qemu-devel@nongnu.org; Wed, 10 Jun 2009 08:40:51 -0400 Received: from mx2.redhat.com ([66.187.237.31]:43055) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1MEN6p-0005O1-8e for qemu-devel@nongnu.org; Wed, 10 Jun 2009 08:40:51 -0400 Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id n5ACeo6Y007146 for ; Wed, 10 Jun 2009 08:40:50 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx2.corp.redhat.com (8.13.1/8.13.1) with ESMTP id n5ACenj0008732 for ; Wed, 10 Jun 2009 08:40:50 -0400 Received: from dhcp-1-237.tlv.redhat.com (dhcp-1-237.tlv.redhat.com [10.35.1.237]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id n5ACemSx017572 for ; Wed, 10 Jun 2009 08:40:49 -0400 Date: Wed, 10 Jun 2009 15:40:48 +0300 From: Gleb Natapov Message-ID: <20090610124048.GH15949@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Subject: [Qemu-devel] [PATCH] Don't use cpu_index as apic_id. List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org (patch is on top of "Apic creation should not depend on pci" series) Currently cpu_index is used as cpu apic id on x86. This is incorrect since apic ids not have to be continuous (they can also encode cpu hierarchy information). This patch uses cpuid_apic_id for initial apic id value. For now cpuid_apic_id is set to be equal to cpu_index so behaviour is fully backward compatible, but it allows us to add qemu option to provide other values for cpu apic id. Signed-off-by: Gleb Natapov diff --git a/hw/apic.c b/hw/apic.c index 8c8b2de..000339b 100644 --- a/hw/apic.c +++ b/hw/apic.c @@ -83,12 +83,13 @@ typedef struct APICState { int count_shift; uint32_t initial_count; int64_t initial_count_load_time, next_time; + uint32_t idx; QEMUTimer *timer; } APICState; static int apic_io_memory; static APICState *local_apics[MAX_APICS + 1]; -static int last_apic_id = 0; +static int last_apic_idx = 0; static int apic_irq_delivered; @@ -400,6 +401,23 @@ static void apic_eoi(APICState *s) apic_update_irq(s); } +static int apic_find_dest(uint8_t dest) +{ + APICState *apic = local_apics[dest]; + int i; + + if (apic && apic->id == dest) + return dest; /* shortcut in case apic->id == apic->idx */ + + for (i = 0; i < MAX_APICS; i++) { + apic = local_apics[i]; + if (apic && apic->id == dest) + return i; + } + + return -1; +} + static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask, uint8_t dest, uint8_t dest_mode) { @@ -410,8 +428,10 @@ static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask, if (dest == 0xff) { memset(deliver_bitmask, 0xff, MAX_APIC_WORDS * sizeof(uint32_t)); } else { + int idx = apic_find_dest(dest); memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t)); - set_bit(deliver_bitmask, dest); + if (idx >= 0) + set_bit(deliver_bitmask, idx); } } else { /* XXX: cluster mode */ @@ -457,8 +477,7 @@ static void apic_init_ipi(APICState *s) cpu_reset(s->cpu_env); - if (!(s->apicbase & MSR_IA32_APICBASE_BSP)) - s->cpu_env->halted = 1; + s->cpu_env->halted = !(s->apicbase & MSR_IA32_APICBASE_BSP); } /* send a SIPI message to the CPU to start it */ @@ -487,14 +506,14 @@ static void apic_deliver(APICState *s, uint8_t dest, uint8_t dest_mode, break; case 1: memset(deliver_bitmask, 0x00, sizeof(deliver_bitmask)); - set_bit(deliver_bitmask, s->id); + set_bit(deliver_bitmask, s->idx); break; case 2: memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask)); break; case 3: memset(deliver_bitmask, 0xff, sizeof(deliver_bitmask)); - reset_bit(deliver_bitmask, s->id); + reset_bit(deliver_bitmask, s->idx); break; } @@ -870,13 +889,14 @@ static int apic_load(QEMUFile *f, void *opaque, int version_id) static void apic_reset(void *opaque) { APICState *s = opaque; + int bsp = cpu_is_bsp(s->cpu_env); s->apicbase = 0xfee00000 | - (s->id ? 0 : MSR_IA32_APICBASE_BSP) | MSR_IA32_APICBASE_ENABLE; + (bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE; apic_init_ipi(s); - if (s->id == 0) { + if (bsp) { /* * LINT0 delivery mode on CPU #0 is set to ExtInt at initialization * time typically by BIOS, so PIC interrupt can be delivered to the @@ -902,12 +922,12 @@ int apic_init(CPUState *env) { APICState *s; - if (last_apic_id >= MAX_APICS) + if (last_apic_idx >= MAX_APICS) return -1; s = qemu_mallocz(sizeof(APICState)); env->apic_state = s; - s->id = last_apic_id++; - env->cpuid_apic_id = s->id; + s->idx = last_apic_idx++; + s->id = env->cpuid_apic_id; s->cpu_env = env; apic_reset(s); @@ -923,10 +943,10 @@ int apic_init(CPUState *env) } s->timer = qemu_new_timer(vm_clock, apic_timer, s); - register_savevm("apic", s->id, 2, apic_save, apic_load, s); + register_savevm("apic", s->idx, 2, apic_save, apic_load, s); qemu_register_reset(apic_reset, 0, s); - local_apics[s->id] = s; + local_apics[s->idx] = s; return 0; } diff --git a/hw/pc.c b/hw/pc.c index 0cdc2a2..a8e2968 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -824,6 +824,11 @@ static int load_option_rom(const char *oprom, target_phys_addr_t start, return size; } +int cpu_is_bsp(CPUState *env) +{ + return env->cpuid_apic_id == 0; +} + /* PC hardware initialisation */ static void pc_init1(ram_addr_t ram_size, const char *boot_device, @@ -870,10 +875,9 @@ static void pc_init1(ram_addr_t ram_size, fprintf(stderr, "Unable to find x86 CPU definition\n"); exit(1); } - if (i != 0) - env->halted = 1; if ((env->cpuid_features & CPUID_APIC) || smp_cpus > 1) { /* APIC reset callback resets cpu */ + env->cpuid_apic_id = env->cpu_index; apic_init(env); } else { qemu_register_reset((QEMUResetHandler*)cpu_reset, 0, env); diff --git a/hw/pc.h b/hw/pc.h index acdd7ee..0afffa2 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -162,4 +162,5 @@ void pci_piix4_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn, void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd); +int cpu_is_bsp(CPUState *env); #endif -- Gleb.