From patchwork Wed Jul 11 10:31:49 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vasilis Liaskovitis X-Patchwork-Id: 170443 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 CAA522C01FA for ; Wed, 11 Jul 2012 21:53:46 +1000 (EST) Received: from localhost ([::1]:41599 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SouES-00055v-Tq for incoming@patchwork.ozlabs.org; Wed, 11 Jul 2012 06:33:20 -0400 Received: from eggs.gnu.org ([208.118.235.92]:44224) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SouDV-0003KP-W0 for qemu-devel@nongnu.org; Wed, 11 Jul 2012 06:32:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SouDQ-0005pn-4r for qemu-devel@nongnu.org; Wed, 11 Jul 2012 06:32:21 -0400 Received: from mail-bk0-f45.google.com ([209.85.214.45]:61756) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SouDP-0005ow-Po for qemu-devel@nongnu.org; Wed, 11 Jul 2012 06:32:16 -0400 Received: by bkcji1 with SMTP id ji1so712868bkc.4 for ; Wed, 11 Jul 2012 03:32:13 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=rxeFQlwCYqLjyRlr3oMNwwpA0EiKZQ7vvtkXvSRyLSc=; b=DLpWPHT2niffPfYn0tHHbyL52ggLwndoNqhtQwuKtLSsXe2C79xNU76WfTvdZp6Q7p Ct7gtzj0JGNUs+rMQWPv81kWh1dztTWESUFo/ay9vbXGGdU8uac33kjOKW9THWve9Kk2 L4bA5GR9tZHO7GqmXau4rY6OchBX21tAi0QXJY3J//lctaX5sckURNXyy4vUbr89BGtR TYmV99WodRy24zgVb5S9zmz73VBkg/8kwfN7/MFHEjdupXpwMnQlckuFcI0nTf06D0z6 HN60gH2blpQStiCVcG437wEbuxfqKqJDdpzCdFY0w/bE4Y7pgYPptRT2Px5iuvPFLCio +B6Q== Received: by 10.204.130.156 with SMTP id t28mr21904332bks.33.1342002733488; Wed, 11 Jul 2012 03:32:13 -0700 (PDT) Received: from dhcp-192-168-178-175.ri.profitbricks.localdomain ([62.217.45.26]) by mx.google.com with ESMTPS id e20sm794740bkv.10.2012.07.11.03.32.12 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 11 Jul 2012 03:32:13 -0700 (PDT) From: Vasilis Liaskovitis To: qemu-devel@nongnu.org, kvm@vger.kernel.org, seabios@seabios.org Date: Wed, 11 Jul 2012 12:31:49 +0200 Message-Id: <1342002726-18258-5-git-send-email-vasilis.liaskovitis@profitbricks.com> X-Mailer: git-send-email 1.7.9 In-Reply-To: <1342002726-18258-1-git-send-email-vasilis.liaskovitis@profitbricks.com> References: <1342002726-18258-1-git-send-email-vasilis.liaskovitis@profitbricks.com> X-Gm-Message-State: ALoCoQnPP2L7l0pl3gkpLE3xbZWEUKWkOHWbMAto6HM7uMZJWpJhOl9g42bD8tG2Y1lnXdgqcLcI X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.85.214.45 Cc: gleb@redhat.com, Vasilis Liaskovitis , kevin@koconnor.net, avi@redhat.com, anthony@codemonkey.ws, imammedo@redhat.com Subject: [Qemu-devel] [RFC PATCH v2 04/21][SeaBIOS] acpi: generate hotplug memory devices 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 The memory device generation is guided by qemu paravirt info. Seabios first uses the info to setup SRAT entries for the hotplug-able memory slots. Afterwards, build_memssdt uses the created SRAT entries to generate appropriate memory device objects. One memory device (and corresponding SRAT entry) is generated for each hotplug-able qemu memslot. Currently no SSDT memory device is created for initial system memory. We only support up to 255 DIMMs for now (PackageOp used for the MEON array can only describe an array of at most 255 elements. VarPackageOp would be needed to support more than 255 devices) v1->v2: Seabios reads mems_sts from qemu to build e820_map SSDT size and some offsets are calculated with extraction macros. Signed-off-by: Vasilis Liaskovitis --- src/acpi.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 152 insertions(+), 6 deletions(-) diff --git a/src/acpi.c b/src/acpi.c index 55e4607..c83e8c7 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -510,6 +510,127 @@ build_ssdt(void) return ssdt; } +#include "ssdt-mem.hex" + +/* 0x5B 0x82 DeviceOp PkgLength NameString DimmID */ +#define MEM_BASE 0xaf80 +#define SD_MEM (ssdm_mem_aml + *ssdt_mem_start) +#define SD_MEMSIZEOF (*ssdt_mem_end - *ssdt_mem_start) +#define SD_OFFSET_MEMHEX (*ssdt_mem_name - *ssdt_mem_start + 2) +#define SD_OFFSET_MEMID (*ssdt_mem_id - *ssdt_mem_start) +#define SD_OFFSET_PXMID 31 +#define SD_OFFSET_MEMSTART 55 +#define SD_OFFSET_MEMEND 63 +#define SD_OFFSET_MEMSIZE 79 + +u64 nb_hp_memslots = 0; +struct srat_memory_affinity *mem; + +static void build_memdev(u8 *ssdt_ptr, int i, u64 mem_base, u64 mem_len, u8 node) +{ + memcpy(ssdt_ptr, SD_MEM, SD_MEMSIZEOF); + ssdt_ptr[SD_OFFSET_MEMHEX] = getHex(i >> 4); + ssdt_ptr[SD_OFFSET_MEMHEX+1] = getHex(i); + ssdt_ptr[SD_OFFSET_MEMID] = i; + ssdt_ptr[SD_OFFSET_PXMID] = node; + *(u64*)(ssdt_ptr + SD_OFFSET_MEMSTART) = mem_base; + *(u64*)(ssdt_ptr + SD_OFFSET_MEMEND) = mem_base + mem_len; + *(u64*)(ssdt_ptr + SD_OFFSET_MEMSIZE) = mem_len; +} + +static void* +build_memssdt(void) +{ + u64 mem_base; + u64 mem_len; + u8 node; + int i; + struct srat_memory_affinity *entry = mem; + u64 nb_memdevs = nb_hp_memslots; + u8 memslot_status, enabled; + + int length = ((1+3+4) + + (nb_memdevs * SD_MEMSIZEOF) + + (1+2+5+(12*nb_memdevs)) + + (6+2+1+(1*nb_memdevs))); + u8 *ssdt = malloc_high(sizeof(struct acpi_table_header) + length); + if (! ssdt) { + warn_noalloc(); + return NULL; + } + u8 *ssdt_ptr = ssdt + sizeof(struct acpi_table_header); + + // build Scope(_SB_) header + *(ssdt_ptr++) = 0x10; // ScopeOp + ssdt_ptr = encodeLen(ssdt_ptr, length-1, 3); + *(ssdt_ptr++) = '_'; + *(ssdt_ptr++) = 'S'; + *(ssdt_ptr++) = 'B'; + *(ssdt_ptr++) = '_'; + + for (i = 0; i < nb_memdevs; i++) { + mem_base = (((u64)(entry->base_addr_high) << 32 )| entry->base_addr_low); + mem_len = (((u64)(entry->length_high) << 32 )| entry->length_low); + node = entry->proximity[0]; + build_memdev(ssdt_ptr, i, mem_base, mem_len, node); + ssdt_ptr += SD_MEMSIZEOF; + entry++; + } + + // build "Method(MTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CM00, Arg1)} ...}" + *(ssdt_ptr++) = 0x14; // MethodOp + ssdt_ptr = encodeLen(ssdt_ptr, 2+5+(12*nb_memdevs), 2); + *(ssdt_ptr++) = 'M'; + *(ssdt_ptr++) = 'T'; + *(ssdt_ptr++) = 'F'; + *(ssdt_ptr++) = 'Y'; + *(ssdt_ptr++) = 0x02; + for (i=0; i> 4); + *(ssdt_ptr++) = getHex(i); + *(ssdt_ptr++) = 0x69; // Arg1Op + } + + // build "Name(MEON, Package() { One, One, ..., Zero, Zero, ... })" + *(ssdt_ptr++) = 0x08; // NameOp + *(ssdt_ptr++) = 'M'; + *(ssdt_ptr++) = 'E'; + *(ssdt_ptr++) = 'O'; + *(ssdt_ptr++) = 'N'; + *(ssdt_ptr++) = 0x12; // PackageOp + ssdt_ptr = encodeLen(ssdt_ptr, 2+1+(1*nb_memdevs), 2); + *(ssdt_ptr++) = nb_memdevs; + + entry = mem; + memslot_status = 0; + + for (i = 0; i < nb_memdevs; i++) { + enabled = 0; + if (i % 8 == 0) + memslot_status = inb(MEM_BASE + i/8); + enabled = memslot_status & 1; + mem_base = (((u64)(entry->base_addr_high) << 32 )| entry->base_addr_low); + mem_len = (((u64)(entry->length_high) << 32 )| entry->length_low); + *(ssdt_ptr++) = enabled ? 0x01 : 0x00; + if (enabled) + add_e820(mem_base, mem_len, E820_RAM); + memslot_status = memslot_status >> 1; + entry++; + } + build_header((void*)ssdt, SSDT_SIGNATURE, ssdt_ptr - ssdt, 1); + + return ssdt; +} + #include "ssdt-pcihp.hex" #define PCI_RMV_BASE 0xae0c @@ -618,9 +739,6 @@ build_srat(void) { int nb_numa_nodes = qemu_cfg_get_numa_nodes(); - if (nb_numa_nodes == 0) - return NULL; - u64 *numadata = malloc_tmphigh(sizeof(u64) * (MaxCountCPUs + nb_numa_nodes)); if (!numadata) { warn_noalloc(); @@ -629,10 +747,11 @@ build_srat(void) qemu_cfg_get_numa_data(numadata, MaxCountCPUs + nb_numa_nodes); + qemu_cfg_get_numa_data(&nb_hp_memslots, 1); struct system_resource_affinity_table *srat; int srat_size = sizeof(*srat) + sizeof(struct srat_processor_affinity) * MaxCountCPUs + - sizeof(struct srat_memory_affinity) * (nb_numa_nodes + 2); + sizeof(struct srat_memory_affinity) * (nb_numa_nodes + nb_hp_memslots + 2); srat = malloc_high(srat_size); if (!srat) { @@ -667,7 +786,7 @@ build_srat(void) * from 640k-1M and possibly another one from 3.5G-4G. */ struct srat_memory_affinity *numamem = (void*)core; - int slots = 0; + int slots = 0, node; u64 mem_len, mem_base, next_base = 0; acpi_build_srat_memory(numamem, 0, 640*1024, 0, 1); @@ -694,10 +813,36 @@ build_srat(void) next_base += (1ULL << 32) - RamSize; } acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1); + numamem++; slots++; + + } + mem = (void*)numamem; + + if (nb_hp_memslots) { + u64 *hpmemdata = malloc_tmphigh(sizeof(u64) * (3 * nb_hp_memslots)); + if (!hpmemdata) { + warn_noalloc(); + free(hpmemdata); + free(numadata); + return NULL; + } + + qemu_cfg_get_numa_data(hpmemdata, 3 * nb_hp_memslots); + + for (i = 1; i < nb_hp_memslots + 1; ++i) { + mem_base = *hpmemdata++; + mem_len = *hpmemdata++; + node = *hpmemdata++; + acpi_build_srat_memory(numamem, mem_base, mem_len, node, 1); + numamem++; + slots++; + } + free(hpmemdata); } - for (; slots < nb_numa_nodes + 2; slots++) { + + for (; slots < nb_numa_nodes + nb_hp_memslots + 2; slots++) { acpi_build_srat_memory(numamem, 0, 0, 0, 0); numamem++; } @@ -748,6 +893,7 @@ acpi_bios_init(void) ACPI_INIT_TABLE(build_madt()); ACPI_INIT_TABLE(build_hpet()); ACPI_INIT_TABLE(build_srat()); + ACPI_INIT_TABLE(build_memssdt()); ACPI_INIT_TABLE(build_pcihp()); u16 i, external_tables = qemu_cfg_acpi_additional_tables();