ia64/xen-unstable

changeset 18604:6ab55f716ce3

hvmloader: smbios support for large memory guests

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

Signed-off-by: Bill Rieske <brieske@novell.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Oct 09 17:18:11 2008 +0100 (2008-10-09)
parents 69f670979660
children c2fc4d26ef18 8f5a67f466e2
files tools/firmware/hvmloader/smbios.c
line diff
     1.1 --- a/tools/firmware/hvmloader/smbios.c	Thu Oct 09 12:47:31 2008 +0100
     1.2 +++ b/tools/firmware/hvmloader/smbios.c	Thu Oct 09 17:18:11 2008 +0100
     1.3 @@ -54,13 +54,13 @@ static void *
     1.4  smbios_type_4_init(void *start, unsigned int cpu_number,
     1.5                     char *cpu_manufacturer);
     1.6  static void *
     1.7 -smbios_type_16_init(void *start, uint32_t memory_size_mb);
     1.8 +smbios_type_16_init(void *start, uint32_t memory_size_mb, int nr_mem_devs);
     1.9  static void *
    1.10 -smbios_type_17_init(void *start, uint32_t memory_size_mb);
    1.11 +smbios_type_17_init(void *start, uint32_t memory_size_mb, int instance);
    1.12  static void *
    1.13 -smbios_type_19_init(void *start, uint32_t memory_size_mb);
    1.14 +smbios_type_19_init(void *start, uint32_t memory_size_mb, int instance);
    1.15  static void *
    1.16 -smbios_type_20_init(void *start, uint32_t memory_size_mb);
    1.17 +smbios_type_20_init(void *start, uint32_t memory_size_mb, int instance);
    1.18  static void *
    1.19  smbios_type_32_init(void *start);
    1.20  static void *
    1.21 @@ -92,6 +92,7 @@ write_smbios_tables(void *start,
    1.22      unsigned cpu_num, nr_structs = 0, max_struct_size = 0;
    1.23      char *p, *q;
    1.24      char cpu_manufacturer[15];
    1.25 +    int i, nr_mem_devs;
    1.26  
    1.27      get_cpu_manufacturer(cpu_manufacturer, 15);
    1.28  
    1.29 @@ -111,10 +112,19 @@ write_smbios_tables(void *start,
    1.30      do_struct(smbios_type_3_init(p));
    1.31      for ( cpu_num = 1; cpu_num <= vcpus; cpu_num++ )
    1.32          do_struct(smbios_type_4_init(p, cpu_num, cpu_manufacturer));
    1.33 -    do_struct(smbios_type_16_init(p, memsize));
    1.34 -    do_struct(smbios_type_17_init(p, memsize));
    1.35 -    do_struct(smbios_type_19_init(p, memsize));
    1.36 -    do_struct(smbios_type_20_init(p, memsize));
    1.37 +
    1.38 +    /* Each 'memory device' covers up to 16GB of address space. */
    1.39 +    nr_mem_devs = (memsize + 0x3fff) >> 14;
    1.40 +    do_struct(smbios_type_16_init(p, memsize, nr_mem_devs));
    1.41 +    for ( i = 0; i < nr_mem_devs; i++ )
    1.42 +    {
    1.43 +        uint32_t dev_memsize = ((i == (nr_mem_devs - 1))
    1.44 +                                ? (memsize & 0x3fff) : 0x4000);
    1.45 +        do_struct(smbios_type_17_init(p, dev_memsize, i));
    1.46 +        do_struct(smbios_type_19_init(p, dev_memsize, i));
    1.47 +        do_struct(smbios_type_20_init(p, dev_memsize, i));
    1.48 +    }
    1.49 +
    1.50      do_struct(smbios_type_32_init(p));
    1.51      do_struct(smbios_type_127_init(p));
    1.52  
    1.53 @@ -441,7 +451,7 @@ smbios_type_4_init(
    1.54  
    1.55  /* Type 16 -- Physical Memory Array */
    1.56  static void *
    1.57 -smbios_type_16_init(void *start, uint32_t memsize)
    1.58 +smbios_type_16_init(void *start, uint32_t memsize, int nr_mem_devs)
    1.59  {
    1.60      struct smbios_type_16 *p = (struct smbios_type_16*)start;
    1.61  
    1.62 @@ -456,7 +466,7 @@ smbios_type_16_init(void *start, uint32_
    1.63      p->error_correction = 0x01; /* other */
    1.64      p->maximum_capacity = memsize * 1024;
    1.65      p->memory_error_information_handle = 0xfffe; /* none provided */
    1.66 -    p->number_of_memory_devices = 1;
    1.67 +    p->number_of_memory_devices = nr_mem_devs;
    1.68  
    1.69      start += sizeof(struct smbios_type_16);
    1.70      *((uint16_t *)start) = 0;
    1.71 @@ -465,22 +475,22 @@ smbios_type_16_init(void *start, uint32_
    1.72  
    1.73  /* Type 17 -- Memory Device */
    1.74  static void *
    1.75 -smbios_type_17_init(void *start, uint32_t memory_size_mb)
    1.76 +smbios_type_17_init(void *start, uint32_t memory_size_mb, int instance)
    1.77  {
    1.78 +    char buf[16];
    1.79      struct smbios_type_17 *p = (struct smbios_type_17 *)start;
    1.80      
    1.81      memset(p, 0, sizeof(*p));
    1.82  
    1.83      p->header.type = 17;
    1.84      p->header.length = sizeof(struct smbios_type_17);
    1.85 -    p->header.handle = 0x1100;
    1.86 +    p->header.handle = 0x1100 + instance;
    1.87  
    1.88      p->physical_memory_array_handle = 0x1000;
    1.89      p->total_width = 64;
    1.90      p->data_width = 64;
    1.91 -    /* truncate memory_size_mb to 16 bits and clear most significant
    1.92 -       bit [indicates size in MB] */
    1.93 -    p->size = (uint16_t) memory_size_mb & 0x7fff;
    1.94 +    ASSERT((memory_size_mb & ~0x7fff) == 0);
    1.95 +    p->size = memory_size_mb;
    1.96      p->form_factor = 0x09; /* DIMM */
    1.97      p->device_set = 0;
    1.98      p->device_locator_str = 1;
    1.99 @@ -489,8 +499,11 @@ smbios_type_17_init(void *start, uint32_
   1.100      p->type_detail = 0;
   1.101  
   1.102      start += sizeof(struct smbios_type_17);
   1.103 -    strcpy((char *)start, "DIMM 1");
   1.104 -    start += strlen("DIMM 1") + 1;
   1.105 +    strcpy(start, "DIMM ");
   1.106 +    start += strlen("DIMM ");
   1.107 +    itoa(buf, instance);
   1.108 +    strcpy(start, buf);
   1.109 +    start += strlen(buf) + 1;
   1.110      *((uint8_t *)start) = 0;
   1.111  
   1.112      return start+1;
   1.113 @@ -498,7 +511,7 @@ smbios_type_17_init(void *start, uint32_
   1.114  
   1.115  /* Type 19 -- Memory Array Mapped Address */
   1.116  static void *
   1.117 -smbios_type_19_init(void *start, uint32_t memory_size_mb)
   1.118 +smbios_type_19_init(void *start, uint32_t memory_size_mb, int instance)
   1.119  {
   1.120      struct smbios_type_19 *p = (struct smbios_type_19 *)start;
   1.121      
   1.122 @@ -506,10 +519,10 @@ smbios_type_19_init(void *start, uint32_
   1.123  
   1.124      p->header.type = 19;
   1.125      p->header.length = sizeof(struct smbios_type_19);
   1.126 -    p->header.handle = 0x1300;
   1.127 +    p->header.handle = 0x1300 + instance;
   1.128  
   1.129 -    p->starting_address = 0;
   1.130 -    p->ending_address = (memory_size_mb-1) * 1024;
   1.131 +    p->starting_address = instance << 24;
   1.132 +    p->ending_address = p->starting_address + (memory_size_mb << 10) - 1;
   1.133      p->memory_array_handle = 0x1000;
   1.134      p->partition_width = 1;
   1.135  
   1.136 @@ -520,7 +533,7 @@ smbios_type_19_init(void *start, uint32_
   1.137  
   1.138  /* Type 20 -- Memory Device Mapped Address */
   1.139  static void *
   1.140 -smbios_type_20_init(void *start, uint32_t memory_size_mb)
   1.141 +smbios_type_20_init(void *start, uint32_t memory_size_mb, int instance)
   1.142  {
   1.143      struct smbios_type_20 *p = (struct smbios_type_20 *)start;
   1.144  
   1.145 @@ -528,12 +541,12 @@ smbios_type_20_init(void *start, uint32_
   1.146  
   1.147      p->header.type = 20;
   1.148      p->header.length = sizeof(struct smbios_type_20);
   1.149 -    p->header.handle = 0x1400;
   1.150 +    p->header.handle = 0x1400 + instance;
   1.151  
   1.152 -    p->starting_address = 0;
   1.153 -    p->ending_address = (memory_size_mb-1)*1024;
   1.154 -    p->memory_device_handle = 0x1100;
   1.155 -    p->memory_array_mapped_address_handle = 0x1300;
   1.156 +    p->starting_address = instance << 24;
   1.157 +    p->ending_address = p->starting_address + (memory_size_mb << 10) - 1;
   1.158 +    p->memory_device_handle = 0x1100 + instance;
   1.159 +    p->memory_array_mapped_address_handle = 0x1300 + instance;
   1.160      p->partition_row_position = 1;
   1.161      p->interleave_position = 0;
   1.162      p->interleaved_data_depth = 0;