From patchwork Thu Apr 19 14:08:41 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vasilis Liaskovitis X-Patchwork-Id: 153771 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 40BAAB6FE4 for ; Fri, 20 Apr 2012 00:10:32 +1000 (EST) Received: from localhost ([::1]:32848 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SKs45-0008KK-Sp for incoming@patchwork.ozlabs.org; Thu, 19 Apr 2012 10:10:29 -0400 Received: from eggs.gnu.org ([208.118.235.92]:37524) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SKs3i-0008DK-SH for qemu-devel@nongnu.org; Thu, 19 Apr 2012 10:10:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SKs3b-0005wk-IS for qemu-devel@nongnu.org; Thu, 19 Apr 2012 10:10:06 -0400 Received: from mail-bk0-f45.google.com ([209.85.214.45]:46206) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SKs3b-0005t5-88 for qemu-devel@nongnu.org; Thu, 19 Apr 2012 10:09:59 -0400 Received: by bkcji1 with SMTP id ji1so416444bkc.4 for ; Thu, 19 Apr 2012 07:09:57 -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=RtiyEHDOiKeY7o6l18m+PpuVy85hKFgU0PX6iAZBAb4=; b=KWdMKZ0I8MH4CPStfp3WSbCFhpfk/Q/iencpTkc98rNHJ0Do/C3pFTeLNA0dLYHkSL cgmU8ouzSRynvi7UXBIFxGic2d9/4nFddta6zsSIqlRLchY58GQq8r8sDwEcpR2UKcx5 3j6tpHyqfjJJTYzZFG4qxMfI2vaF6/GGwvEtPkGoC//rZ8bAvF1eNenGASBONIasgF38 0yaEvdUdDGZTZ8dadhE4BT9rCXA5KUk2LKxMCZtFnqeRN5wbZyDGh8kXnhQlKz6Xh3qh shI8iXAr6VxdDeKCVBnkNepe6BjoXS/xzhjzUmi2Yw+Gfm9YvHxsmDrodAxCyP7THOJf L+4w== Received: by 10.204.152.28 with SMTP id e28mr721353bkw.53.1334844597042; Thu, 19 Apr 2012 07:09:57 -0700 (PDT) Received: from dhcp-192-168-178-175.ri.profitbricks.localdomain ([62.217.45.26]) by mx.google.com with ESMTPS id gu12sm4434954bkc.1.2012.04.19.07.09.56 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 19 Apr 2012 07:09:56 -0700 (PDT) From: Vasilis Liaskovitis To: qemu-devel@nongnu.org, kvm@vger.kernel.org, seabios@seabios.org Date: Thu, 19 Apr 2012 16:08:41 +0200 Message-Id: <1334844527-18869-4-git-send-email-vasilis.liaskovitis@profitbricks.com> X-Mailer: git-send-email 1.7.9 In-Reply-To: <1334844527-18869-1-git-send-email-vasilis.liaskovitis@profitbricks.com> References: <1334844527-18869-1-git-send-email-vasilis.liaskovitis@profitbricks.com> X-Gm-Message-State: ALoCoQloeGFEf1jqjuH4HObWfQVz57xat/3YJhDucMmN31zsOywkmaiGKAUChaHS+VhSaZn0fUv/ X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.85.214.45 Cc: Vasilis Liaskovitis , avi@redhat.com, gleb@redhat.com Subject: [Qemu-devel] [RFC PATCH 3/9][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 (the method can be generalized to all memory though). Signed-off-by: Vasilis Liaskovitis --- src/acpi.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 147 insertions(+), 4 deletions(-) diff --git a/src/acpi.c b/src/acpi.c index 30888b9..5580099 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -484,6 +484,131 @@ build_ssdt(void) return ssdt; } +static unsigned char ssdt_mem[] = { + 0x5b,0x82,0x47,0x07,0x4d,0x50,0x41,0x41, + 0x08,0x49,0x44,0x5f,0x5f,0x0a,0xaa,0x08, + 0x5f,0x48,0x49,0x44,0x0c,0x41,0xd0,0x0c, + 0x80,0x08,0x5f,0x50,0x58,0x4d,0x0a,0xaa, + 0x08,0x5f,0x43,0x52,0x53,0x11,0x33,0x0a, + 0x30,0x8a,0x2b,0x00,0x00,0x0d,0x03,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xef, + 0xbe,0xad,0xde,0x00,0x00,0x00,0x00,0xee, + 0xbe,0xad,0xe6,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x79, + 0x00,0x14,0x0f,0x5f,0x53,0x54,0x41,0x00, + 0xa4,0x43,0x4d,0x53,0x54,0x49,0x44,0x5f, + 0x5f,0x14,0x0f,0x5f,0x45,0x4a,0x30,0x01, + 0x4d,0x50,0x45,0x4a,0x49,0x44,0x5f,0x5f, + 0x68 +}; + +#define SD_OFFSET_MEMHEX 6 +#define SD_OFFSET_MEMID 14 +#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, ssdt_mem, sizeof(ssdt_mem)); + 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; + + int length = ((1+3+4) + + (nb_memdevs * sizeof(ssdt_mem)) + + (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 += sizeof(ssdt_mem); + 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; + + 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); + *(ssdt_ptr++) = 0x00; + entry++; + } + build_header((void*)ssdt, SSDT_SIGNATURE, ssdt_ptr - ssdt, 1); + + return ssdt; +} + #include "ssdt-pcihp.hex" #define PCI_RMV_BASE 0xae0c @@ -580,18 +705,21 @@ build_srat(void) if (nb_numa_nodes == 0) return NULL; - u64 *numadata = malloc_tmphigh(sizeof(u64) * (MaxCountCPUs + nb_numa_nodes)); + qemu_cfg_get_numa_data(&nb_hp_memslots, 1); + + u64 *numadata = malloc_tmphigh(sizeof(u64) * (MaxCountCPUs + nb_numa_nodes + + 3 * nb_hp_memslots)); if (!numadata) { warn_noalloc(); return NULL; } - qemu_cfg_get_numa_data(numadata, MaxCountCPUs + nb_numa_nodes); + qemu_cfg_get_numa_data(numadata, MaxCountCPUs + nb_numa_nodes + 3 * nb_hp_memslots); 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) { @@ -627,6 +755,7 @@ build_srat(void) */ struct srat_memory_affinity *numamem = (void*)core; int slots = 0; + int node; u64 mem_len, mem_base, next_base = 0; acpi_build_srat_memory(numamem, 0, 640*1024, 0, 1); @@ -653,10 +782,23 @@ 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; + + for (i = 1; i < nb_hp_memslots + 1; ++i) { + mem_base = *numadata++; + mem_len = *numadata++; + node = *numadata++; + acpi_build_srat_memory(numamem, mem_base, mem_len, node, 1); + dprintf(1, "hotplug memory slot %d on node %d\n", i, node); numamem++; slots++; } - 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++; } @@ -707,6 +849,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();