From patchwork Tue Jul 10 20:22:23 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eduardo Habkost X-Patchwork-Id: 170282 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 CA6182C01FF for ; Wed, 11 Jul 2012 06:37:10 +1000 (EST) Received: from localhost ([::1]:38842 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SogxX-0006fx-Au for incoming@patchwork.ozlabs.org; Tue, 10 Jul 2012 16:22:59 -0400 Received: from eggs.gnu.org ([208.118.235.92]:42769) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Sogwk-0004xK-OT for qemu-devel@nongnu.org; Tue, 10 Jul 2012 16:22:12 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Sogwh-0001uZ-9d for qemu-devel@nongnu.org; Tue, 10 Jul 2012 16:22:10 -0400 Received: from mx1.redhat.com ([209.132.183.28]:5234) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Sogwh-0001tk-1b for qemu-devel@nongnu.org; Tue, 10 Jul 2012 16:22:07 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q6AKM48f024681 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 10 Jul 2012 16:22:05 -0400 Received: from blackpad.lan.raisama.net (vpn1-4-185.gru2.redhat.com [10.97.4.185]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q6AKM4XI025815; Tue, 10 Jul 2012 16:22:04 -0400 Received: by blackpad.lan.raisama.net (Postfix, from userid 500) id 836862044C5; Tue, 10 Jul 2012 17:22:49 -0300 (BRT) From: Eduardo Habkost To: qemu-devel@nongnu.org Date: Tue, 10 Jul 2012 17:22:23 -0300 Message-Id: <1341951743-2285-9-git-send-email-ehabkost@redhat.com> In-Reply-To: <1341951743-2285-1-git-send-email-ehabkost@redhat.com> References: <1341951743-2285-1-git-send-email-ehabkost@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Cc: Igor Mammedov , seabios@seabios.org, Gleb Natapov , Anthony Liguori Subject: [Qemu-devel] [Seabios RFC PATCH 1/1] get lapic IDs from fw_cfg 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 This changes: - MADT table generation - SRAT table generation Still missing: - The _MAT method on SSDT Processor entries still return the wrong APIC ID (breaking CPU hotplug) - The MPTable generation code doesn't take the new APIC IDs into account Signed-off-by: Eduardo Habkost --- src/acpi.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++-------- src/paravirt.c | 12 +++++++++++ src/paravirt.h | 13 ++++++++++++ 3 files changed, 80 insertions(+), 9 deletions(-) diff --git a/src/acpi.c b/src/acpi.c index 8549304..f9eafad 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -311,21 +311,40 @@ build_madt(void) + sizeof(struct madt_intsrcovr) * 16 + sizeof(struct madt_local_nmi)); - struct multiple_apic_table *madt = malloc_high(madt_size); + struct fw_cfg_lapic_info_entry *lapics = NULL; + struct multiple_apic_table *madt = NULL; + u64 lapic_count = qemu_cfg_get_lapic_count(); + + if (lapic_count) { + lapics = malloc_tmphigh(sizeof(*lapics) * lapic_count); + if (!lapics) { + warn_noalloc(); + goto out; + } + } + + qemu_cfg_get_lapic_info(lapics, lapic_count); + + madt = malloc_high(madt_size); if (!madt) { warn_noalloc(); - return NULL; + goto out; } + memset(madt, 0, madt_size); madt->local_apic_address = cpu_to_le32(BUILD_APIC_ADDR); madt->flags = cpu_to_le32(1); struct madt_processor_apic *apic = (void*)&madt[1]; int i; + int last_apic_id = -1; for (i=0; itype = APIC_PROCESSOR; apic->length = sizeof(*apic); apic->processor_id = i; - apic->local_apic_id = i; + if (i < lapic_count) + last_apic_id = apic->local_apic_id = lapics[i].apic_id; + else + apic->local_apic_id = ++last_apic_id; if (i < CountCPUs) apic->flags = cpu_to_le32(1); else @@ -371,6 +390,10 @@ build_madt(void) local_nmi++; build_header((void*)madt, APIC_SIGNATURE, (void*)local_nmi - (void*)madt, 1); + +out: + if (lapics) + free(lapics); return madt; } @@ -616,20 +639,35 @@ acpi_build_srat_memory(struct srat_memory_affinity *numamem, static void * build_srat(void) { + struct fw_cfg_lapic_info_entry *lapics = NULL; + u64 lapic_count = 0; + struct system_resource_affinity_table *srat = NULL; + u64 *numadata = NULL; int nb_numa_nodes = qemu_cfg_get_numa_nodes(); if (nb_numa_nodes == 0) - return NULL; + goto out; - u64 *numadata = malloc_tmphigh(sizeof(u64) * (MaxCountCPUs + nb_numa_nodes)); + numadata = malloc_tmphigh(sizeof(u64) * (MaxCountCPUs + nb_numa_nodes)); if (!numadata) { warn_noalloc(); - return NULL; + goto out; } qemu_cfg_get_numa_data(numadata, MaxCountCPUs + nb_numa_nodes); - struct system_resource_affinity_table *srat; + lapic_count = qemu_cfg_get_lapic_count(); + + if (lapic_count) { + lapics = malloc_tmphigh(sizeof(*lapics) * lapic_count); + if (!lapics) { + warn_noalloc(); + goto out; + } + } + + qemu_cfg_get_lapic_info(lapics, lapic_count); + int srat_size = sizeof(*srat) + sizeof(struct srat_processor_affinity) * MaxCountCPUs + sizeof(struct srat_memory_affinity) * (nb_numa_nodes + 2); @@ -646,11 +684,15 @@ build_srat(void) struct srat_processor_affinity *core = (void*)(srat + 1); int i; u64 curnode; + int last_apic_id = -1; for (i = 0; i < MaxCountCPUs; ++i) { core->type = SRAT_PROCESSOR; core->length = sizeof(*core); - core->local_apic_id = i; + if (i < lapic_count) + last_apic_id = core->local_apic_id = lapics[i].apic_id; + else + core->local_apic_id = ++last_apic_id; curnode = *numadata++; core->proximity_lo = curnode; memset(core->proximity_hi, 0, 3); @@ -704,7 +746,11 @@ build_srat(void) build_header((void*)srat, SRAT_SIGNATURE, srat_size, 1); - free(numadata); +out: + if (lapics) + free(lapics); + if (numadata) + free(numadata); return srat; } diff --git a/src/paravirt.c b/src/paravirt.c index 2a98d53..674d512 100644 --- a/src/paravirt.c +++ b/src/paravirt.c @@ -293,6 +293,18 @@ void qemu_cfg_get_numa_data(u64 *data, int n) qemu_cfg_read((u8*)(data + i), sizeof(u64)); } +u64 qemu_cfg_get_lapic_count(void) +{ + u64 cnt; + qemu_cfg_read_entry(&cnt, QEMU_CFG_LAPIC_INFO, sizeof(cnt)); + return cnt; +} + +void qemu_cfg_get_lapic_info(struct fw_cfg_lapic_info_entry *entries, u64 n) +{ + qemu_cfg_read((u8*)entries, sizeof(struct fw_cfg_lapic_info_entry)*n); +} + u16 qemu_cfg_get_max_cpus(void) { u16 cnt; diff --git a/src/paravirt.h b/src/paravirt.h index a284c41..5e3e500 100644 --- a/src/paravirt.h +++ b/src/paravirt.h @@ -40,6 +40,8 @@ static inline int kvm_para_available(void) #define QEMU_CFG_SMBIOS_ENTRIES (QEMU_CFG_ARCH_LOCAL + 1) #define QEMU_CFG_IRQ0_OVERRIDE (QEMU_CFG_ARCH_LOCAL + 2) #define QEMU_CFG_E820_TABLE (QEMU_CFG_ARCH_LOCAL + 3) +#define QEMU_CFG_LAPIC_INFO (QEMU_CFG_ARCH_LOCAL + 5) + extern int qemu_cfg_present; @@ -57,6 +59,17 @@ int qemu_cfg_smbios_load_external(int type, char **p, unsigned *nr_structs, int qemu_cfg_get_numa_nodes(void); void qemu_cfg_get_numa_data(u64 *data, int n); u16 qemu_cfg_get_max_cpus(void); + +struct fw_cfg_lapic_info_entry { + u8 apic_id; + u8 reserved1; + u16 reserved2; + u32 reserved3; +} PACKED; + +u64 qemu_cfg_get_lapic_count(void); +void qemu_cfg_get_lapic_info(struct fw_cfg_lapic_info_entry *entries, u64 n); + struct e820_reservation { u64 address; u64 length;