| 1 |
resolve memory device roll over reporting issues with >32G guests (Bill Rieske)
|
| 2 |
|
| 3 |
The field within the Memory Device type 17 is only a word with the MSB being
|
| 4 |
used to report MB/KB. Thereby, a guest with 32G and greater would report
|
| 5 |
incorrect memory device information rolling over to 0.
|
| 6 |
|
| 7 |
This presents more than one memory device and associated memory structures
|
| 8 |
if the memory is larger than 16G
|
| 9 |
|
| 10 |
Signed-off-by: Bill Rieske <brieske@novell.com>
|
| 11 |
Signed-off-by: Avi Kivity <avi@redhat.com>
|
| 12 |
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
|
| 13 |
|
| 14 |
Index: bochs/bios/rombios32.c
|
| 15 |
===================================================================
|
| 16 |
--- bochs.orig/bios/rombios32.c
|
| 17 |
+++ bochs/bios/rombios32.c
|
| 18 |
@@ -381,6 +381,17 @@ int vsnprintf(char *buf, int buflen, con
|
| 19 |
return buf - buf0;
|
| 20 |
}
|
| 21 |
|
| 22 |
+int snprintf(char * buf, size_t size, const char *fmt, ...)
|
| 23 |
+{
|
| 24 |
+ va_list args;
|
| 25 |
+ int i;
|
| 26 |
+
|
| 27 |
+ va_start(args, fmt);
|
| 28 |
+ i=vsnprintf(buf,size,fmt,args);
|
| 29 |
+ va_end(args);
|
| 30 |
+ return i;
|
| 31 |
+}
|
| 32 |
+
|
| 33 |
void bios_printf(int flags, const char *fmt, ...)
|
| 34 |
{
|
| 35 |
va_list ap;
|
| 36 |
@@ -2039,7 +2050,7 @@ smbios_type_4_init(void *start, unsigned
|
| 37 |
|
| 38 |
/* Type 16 -- Physical Memory Array */
|
| 39 |
static void *
|
| 40 |
-smbios_type_16_init(void *start, uint32_t memsize)
|
| 41 |
+smbios_type_16_init(void *start, uint32_t memsize, int nr_mem_devs)
|
| 42 |
{
|
| 43 |
struct smbios_type_16 *p = (struct smbios_type_16*)start;
|
| 44 |
|
| 45 |
@@ -2052,7 +2063,7 @@ smbios_type_16_init(void *start, uint32_
|
| 46 |
p->error_correction = 0x01; /* other */
|
| 47 |
p->maximum_capacity = memsize * 1024;
|
| 48 |
p->memory_error_information_handle = 0xfffe; /* none provided */
|
| 49 |
- p->number_of_memory_devices = 1;
|
| 50 |
+ p->number_of_memory_devices = nr_mem_devs;
|
| 51 |
|
| 52 |
start += sizeof(struct smbios_type_16);
|
| 53 |
*((uint16_t *)start) = 0;
|
| 54 |
@@ -2062,20 +2073,19 @@ smbios_type_16_init(void *start, uint32_
|
| 55 |
|
| 56 |
/* Type 17 -- Memory Device */
|
| 57 |
static void *
|
| 58 |
-smbios_type_17_init(void *start, uint32_t memory_size_mb)
|
| 59 |
+smbios_type_17_init(void *start, uint32_t memory_size_mb, int instance)
|
| 60 |
{
|
| 61 |
struct smbios_type_17 *p = (struct smbios_type_17 *)start;
|
| 62 |
|
| 63 |
p->header.type = 17;
|
| 64 |
p->header.length = sizeof(struct smbios_type_17);
|
| 65 |
- p->header.handle = 0x1100;
|
| 66 |
+ p->header.handle = 0x1100 + instance;
|
| 67 |
|
| 68 |
p->physical_memory_array_handle = 0x1000;
|
| 69 |
p->total_width = 64;
|
| 70 |
p->data_width = 64;
|
| 71 |
- /* truncate memory_size_mb to 16 bits and clear most significant
|
| 72 |
- bit [indicates size in MB] */
|
| 73 |
- p->size = (uint16_t) memory_size_mb & 0x7fff;
|
| 74 |
+/* TODO: should assert in case something is wrong ASSERT((memory_size_mb & ~0x7fff) == 0); */
|
| 75 |
+ p->size = memory_size_mb;
|
| 76 |
p->form_factor = 0x09; /* DIMM */
|
| 77 |
p->device_set = 0;
|
| 78 |
p->device_locator_str = 1;
|
| 79 |
@@ -2084,8 +2094,8 @@ smbios_type_17_init(void *start, uint32_
|
| 80 |
p->type_detail = 0;
|
| 81 |
|
| 82 |
start += sizeof(struct smbios_type_17);
|
| 83 |
- memcpy((char *)start, "DIMM 1", 7);
|
| 84 |
- start += 7;
|
| 85 |
+ snprintf(start, 8, "DIMM %d", instance);
|
| 86 |
+ start += strlen(start) + 1;
|
| 87 |
*((uint8_t *)start) = 0;
|
| 88 |
|
| 89 |
return start+1;
|
| 90 |
@@ -2093,16 +2103,16 @@ smbios_type_17_init(void *start, uint32_
|
| 91 |
|
| 92 |
/* Type 19 -- Memory Array Mapped Address */
|
| 93 |
static void *
|
| 94 |
-smbios_type_19_init(void *start, uint32_t memory_size_mb)
|
| 95 |
+smbios_type_19_init(void *start, uint32_t memory_size_mb, int instance)
|
| 96 |
{
|
| 97 |
struct smbios_type_19 *p = (struct smbios_type_19 *)start;
|
| 98 |
|
| 99 |
p->header.type = 19;
|
| 100 |
p->header.length = sizeof(struct smbios_type_19);
|
| 101 |
- p->header.handle = 0x1300;
|
| 102 |
+ p->header.handle = 0x1300 + instance;
|
| 103 |
|
| 104 |
- p->starting_address = 0;
|
| 105 |
- p->ending_address = (memory_size_mb * 1024) - 1;
|
| 106 |
+ p->starting_address = instance << 24;
|
| 107 |
+ p->ending_address = p->starting_address + (memory_size_mb << 10) - 1;
|
| 108 |
p->memory_array_handle = 0x1000;
|
| 109 |
p->partition_width = 1;
|
| 110 |
|
| 111 |
@@ -2114,18 +2124,18 @@ smbios_type_19_init(void *start, uint32_
|
| 112 |
|
| 113 |
/* Type 20 -- Memory Device Mapped Address */
|
| 114 |
static void *
|
| 115 |
-smbios_type_20_init(void *start, uint32_t memory_size_mb)
|
| 116 |
+smbios_type_20_init(void *start, uint32_t memory_size_mb, int instance)
|
| 117 |
{
|
| 118 |
struct smbios_type_20 *p = (struct smbios_type_20 *)start;
|
| 119 |
|
| 120 |
p->header.type = 20;
|
| 121 |
p->header.length = sizeof(struct smbios_type_20);
|
| 122 |
- p->header.handle = 0x1400;
|
| 123 |
+ p->header.handle = 0x1400 + instance;
|
| 124 |
|
| 125 |
- p->starting_address = 0;
|
| 126 |
- p->ending_address = (memory_size_mb * 1024) - 1;
|
| 127 |
- p->memory_device_handle = 0x1100;
|
| 128 |
- p->memory_array_mapped_address_handle = 0x1300;
|
| 129 |
+ p->starting_address = instance << 24;
|
| 130 |
+ p->ending_address = p->starting_address + (memory_size_mb << 10) - 1;
|
| 131 |
+ p->memory_device_handle = 0x1100 + instance;
|
| 132 |
+ p->memory_array_mapped_address_handle = 0x1300 + instance;
|
| 133 |
p->partition_row_position = 1;
|
| 134 |
p->interleave_position = 0;
|
| 135 |
p->interleaved_data_depth = 0;
|
| 136 |
@@ -2176,6 +2186,7 @@ void smbios_init(void)
|
| 137 |
char *start, *p, *q;
|
| 138 |
int memsize = (ram_end == ram_size) ? ram_size / (1024 * 1024) :
|
| 139 |
(ram_end - (1ull << 32) + ram_size) / (1024 * 1024);
|
| 140 |
+ int i, nr_mem_devs;
|
| 141 |
|
| 142 |
#ifdef BX_USE_EBDA_TABLES
|
| 143 |
ebda_cur_addr = align(ebda_cur_addr, 16);
|
| 144 |
@@ -2187,23 +2198,32 @@ void smbios_init(void)
|
| 145 |
|
| 146 |
p = (char *)start + sizeof(struct smbios_entry_point);
|
| 147 |
|
| 148 |
-#define add_struct(fn) { \
|
| 149 |
+#define add_struct(fn) do{ \
|
| 150 |
q = (fn); \
|
| 151 |
nr_structs++; \
|
| 152 |
if ((q - p) > max_struct_size) \
|
| 153 |
max_struct_size = q - p; \
|
| 154 |
p = q; \
|
| 155 |
-}
|
| 156 |
+}while (0)
|
| 157 |
|
| 158 |
add_struct(smbios_type_0_init(p));
|
| 159 |
add_struct(smbios_type_1_init(p));
|
| 160 |
add_struct(smbios_type_3_init(p));
|
| 161 |
for (cpu_num = 1; cpu_num <= smp_cpus; cpu_num++)
|
| 162 |
add_struct(smbios_type_4_init(p, cpu_num));
|
| 163 |
- add_struct(smbios_type_16_init(p, memsize));
|
| 164 |
- add_struct(smbios_type_17_init(p, memsize));
|
| 165 |
- add_struct(smbios_type_19_init(p, ram_end / (1024 * 1024)));
|
| 166 |
- add_struct(smbios_type_20_init(p, ram_end / (1024 * 1024)));
|
| 167 |
+
|
| 168 |
+ /* Each 'memory device' covers up to 16GB of address space. */
|
| 169 |
+ nr_mem_devs = (memsize + 0x3fff) >> 14;
|
| 170 |
+ add_struct(smbios_type_16_init(p, memsize, nr_mem_devs));
|
| 171 |
+ for ( i = 0; i < nr_mem_devs; i++ )
|
| 172 |
+ {
|
| 173 |
+ uint32_t dev_memsize = ((i == (nr_mem_devs - 1))
|
| 174 |
+ ? (memsize & 0x3fff) : 0x4000);
|
| 175 |
+ add_struct(smbios_type_17_init(p, dev_memsize, i));
|
| 176 |
+ add_struct(smbios_type_19_init(p, dev_memsize, i));
|
| 177 |
+ add_struct(smbios_type_20_init(p, dev_memsize, i));
|
| 178 |
+ }
|
| 179 |
+
|
| 180 |
add_struct(smbios_type_32_init(p));
|
| 181 |
add_struct(smbios_type_127_init(p));
|
| 182 |
|
| 183 |
|
| 184 |
|