From patchwork Wed Oct 7 16:16:50 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gleb Natapov X-Patchwork-Id: 35312 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 45305B7B7F for ; Thu, 8 Oct 2009 03:20:25 +1100 (EST) Received: from localhost ([127.0.0.1]:35584 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MvZFV-0001gL-Vw for incoming@patchwork.ozlabs.org; Wed, 07 Oct 2009 12:20:22 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1MvZCH-00073J-Fk for qemu-devel@nongnu.org; Wed, 07 Oct 2009 12:17:01 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1MvZCC-0006wA-7n for qemu-devel@nongnu.org; Wed, 07 Oct 2009 12:17:00 -0400 Received: from [199.232.76.173] (port=56873 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MvZCC-0006vv-0H for qemu-devel@nongnu.org; Wed, 07 Oct 2009 12:16:56 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51830) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1MvZCB-0000dL-DO for qemu-devel@nongnu.org; Wed, 07 Oct 2009 12:16:55 -0400 Received: from int-mx05.intmail.prod.int.phx2.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.18]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id n97GGrmE000663; Wed, 7 Oct 2009 12:16:53 -0400 Received: from dhcp-1-237.tlv.redhat.com (dhcp-1-237.tlv.redhat.com [10.35.1.237]) by int-mx05.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id n97GGq9b026128; Wed, 7 Oct 2009 12:16:53 -0400 Received: by dhcp-1-237.tlv.redhat.com (Postfix, from userid 13519) id 9AED61336CB; Wed, 7 Oct 2009 18:16:51 +0200 (IST) From: Gleb Natapov To: kevin@koconnor.net Date: Wed, 7 Oct 2009 18:16:50 +0200 Message-Id: <1254932211-28010-1-git-send-email-gleb@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.18 X-detected-operating-system: by monty-python.gnu.org: Genre and OS details not recognized. Cc: qemu-devel@nongnu.org Subject: [Qemu-devel] [PATCH 1/2] resolve memory device roll over reporting issues with >32G guests X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org The field within the Memory Device type 17 is only a word with the MSB being used to report MB/KB. Thereby, a guest with 32G and greater would report incorrect memory device information rolling over to 0. This presents more than one memory device and associated memory structures if the memory is larger than 16G This is port of commit e65bb0d2bd3a156408996674965555979de3a61b from qemu pc-bios tree. Signed-off-by: Gleb Natapov --- src/smbios.c | 70 +++++++++++++++++++++++++++++----------------------------- 1 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/smbios.c b/src/smbios.c index c408601..30dc853 100644 --- a/src/smbios.c +++ b/src/smbios.c @@ -366,7 +366,7 @@ smbios_type_4_init(void *start, unsigned int cpu_number) /* Type 16 -- Physical Memory Array */ static void * -smbios_type_16_init(void *start) +smbios_type_16_init(void *start, u32 memory_size_mb, int nr_mem_devs) { struct smbios_type_16 *p = (struct smbios_type_16*)start; @@ -377,10 +377,9 @@ smbios_type_16_init(void *start) p->location = 0x01; /* other */ p->use = 0x03; /* system memory */ p->error_correction = 0x01; /* other */ - u64 memsize = RamSize + RamSizeOver4G; - p->maximum_capacity = memsize / 1024; + p->maximum_capacity = memory_size_mb * 1024; p->memory_error_information_handle = 0xfffe; /* none provided */ - p->number_of_memory_devices = 1; + p->number_of_memory_devices = nr_mem_devs; start += sizeof(struct smbios_type_16); *((u16 *)start) = 0; @@ -390,21 +389,19 @@ smbios_type_16_init(void *start) /* Type 17 -- Memory Device */ static void * -smbios_type_17_init(void *start) +smbios_type_17_init(void *start, u32 memory_size_mb, int instance) { struct smbios_type_17 *p = (struct smbios_type_17 *)start; p->header.type = 17; p->header.length = sizeof(struct smbios_type_17); - p->header.handle = 0x1100; + p->header.handle = 0x1100 + instance; p->physical_memory_array_handle = 0x1000; p->total_width = 64; p->data_width = 64; - /* truncate memory_size_mb to 16 bits and clear most significant - bit [indicates size in MB] */ - u64 memsize = RamSize + RamSizeOver4G; - p->size = (u16) (memsize / (1024*1024)) & 0x7fff; +/* TODO: should assert in case something is wrong ASSERT((memory_size_mb & ~0x7fff) == 0); */ + p->size = memory_size_mb; p->form_factor = 0x09; /* DIMM */ p->device_set = 0; p->device_locator_str = 1; @@ -413,7 +410,8 @@ smbios_type_17_init(void *start) p->type_detail = 0; start += sizeof(struct smbios_type_17); - memcpy((char *)start, "DIMM 1", 7); + memcpy((char *)start, "DIMM 0", 7); + ((char*)start)[5] += instance; start += 7; *((u8 *)start) = 0; @@ -422,21 +420,16 @@ smbios_type_17_init(void *start) /* Type 19 -- Memory Array Mapped Address */ static void * -smbios_type_19_init(void *start) +smbios_type_19_init(void *start, u32 memory_size_mb, int instance) { struct smbios_type_19 *p = (struct smbios_type_19 *)start; p->header.type = 19; p->header.length = sizeof(struct smbios_type_19); - p->header.handle = 0x1300; + p->header.handle = 0x1300 + instance; - p->starting_address = 0; - u64 memsize = RamSizeOver4G; - if (memsize) - memsize += 0x100000000ull; - else - memsize = RamSize; - p->ending_address = memsize / 1024 - 1; + p->starting_address = instance << 24; + p->ending_address = p->starting_address + (memory_size_mb << 10) - 1; p->memory_array_handle = 0x1000; p->partition_width = 1; @@ -448,23 +441,18 @@ smbios_type_19_init(void *start) /* Type 20 -- Memory Device Mapped Address */ static void * -smbios_type_20_init(void *start) +smbios_type_20_init(void *start, u32 memory_size_mb, int instance) { struct smbios_type_20 *p = (struct smbios_type_20 *)start; p->header.type = 20; p->header.length = sizeof(struct smbios_type_20); - p->header.handle = 0x1400; + p->header.handle = 0x1400 + instance; - p->starting_address = 0; - u64 memsize = RamSizeOver4G; - if (memsize) - memsize += 0x100000000ull; - else - memsize = RamSize; - p->ending_address = memsize / 1024 - 1; - p->memory_device_handle = 0x1100; - p->memory_array_mapped_address_handle = 0x1300; + p->starting_address = instance << 24; + p->ending_address = p->starting_address + (memory_size_mb << 10) - 1; + p->memory_device_handle = 0x1100 + instance; + p->memory_array_mapped_address_handle = 0x1300 + instance; p->partition_row_position = 1; p->interleave_position = 0; p->interleaved_data_depth = 0; @@ -540,10 +528,22 @@ smbios_init(void) int cpu_num, smp_cpus = CountCPUs; for (cpu_num = 1; cpu_num <= smp_cpus; cpu_num++) add_struct(smbios_type_4_init(p, cpu_num)); - add_struct(smbios_type_16_init(p)); - add_struct(smbios_type_17_init(p)); - add_struct(smbios_type_19_init(p)); - add_struct(smbios_type_20_init(p)); + u64 memsize = RamSizeOver4G; + if (memsize) + memsize += 0x100000000ull; + else + memsize = RamSize; + memsize = memsize / (1024 * 1024); + int nr_mem_devs = (memsize + 0x3fff) >> 14; + add_struct(smbios_type_16_init(p, memsize, nr_mem_devs)); + int i; + for (i = 0; i < nr_mem_devs; i++) { + u32 dev_memsize = ((i == (nr_mem_devs - 1)) + ? (((memsize-1) & 0x3fff)+1) : 0x4000); + add_struct(smbios_type_17_init(p, dev_memsize, i)); + add_struct(smbios_type_19_init(p, dev_memsize, i)); + add_struct(smbios_type_20_init(p, dev_memsize, i)); + } add_struct(smbios_type_32_init(p)); add_struct(smbios_type_127_init(p));