From patchwork Wed Jul 25 18:45:30 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eduardo Habkost X-Patchwork-Id: 173242 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 01E8C2C00A4 for ; Thu, 26 Jul 2012 04:45:26 +1000 (EST) Received: from localhost ([::1]:33082 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Su6aK-0007DC-1c for incoming@patchwork.ozlabs.org; Wed, 25 Jul 2012 14:45:24 -0400 Received: from eggs.gnu.org ([208.118.235.92]:50316) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Su6a1-00073U-6O for qemu-devel@nongnu.org; Wed, 25 Jul 2012 14:45:06 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Su6Zz-0001hh-Cr for qemu-devel@nongnu.org; Wed, 25 Jul 2012 14:45:05 -0400 Received: from mx1.redhat.com ([209.132.183.28]:18517) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Su6Zz-0001ga-4A for qemu-devel@nongnu.org; Wed, 25 Jul 2012 14:45:03 -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 q6PIj194015175 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 25 Jul 2012 14:45:01 -0400 Received: from blackpad.lan.raisama.net (ovpn-116-43.ams2.redhat.com [10.36.116.43]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q6PIimDA015449; Wed, 25 Jul 2012 14:44:57 -0400 From: Eduardo Habkost To: qemu-devel@nongnu.org, seabios@seabios.org Date: Wed, 25 Jul 2012 15:45:30 -0300 Message-Id: <1343241930-9506-3-git-send-email-ehabkost@redhat.com> In-Reply-To: <1343241930-9506-1-git-send-email-ehabkost@redhat.com> References: <1343241930-9506-1-git-send-email-ehabkost@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: Igor Mammedov , Kevin O'Connor , Laszlo Ersek , Gleb Natapov Subject: [Qemu-devel] [SeaBIOS PATCH 2/2] allow CPUs to have non-contiguous Local APIC IDs (v2) 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 Extract Local APIC IDs directly from the CPUs, and instead of check for "i < CountCPUs", check if the APIC ID was present on boot, when building ACPI tables and the MP-Table. This keeps ACPI Processor ID == APIC ID, but allows the hardware<->SeaBIOS interface be completely APIC-ID based and not depend on any other kind of "CPU identifier". This way, SeaBIOS may change the way ACPI Processor IDs are chosen in the future. As currently SeaBIOS supports only xAPIC and not x2APIC, the list of present-on-boot APIC IDs is a 256-bit bitmap. If one day SeaBIOS starts to support x2APIC, the data structure used to enumerate the APIC IDs will have to be changed (but this is an internal implementation detail, not visible to the OS or on any hardware<=>SeaBIOS interface). For current QEMU versions (that always make the APIC IDs contiguous), the OS-visible behavior and resulting ACPI tables should be exactly the same. This patch will simply allow QEMU to start setting non-contiguous APIC IDs (that is a requirement for some sockets/cores/threads topology settings). Changes v1 -> v2: - Use size suffixes on all asm instructions on smp.c - New patch description Signed-off-by: Eduardo Habkost --- src/acpi-dsdt.dsl | 4 +++- src/acpi.c | 9 +++++---- src/mptable.c | 2 +- src/smp.c | 17 +++++++++++++++++ src/util.h | 1 + 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/acpi-dsdt.dsl b/src/acpi-dsdt.dsl index 2060686..72dc7d8 100644 --- a/src/acpi-dsdt.dsl +++ b/src/acpi-dsdt.dsl @@ -676,6 +676,7 @@ DefinitionBlock ( /* Methods called by run-time generated SSDT Processor objects */ Method (CPMA, 1, NotSerialized) { // _MAT method - create an madt apic buffer + // Arg0 = Processor ID = Local APIC ID // Local0 = CPON flag for this cpu Store(DerefOf(Index(CPON, Arg0)), Local0) // Local1 = Buffer (in madt apic form) to return @@ -688,6 +689,7 @@ DefinitionBlock ( } Method (CPST, 1, NotSerialized) { // _STA method - return ON status of cpu + // Arg0 = Processor ID = Local APIC ID // Local0 = CPON flag for this cpu Store(DerefOf(Index(CPON, Arg0)), Local0) If (Local0) { Return(0xF) } Else { Return(0x0) } @@ -708,7 +710,7 @@ DefinitionBlock ( Store (PRS, Local5) // Local2 = last read byte from bitmap Store (Zero, Local2) - // Local0 = cpuid iterator + // Local0 = Processor ID / APIC ID iterator Store (Zero, Local0) While (LLess(Local0, SizeOf(CPON))) { // Local1 = CPON flag for this cpu diff --git a/src/acpi.c b/src/acpi.c index da3bc57..39b7172 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -327,7 +327,7 @@ build_madt(void) apic->length = sizeof(*apic); apic->processor_id = i; apic->local_apic_id = i; - if (i < CountCPUs) + if (apic_id_is_present(apic->local_apic_id)) apic->flags = cpu_to_le32(1); else apic->flags = cpu_to_le32(0); @@ -445,6 +445,7 @@ build_ssdt(void) } // build "Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...}" + // Arg0 = Processor ID = APIC ID *(ssdt_ptr++) = 0x14; // MethodOp ssdt_ptr = encodeLen(ssdt_ptr, 2+5+(12*acpi_cpus), 2); *(ssdt_ptr++) = 'N'; @@ -477,7 +478,7 @@ build_ssdt(void) ssdt_ptr = encodeLen(ssdt_ptr, 2+1+(1*acpi_cpus), 2); *(ssdt_ptr++) = acpi_cpus; for (i=0; iproximity_lo = curnode; memset(core->proximity_hi, 0, 3); core->local_sapic_eid = 0; - if (i < CountCPUs) + if (apic_id_is_present(i)) core->flags = cpu_to_le32(1); else - core->flags = 0; + core->flags = cpu_to_le32(0); core++; } diff --git a/src/mptable.c b/src/mptable.c index 74ed33d..3aa3427 100644 --- a/src/mptable.c +++ b/src/mptable.c @@ -59,7 +59,7 @@ mptable_init(void) cpu->apicid = i; cpu->apicver = apic_version; /* cpu flags: enabled, bootstrap cpu */ - cpu->cpuflag = ((icpuflag = (apic_id_is_present(i) ? 0x01 : 0x00) | ((i==0) ? 0x02 : 0x00); cpu->cpusignature = cpuid_signature; cpu->featureflag = cpuid_features; cpu++; diff --git a/src/smp.c b/src/smp.c index 8c077a1..3c36f8c 100644 --- a/src/smp.c +++ b/src/smp.c @@ -36,6 +36,8 @@ wrmsr_smp(u32 index, u64 val) u32 CountCPUs VAR16VISIBLE; u32 MaxCountCPUs VAR16VISIBLE; +// 256 bits for the found APIC IDs +u32 FoundAPICIDs[256/32] VAR16VISIBLE; extern void smp_ap_boot_code(void); ASM16( " .global smp_ap_boot_code\n" @@ -59,6 +61,12 @@ ASM16( " jmp 1b\n" "2:\n" + // get apic ID on EBX, set bit on FoundAPICIDs + " movl $1, %eax\n" + " cpuid\n" + " shrl $24, %ebx\n" + " lock btsl %ebx, FoundAPICIDs\n" + // Increment the cpu counter " lock incl CountCPUs\n" @@ -67,6 +75,11 @@ ASM16( " jmp 1b\n" ); +int apic_id_is_present(u8 apic_id) +{ + return FoundAPICIDs[apic_id/32] & (1 << (apic_id % 32)); +} + // find and initialize the CPUs by launching a SIPI to them void smp_probe(void) @@ -82,6 +95,10 @@ smp_probe(void) return; } + // mark the BSP initial APIC ID as found, too: + u8 apic_id = ebx>>24; + FoundAPICIDs[apic_id/32] |= (1 << (apic_id % 32)); + // Init the counter. writel(&CountCPUs, 1); diff --git a/src/util.h b/src/util.h index ef8ec7c..89e928c 100644 --- a/src/util.h +++ b/src/util.h @@ -355,6 +355,7 @@ extern u32 CountCPUs; extern u32 MaxCountCPUs; void wrmsr_smp(u32 index, u64 val); void smp_probe(void); +int apic_id_is_present(u8 apic_id); // coreboot.c extern const char *CBvendor, *CBpart;