Statistics
| Branch: | Revision:

root / pc-bios / bios-pq / 0009_kvm-bios-resolve-memory-device-roll-over-reporting--issues-with-32g-guests.patch @ 9a717b55

History | View | Annotate | Download (6.3 kB)

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