[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [patch 8/9] kvm: bios: resolve memory device roll over repo
From: |
Marcelo Tosatti |
Subject: |
[Qemu-devel] [patch 8/9] kvm: bios: resolve memory device roll over reporting issues with >32G guests |
Date: |
Tue, 20 Jan 2009 00:30:48 -0200 |
User-agent: |
quilt/0.47-1 |
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
Signed-off-by: Bill Rieske <address@hidden>
Signed-off-by: Avi Kivity <address@hidden>
From: Bill Rieske <address@hidden>
Index: bochs/bios/rombios32.c
===================================================================
--- bochs.orig/bios/rombios32.c
+++ bochs/bios/rombios32.c
@@ -381,6 +381,17 @@ int vsnprintf(char *buf, int buflen, con
return buf - buf0;
}
+int snprintf(char * buf, size_t size, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vsnprintf(buf,size,fmt,args);
+ va_end(args);
+ return i;
+}
+
void bios_printf(int flags, const char *fmt, ...)
{
va_list ap;
@@ -2039,7 +2050,7 @@ smbios_type_4_init(void *start, unsigned
/* Type 16 -- Physical Memory Array */
static void *
-smbios_type_16_init(void *start, uint32_t memsize)
+smbios_type_16_init(void *start, uint32_t memsize, int nr_mem_devs)
{
struct smbios_type_16 *p = (struct smbios_type_16*)start;
@@ -2052,7 +2063,7 @@ smbios_type_16_init(void *start, uint32_
p->error_correction = 0x01; /* other */
p->maximum_capacity = memsize * 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);
*((uint16_t *)start) = 0;
@@ -2062,20 +2073,19 @@ smbios_type_16_init(void *start, uint32_
/* Type 17 -- Memory Device */
static void *
-smbios_type_17_init(void *start, uint32_t memory_size_mb)
+smbios_type_17_init(void *start, uint32_t 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] */
- p->size = (uint16_t) memory_size_mb & 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;
@@ -2084,8 +2094,8 @@ smbios_type_17_init(void *start, uint32_
p->type_detail = 0;
start += sizeof(struct smbios_type_17);
- memcpy((char *)start, "DIMM 1", 7);
- start += 7;
+ snprintf(start, 8, "DIMM %d", instance);
+ start += strlen(start) + 1;
*((uint8_t *)start) = 0;
return start+1;
@@ -2093,16 +2103,16 @@ smbios_type_17_init(void *start, uint32_
/* Type 19 -- Memory Array Mapped Address */
static void *
-smbios_type_19_init(void *start, uint32_t memory_size_mb)
+smbios_type_19_init(void *start, uint32_t 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;
- p->ending_address = (memory_size_mb * 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;
@@ -2114,18 +2124,18 @@ smbios_type_19_init(void *start, uint32_
/* Type 20 -- Memory Device Mapped Address */
static void *
-smbios_type_20_init(void *start, uint32_t memory_size_mb)
+smbios_type_20_init(void *start, uint32_t 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;
- p->ending_address = (memory_size_mb * 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;
@@ -2176,6 +2186,7 @@ void smbios_init(void)
char *start, *p, *q;
int memsize = (ram_end == ram_size) ? ram_size / (1024 * 1024) :
(ram_end - (1ull << 32) + ram_size) / (1024 * 1024);
+ int i, nr_mem_devs;
#ifdef BX_USE_EBDA_TABLES
ebda_cur_addr = align(ebda_cur_addr, 16);
@@ -2187,23 +2198,32 @@ void smbios_init(void)
p = (char *)start + sizeof(struct smbios_entry_point);
-#define add_struct(fn) { \
+#define add_struct(fn) do{ \
q = (fn); \
nr_structs++; \
if ((q - p) > max_struct_size) \
max_struct_size = q - p; \
p = q; \
-}
+}while (0)
add_struct(smbios_type_0_init(p));
add_struct(smbios_type_1_init(p));
add_struct(smbios_type_3_init(p));
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, memsize));
- add_struct(smbios_type_17_init(p, memsize));
- add_struct(smbios_type_19_init(p, ram_end / (1024 * 1024)));
- add_struct(smbios_type_20_init(p, ram_end / (1024 * 1024)));
+
+ /* Each 'memory device' covers up to 16GB of address space. */
+ nr_mem_devs = (memsize + 0x3fff) >> 14;
+ add_struct(smbios_type_16_init(p, memsize, nr_mem_devs));
+ for ( i = 0; i < nr_mem_devs; i++ )
+ {
+ uint32_t dev_memsize = ((i == (nr_mem_devs - 1))
+ ? (memsize & 0x3fff) : 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));
- [Qemu-devel] [patch 0/9] Bochs BIOS MTRR support + SMBIOS updates, Marcelo Tosatti, 2009/01/19
- [Qemu-devel] [patch 1/9] kvm: bios: update SMBIOS table to report memory above 4G, Marcelo Tosatti, 2009/01/19
- [Qemu-devel] [patch 2/9] kvm: bios: generate mptable unconditionally, Marcelo Tosatti, 2009/01/19
- [Qemu-devel] [patch 3/9] kvm: bios: add mtrr support, Marcelo Tosatti, 2009/01/19
- [Qemu-devel] [patch 4/9] kvm: bios: smp mtrr support, Marcelo Tosatti, 2009/01/19
- [Qemu-devel] [patch 5/9] kvm: bios: extend MTRRs to above 4G, Marcelo Tosatti, 2009/01/19
- [Qemu-devel] [patch 6/9] kvm: bios: cleanup/consolidate above 4G memory parsing, Marcelo Tosatti, 2009/01/19
- [Qemu-devel] [patch 8/9] kvm: bios: resolve memory device roll over reporting issues with >32G guests,
Marcelo Tosatti <=
- [Qemu-devel] [patch 9/9] kvm: bios: fix smbios memory device length boundary condition, Marcelo Tosatti, 2009/01/19
- [Qemu-devel] [patch 7/9] kvm: bios: switch MTRRs to cover only the PCI range and default to WB, Marcelo Tosatti, 2009/01/19
- [Qemu-devel] Re: [patch 0/9] Bochs BIOS MTRR support + SMBIOS updates, Anthony Liguori, 2009/01/21