Skip to contentSkip to conversation

smbios support large memory guests

PATCH In review Bill Rieske 2 participants 3 messages Oct 9, 2008

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 smbios support large memory guests

This reports more than one memory device if the memory for the guest is larger than 16G.

tools/firmware/hvmloader/smbios.c +32 -19
diff -r e66cecb66b1e tools/firmware/hvmloader/smbios.c
@@ -56,11 +56,11 @@ static void *
 static void *
 smbios_type_16_init(void *start, uint32_t memory_size_mb);
 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);
 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);
 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);
 static void *
 smbios_type_32_init(void *start);
 static void *
@@ -89,9 +89,11 @@ write_smbios_tables(void *start,
                     uint8_t uuid[16], char *xen_version,
                     uint32_t xen_major_version, uint32_t xen_minor_version)
 {
+    uint64_t devmemsize;
     unsigned cpu_num, nr_structs = 0, max_struct_size = 0;
     char *p, *q;
     char cpu_manufacturer[15];
+    int i;
 
     get_cpu_manufacturer(cpu_manufacturer, 15);
 
@@ -112,9 +114,15 @@ write_smbios_tables(void *start,
     for ( cpu_num = 1; cpu_num <= vcpus; cpu_num++ )
         do_struct(smbios_type_4_init(p, cpu_num, cpu_manufacturer));
     do_struct(smbios_type_16_init(p, memsize));
-    do_struct(smbios_type_17_init(p, memsize));
-    do_struct(smbios_type_19_init(p, memsize));
-    do_struct(smbios_type_20_init(p, memsize));
+    for ( i=0; memsize; memsize -= devmemsize ) 
+    {
+        devmemsize = (memsize < 0x4000) ? memsize : 0x4000; 
+        /* more than 1 of each type needed if memsize */
+        /* represents greater than 16G */
+        do_struct(smbios_type_17_init(p, devmemsize,i));
+        do_struct(smbios_type_19_init(p, devmemsize,i));
+        do_struct(smbios_type_20_init(p, devmemsize,i++));
+    }
     do_struct(smbios_type_32_init(p));
     do_struct(smbios_type_127_init(p));
 
@@ -456,7 +464,8 @@ 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 = ( memsize <= 0x4000 )?1:
+       ( memsize % 0x4000 )? (memsize >> 14)+1:memsize >> 14;
 
     start += sizeof(struct smbios_type_16);
     *((uint16_t *)start) = 0;
@@ -465,15 +474,16 @@ 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)
 {
+    char buf[16];
     struct smbios_type_17 *p = (struct smbios_type_17 *)start;
     
     memset(p, 0, sizeof(*p));
 
     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;
@@ -489,8 +499,11 @@ smbios_type_17_init(void *start, uint32_
     p->type_detail = 0;
 
     start += sizeof(struct smbios_type_17);
-    strcpy((char *)start, "DIMM 1");
-    start += strlen("DIMM 1") + 1;
+    strcpy((char *)start, "DIMM ");
+    start += strlen("DIMM ");
+    itoa(buf, instance);
+    strcpy((char *)start, buf);
+    start += strlen(buf) +1;
     *((uint8_t *)start) = 0;
 
     return start+1;
@@ -498,7 +511,7 @@ 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;
     
@@ -506,10 +519,10 @@ smbios_type_19_init(void *start, uint32_
 
     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-1) * 1024;
+    p->starting_address = instance*0x4000;
+    p->ending_address = (( memory_size_mb+instance*0x4000 )-1)* 1024;
     p->memory_array_handle = 0x1000;
     p->partition_width = 1;
 
@@ -528,11 +541,11 @@ smbios_type_20_init(void *start, uint32_
 
     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-1)*1024;
-    p->memory_device_handle = 0x1100;
+    p->starting_address = instance*0x4000;
+    p->ending_address = (( memory_size_mb+instance*0x4000 ) -1)*1024;
+    p->memory_device_handle = 0x1100+instance;
     p->memory_array_mapped_address_handle = 0x1300;
     p->partition_row_position = 1;
     p->interleave_position = 0;

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel

#1 lore raw
Quoted 5 lines · Bill Rieske

This reports more than one memory device if the memory for the guest is larger than 16G.

It's not a great start that this patch cannot possibly compile.

-- Keir

#2 lore raw
Quoted 10 lines · Keir Fraser
Quoted 6 lines · Bill Rieske

This reports more than one memory device if the memory for the guest is larger
than 16G.

It's not a great start that this patch cannot possibly compile.

Also the starting_address computations are bogus, since the field is in kilobytes not megabytes. I will fix this patch up as necessary and apply it.

-- Keir