ia64/xen-unstable

changeset 17363:69c951243105

hvmloader: Properly implement some more SMBIOS fields.

In particular:
- BIOS release date
- BIOS characteristics
- BIOS extended characteristics (Targeted Content Distribution is
required to be specified to pass WHQL).
- CPU speed

Based on a patch by Kamala Narasimhan <kamala.narasimhan@citrix.com>

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Apr 01 17:21:05 2008 +0100 (2008-04-01)
parents db943e8d1051
children baff5b3aaf13
files tools/firmware/hvmloader/Makefile tools/firmware/hvmloader/hvmloader.c tools/firmware/hvmloader/smbios.c tools/firmware/hvmloader/util.c tools/firmware/hvmloader/util.h
line diff
     1.1 --- a/tools/firmware/hvmloader/Makefile	Tue Apr 01 10:09:33 2008 +0100
     1.2 +++ b/tools/firmware/hvmloader/Makefile	Tue Apr 01 17:21:05 2008 +0100
     1.3 @@ -42,16 +42,21 @@ OBJS = $(patsubst %.c,%.o,$(SRCS))
     1.4  .PHONY: all
     1.5  all: hvmloader
     1.6  
     1.7 -hvmloader: roms.h subdirs-all $(SRCS)
     1.8 -	$(CC) $(CFLAGS) -c $(SRCS)
     1.9 -	$(LD) $(LDFLAGS_DIRECT) -N -Ttext $(LOADADDR) -o hvmloader.tmp $(OBJS) acpi/acpi.a
    1.10 +smbios.o: CFLAGS += -D__SMBIOS_DATE__="\"$(shell date +%m/%d/%Y)\""
    1.11 +
    1.12 +hvmloader: roms.h subdirs-all $(OBJS)
    1.13 +	$(LD) $(LDFLAGS_DIRECT) -N -Ttext $(LOADADDR) \
    1.14 +		-o hvmloader.tmp $(OBJS) acpi/acpi.a
    1.15  	$(OBJCOPY) hvmloader.tmp hvmloader
    1.16  	rm -f hvmloader.tmp
    1.17  
    1.18 -roms.h: ../rombios/BIOS-bochs-latest ../vgabios/VGABIOS-lgpl-latest.bin ../vgabios/VGABIOS-lgpl-latest.cirrus.bin ../etherboot/eb-roms.h ../extboot/extboot.bin
    1.19 +roms.h: ../rombios/BIOS-bochs-latest ../vgabios/VGABIOS-lgpl-latest.bin \
    1.20 +	../vgabios/VGABIOS-lgpl-latest.cirrus.bin ../etherboot/eb-roms.h \
    1.21 +	../extboot/extboot.bin
    1.22  	sh ./mkhex rombios ../rombios/BIOS-bochs-latest > roms.h
    1.23  	sh ./mkhex vgabios_stdvga ../vgabios/VGABIOS-lgpl-latest.bin >> roms.h
    1.24 -	sh ./mkhex vgabios_cirrusvga ../vgabios/VGABIOS-lgpl-latest.cirrus.bin >> roms.h
    1.25 +	sh ./mkhex vgabios_cirrusvga \
    1.26 +		../vgabios/VGABIOS-lgpl-latest.cirrus.bin >> roms.h
    1.27  	cat ../etherboot/eb-roms.h >> roms.h
    1.28  	sh ./mkhex extboot ../extboot/extboot.bin >> roms.h
    1.29  
     2.1 --- a/tools/firmware/hvmloader/hvmloader.c	Tue Apr 01 10:09:33 2008 +0100
     2.2 +++ b/tools/firmware/hvmloader/hvmloader.c	Tue Apr 01 17:21:05 2008 +0100
     2.3 @@ -420,6 +420,8 @@ int main(void)
     2.4  
     2.5      init_hypercalls();
     2.6  
     2.7 +    printf("CPU speed is %u MHz\n", get_cpu_mhz());
     2.8 +
     2.9      printf("Writing SMBIOS tables ...\n");
    2.10      smbios_sz = hvm_write_smbios_tables();
    2.11  
     3.1 --- a/tools/firmware/hvmloader/smbios.c	Tue Apr 01 10:09:33 2008 +0100
     3.2 +++ b/tools/firmware/hvmloader/smbios.c	Tue Apr 01 17:21:05 2008 +0100
     3.3 @@ -21,6 +21,7 @@
     3.4   */
     3.5  
     3.6  #include <stdint.h>
     3.7 +#include <xen/xen.h>
     3.8  #include <xen/version.h>
     3.9  #include "smbios_types.h"
    3.10  #include "util.h"
    3.11 @@ -246,13 +247,14 @@ smbios_entry_point_init(void *start,
    3.12      int i;
    3.13      struct smbios_entry_point *ep = (struct smbios_entry_point *)start;
    3.14  
    3.15 +    memset(ep, 0, sizeof(*ep));
    3.16 +
    3.17      strncpy(ep->anchor_string, "_SM_", 4);
    3.18      ep->length = 0x1f;
    3.19      ep->smbios_major_version = 2;
    3.20      ep->smbios_minor_version = 4;
    3.21      ep->max_structure_size = max_structure_size;
    3.22      ep->entry_point_revision = 0;
    3.23 -    memset(ep->formatted_area, 0, 5);
    3.24      strncpy(ep->intermediate_anchor_string, "_DMI_", 5);
    3.25      
    3.26      ep->structure_table_length = structure_table_length;
    3.27 @@ -260,9 +262,6 @@ smbios_entry_point_init(void *start,
    3.28      ep->number_of_structures = number_of_structures;
    3.29      ep->smbios_bcd_revision = 0x24;
    3.30  
    3.31 -    ep->checksum = 0;
    3.32 -    ep->intermediate_checksum = 0;
    3.33 -    
    3.34      sum = 0;
    3.35      for ( i = 0; i < 0x10; i++ )
    3.36          sum += ((int8_t *)start)[i];
    3.37 @@ -280,22 +279,27 @@ smbios_type_0_init(void *start, const ch
    3.38                     uint32_t xen_major_version, uint32_t xen_minor_version)
    3.39  {
    3.40      struct smbios_type_0 *p = (struct smbios_type_0 *)start;
    3.41 -    
    3.42 +    static const char *smbios_release_date = __SMBIOS_DATE__;
    3.43 +
    3.44 +    memset(p, 0, sizeof(*p));
    3.45 +
    3.46      p->header.type = 0;
    3.47      p->header.length = sizeof(struct smbios_type_0);
    3.48      p->header.handle = 0;
    3.49 -    
    3.50 +
    3.51      p->vendor_str = 1;
    3.52      p->version_str = 2;
    3.53      p->starting_address_segment = 0xe800;
    3.54 -    p->release_date_str = 0;
    3.55 +    p->release_date_str = 3;
    3.56      p->rom_size = 0;
    3.57 -    
    3.58 -    memset(p->characteristics, 0, 8);
    3.59 -    p->characteristics[7] = 0x08; /* BIOS characteristics not supported */
    3.60 -    p->characteristics_extension_bytes[0] = 0;
    3.61 -    p->characteristics_extension_bytes[1] = 0;
    3.62 -    
    3.63 +
    3.64 +    /* BIOS Characteristics. */
    3.65 +    p->characteristics[0] = 0x80; /* PCI is supported */
    3.66 +    p->characteristics[2] = 0x08; /* EDD is supported */
    3.67 +
    3.68 +    /* Extended Characteristics: Enable Targeted Content Distribution. */
    3.69 +    p->characteristics_extension_bytes[1] = 0x04;
    3.70 +
    3.71      p->major_release = (uint8_t) xen_major_version;
    3.72      p->minor_release = (uint8_t) xen_minor_version;
    3.73      p->embedded_controller_major = 0xff;
    3.74 @@ -306,6 +310,8 @@ smbios_type_0_init(void *start, const ch
    3.75      start += strlen("Xen") + 1;
    3.76      strcpy((char *)start, xen_version);
    3.77      start += strlen(xen_version) + 1;
    3.78 +    strcpy((char *)start, smbios_release_date);
    3.79 +    start += strlen(smbios_release_date) + 1;
    3.80  
    3.81      *((uint8_t *)start) = 0;
    3.82      return start + 1;
    3.83 @@ -318,6 +324,9 @@ smbios_type_1_init(void *start, const ch
    3.84  {
    3.85      char uuid_str[37];
    3.86      struct smbios_type_1 *p = (struct smbios_type_1 *)start;
    3.87 +
    3.88 +    memset(p, 0, sizeof(*p));
    3.89 +
    3.90      p->header.type = 1;
    3.91      p->header.length = sizeof(struct smbios_type_1);
    3.92      p->header.handle = 0x100;
    3.93 @@ -355,6 +364,8 @@ smbios_type_3_init(void *start)
    3.94  {
    3.95      struct smbios_type_3 *p = (struct smbios_type_3 *)start;
    3.96      
    3.97 +    memset(p, 0, sizeof(*p));
    3.98 +
    3.99      p->header.type = 3;
   3.100      p->header.length = sizeof(struct smbios_type_3);
   3.101      p->header.handle = 0x300;
   3.102 @@ -379,12 +390,15 @@ smbios_type_3_init(void *start)
   3.103  
   3.104  /* Type 4 -- Processor Information */
   3.105  static void *
   3.106 -smbios_type_4_init(void *start, unsigned int cpu_number, char *cpu_manufacturer)
   3.107 +smbios_type_4_init(
   3.108 +    void *start, unsigned int cpu_number, char *cpu_manufacturer)
   3.109  {
   3.110      char buf[80]; 
   3.111      struct smbios_type_4 *p = (struct smbios_type_4 *)start;
   3.112      uint32_t eax, ebx, ecx, edx;
   3.113  
   3.114 +    memset(p, 0, sizeof(*p));
   3.115 +
   3.116      p->header.type = 4;
   3.117      p->header.length = sizeof(struct smbios_type_4);
   3.118      p->header.handle = 0x400 + cpu_number;
   3.119 @@ -403,8 +417,7 @@ smbios_type_4_init(void *start, unsigned
   3.120      p->voltage = 0;
   3.121      p->external_clock = 0;
   3.122  
   3.123 -    p->max_speed = 0; /* unknown */
   3.124 -    p->current_speed = 0; /* unknown */
   3.125 +    p->max_speed = p->current_speed = get_cpu_mhz();
   3.126  
   3.127      p->status = 0x41; /* socket populated, CPU enabled */
   3.128      p->upgrade = 0x01; /* other */
   3.129 @@ -431,6 +444,8 @@ smbios_type_16_init(void *start, uint32_
   3.130  {
   3.131      struct smbios_type_16 *p = (struct smbios_type_16*)start;
   3.132  
   3.133 +    memset(p, 0, sizeof(*p));
   3.134 +
   3.135      p->header.type = 16;
   3.136      p->header.handle = 0x1000;
   3.137      p->header.length = sizeof(struct smbios_type_16);
   3.138 @@ -453,6 +468,8 @@ smbios_type_17_init(void *start, uint32_
   3.139  {
   3.140      struct smbios_type_17 *p = (struct smbios_type_17 *)start;
   3.141      
   3.142 +    memset(p, 0, sizeof(*p));
   3.143 +
   3.144      p->header.type = 17;
   3.145      p->header.length = sizeof(struct smbios_type_17);
   3.146      p->header.handle = 0x1100;
   3.147 @@ -484,6 +501,8 @@ smbios_type_19_init(void *start, uint32_
   3.148  {
   3.149      struct smbios_type_19 *p = (struct smbios_type_19 *)start;
   3.150      
   3.151 +    memset(p, 0, sizeof(*p));
   3.152 +
   3.153      p->header.type = 19;
   3.154      p->header.length = sizeof(struct smbios_type_19);
   3.155      p->header.handle = 0x1300;
   3.156 @@ -504,6 +523,8 @@ smbios_type_20_init(void *start, uint32_
   3.157  {
   3.158      struct smbios_type_20 *p = (struct smbios_type_20 *)start;
   3.159  
   3.160 +    memset(p, 0, sizeof(*p));
   3.161 +
   3.162      p->header.type = 20;
   3.163      p->header.length = sizeof(struct smbios_type_20);
   3.164      p->header.handle = 0x1400;
   3.165 @@ -528,6 +549,8 @@ smbios_type_32_init(void *start)
   3.166  {
   3.167      struct smbios_type_32 *p = (struct smbios_type_32 *)start;
   3.168  
   3.169 +    memset(p, 0, sizeof(*p));
   3.170 +
   3.171      p->header.type = 32;
   3.172      p->header.length = sizeof(struct smbios_type_32);
   3.173      p->header.handle = 0x2000;
   3.174 @@ -545,6 +568,8 @@ smbios_type_127_init(void *start)
   3.175  {
   3.176      struct smbios_type_127 *p = (struct smbios_type_127 *)start;
   3.177  
   3.178 +    memset(p, 0, sizeof(*p));
   3.179 +
   3.180      p->header.type = 127;
   3.181      p->header.length = sizeof(struct smbios_type_127);
   3.182      p->header.handle = 0x7f00;
     4.1 --- a/tools/firmware/hvmloader/util.c	Tue Apr 01 10:09:33 2008 +0100
     4.2 +++ b/tools/firmware/hvmloader/util.c	Tue Apr 01 17:21:05 2008 +0100
     4.3 @@ -21,7 +21,10 @@
     4.4  #include "util.h"
     4.5  #include "config.h"
     4.6  #include "e820.h"
     4.7 +#include "hypercall.h"
     4.8  #include <stdint.h>
     4.9 +#include <xen/xen.h>
    4.10 +#include <xen/memory.h>
    4.11  #include <xen/hvm/hvm_info_table.h>
    4.12  
    4.13  void outb(uint16_t addr, uint8_t val)
    4.14 @@ -585,6 +588,56 @@ int get_apic_mode(void)
    4.15      return (t ? t->apic_mode : 1);
    4.16  }
    4.17  
    4.18 +uint16_t get_cpu_mhz(void)
    4.19 +{
    4.20 +    struct xen_add_to_physmap xatp;
    4.21 +    struct shared_info *shared_info = (struct shared_info *)0xa0000;
    4.22 +    struct vcpu_time_info *info = &shared_info->vcpu_info[0].time;
    4.23 +    uint64_t cpu_khz;
    4.24 +    uint32_t tsc_to_nsec_mul, version;
    4.25 +    int8_t tsc_shift;
    4.26 +
    4.27 +    static uint16_t cpu_mhz;
    4.28 +    if ( cpu_mhz != 0 )
    4.29 +        return cpu_mhz;
    4.30 +
    4.31 +    /* Map shared-info page to 0xa0000 (i.e., overlap VGA hole). */
    4.32 +    xatp.domid = DOMID_SELF;
    4.33 +    xatp.space = XENMAPSPACE_shared_info;
    4.34 +    xatp.idx   = 0;
    4.35 +    xatp.gpfn  = (unsigned long)shared_info >> 12;
    4.36 +    if ( hypercall_memory_op(XENMEM_add_to_physmap, &xatp) != 0 )
    4.37 +        BUG();
    4.38 +
    4.39 +    /* Get a consistent snapshot of scale factor (multiplier and shift). */
    4.40 +    do {
    4.41 +        version = info->version;
    4.42 +        rmb();
    4.43 +        tsc_to_nsec_mul = info->tsc_to_system_mul;
    4.44 +        tsc_shift       = info->tsc_shift;
    4.45 +        rmb();
    4.46 +    } while ((version & 1) | (version ^ info->version));
    4.47 +
    4.48 +    /* Compute CPU speed in kHz. */
    4.49 +    cpu_khz = 1000000ull << 32;
    4.50 +    do_div(cpu_khz, tsc_to_nsec_mul);
    4.51 +    if ( tsc_shift < 0 )
    4.52 +        cpu_khz = cpu_khz << -tsc_shift;
    4.53 +    else
    4.54 +        cpu_khz = cpu_khz >> tsc_shift;
    4.55 +
    4.56 +    /* Get the VGA MMIO hole back by remapping shared info to scratch. */
    4.57 +    xatp.domid = DOMID_SELF;
    4.58 +    xatp.space = XENMAPSPACE_shared_info;
    4.59 +    xatp.idx   = 0;
    4.60 +    xatp.gpfn  = 0xfffff; /* scratch pfn */
    4.61 +    if ( hypercall_memory_op(XENMEM_add_to_physmap, &xatp) != 0 )
    4.62 +        BUG();
    4.63 +
    4.64 +    cpu_mhz = (uint16_t)(((uint32_t)cpu_khz + 500) / 1000);
    4.65 +    return cpu_mhz;
    4.66 +}
    4.67 +
    4.68  /*
    4.69   * Local variables:
    4.70   * mode: C
     5.1 --- a/tools/firmware/hvmloader/util.h	Tue Apr 01 10:09:33 2008 +0100
     5.2 +++ b/tools/firmware/hvmloader/util.h	Tue Apr 01 17:21:05 2008 +0100
     5.3 @@ -10,11 +10,11 @@
     5.4  #undef NULL
     5.5  #define NULL ((void*)0)
     5.6  
     5.7 -extern void __assert_failed(char *assertion, char *file, int line)
     5.8 +void __assert_failed(char *assertion, char *file, int line)
     5.9      __attribute__((noreturn));
    5.10  #define ASSERT(p) \
    5.11      do { if (!(p)) __assert_failed(#p, __FILE__, __LINE__); } while (0)
    5.12 -extern void __bug(char *file, int line) __attribute__((noreturn));
    5.13 +void __bug(char *file, int line) __attribute__((noreturn));
    5.14  #define BUG() __bug(__FILE__, __LINE__)
    5.15  #define BUG_ON(p) do { if (p) BUG(); } while (0)
    5.16  #define BUILD_BUG_ON(p) ((void)sizeof(char[1 - 2 * !!(p)]))
    5.17 @@ -49,10 +49,54 @@ void pci_write(uint32_t devfn, uint32_t 
    5.18  #define pci_writew(devfn, reg, val) (pci_write(devfn, reg, 2, (uint16_t)val))
    5.19  #define pci_writel(devfn, reg, val) (pci_write(devfn, reg, 4, (uint32_t)val))
    5.20  
    5.21 +/* Get CPU speed in MHz. */
    5.22 +uint16_t get_cpu_mhz(void);
    5.23 +
    5.24  /* Do cpuid instruction, with operation 'idx' */
    5.25  void cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx,
    5.26             uint32_t *ecx, uint32_t *edx);
    5.27  
    5.28 +/* Read the TSC register. */
    5.29 +static inline uint64_t rdtsc(void)
    5.30 +{
    5.31 +    uint64_t tsc;
    5.32 +    asm volatile ( "rdtsc" : "=A" (tsc) );
    5.33 +    return tsc;
    5.34 +}
    5.35 +
    5.36 +/* Relax the CPU and let the compiler know that time passes. */
    5.37 +static inline void cpu_relax(void)
    5.38 +{
    5.39 +    asm volatile ( "rep ; nop" : : : "memory" );
    5.40 +}
    5.41 +
    5.42 +/* Memory barriers. */
    5.43 +#define barrier() asm volatile ( "" : : : "memory" )
    5.44 +#define rmb()     barrier()
    5.45 +#define wmb()     barrier()
    5.46 +
    5.47 +/*
    5.48 + * Divide a 64-bit dividend by a 32-bit divisor.
    5.49 + * (1) Overwrites the 64-bit dividend _in_place_ with the quotient
    5.50 + * (2) Returns the 32-bit remainder
    5.51 + */
    5.52 +#define do_div(n, base) ({                                      \
    5.53 +    unsigned long __upper, __low, __high, __mod, __base;        \
    5.54 +    __base = (base);                                            \
    5.55 +    asm ( "" : "=a" (__low), "=d" (__high) : "A" (n) );         \
    5.56 +    __upper = __high;                                           \
    5.57 +    if ( __high )                                               \
    5.58 +    {                                                           \
    5.59 +        __upper = __high % (__base);                            \
    5.60 +        __high = __high / (__base);                             \
    5.61 +    }                                                           \
    5.62 +    asm ( "divl %2"                                             \
    5.63 +          : "=a" (__low), "=d" (__mod)                          \
    5.64 +          : "rm" (__base), "0" (__low), "1" (__upper) );        \
    5.65 +    asm ( "" : "=A" (n) : "a" (__low), "d" (__high) );          \
    5.66 +    __mod;                                                      \
    5.67 +})
    5.68 +
    5.69  /* HVM-builder info. */
    5.70  int get_vcpu_nr(void);
    5.71  int get_acpi_enabled(void);