sim-card
/
qemu
Archived
10
0
Fork 0

Add BIOS fixes from KVM tree

See each patch for individual Signed-off-by's/commit logs



git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6392 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
aliguori 2009-01-21 21:46:20 +00:00
parent 9043b62d4c
commit 9a717b55df
12 changed files with 695 additions and 1 deletions

View File

@ -0,0 +1,33 @@
update SMBIOS table to report memory above 4G (Alex Williamson)
Signed-off-by: Alex Williamson <alex.williamson@hp.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Index: bochs/bios/rombios32.c
===================================================================
--- bochs.orig/bios/rombios32.c
+++ bochs/bios/rombios32.c
@@ -2081,7 +2081,8 @@ void smbios_init(void)
{
unsigned cpu_num, nr_structs = 0, max_struct_size = 0;
char *start, *p, *q;
- int memsize = ram_size / (1024 * 1024);
+ int memsize = (ram_end == ram_size) ? ram_size / (1024 * 1024) :
+ (ram_end - (1ull << 32) + ram_size) / (1024 * 1024);
#ifdef BX_USE_EBDA_TABLES
ebda_cur_addr = align(ebda_cur_addr, 16);
@@ -2108,8 +2109,8 @@ void smbios_init(void)
add_struct(smbios_type_4_init(p, cpu_num));
add_struct(smbios_type_16_init(p, memsize));
add_struct(smbios_type_17_init(p, memsize));
- add_struct(smbios_type_19_init(p, memsize));
- add_struct(smbios_type_20_init(p, memsize));
+ add_struct(smbios_type_19_init(p, ram_end / (1024 * 1024)));
+ add_struct(smbios_type_20_init(p, ram_end / (1024 * 1024)));
add_struct(smbios_type_32_init(p));
add_struct(smbios_type_127_init(p));

View File

@ -0,0 +1,25 @@
generate mptable unconditionally (Avi Kivity)
VMware ESX requires an mptable even for uniprocessor guests.
Signed-off-by: Avi Kivity <avi@qumranet.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Index: bochs/bios/rombios32.c
===================================================================
--- bochs.orig/bios/rombios32.c
+++ bochs/bios/rombios32.c
@@ -970,11 +970,6 @@ static void mptable_init(void)
int ioapic_id, i, len;
int mp_config_table_size;
-#ifdef BX_QEMU
- if (smp_cpus <= 1)
- return;
-#endif
-
#ifdef BX_USE_EBDA_TABLES
mp_config_table = (uint8_t *)(ram_size - ACPI_DATA_SIZE - MPTABLE_MAX_SIZE);
#else

View File

@ -0,0 +1,120 @@
add mtrr support (Avi Kivity)
program mtrrs for cpu 0. Doesn't support >=4G at the moment.
Signed-off-by: Avi Kivity <avi@qumranet.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Index: bochs/bios/rombios32.c
===================================================================
--- bochs.orig/bios/rombios32.c
+++ bochs/bios/rombios32.c
@@ -64,6 +64,23 @@ typedef unsigned long long uint64_t;
#define BIOS_TMP_STORAGE 0x00030000 /* 64 KB used to copy the BIOS to shadow RAM */
+#define MSR_MTRRcap 0x000000fe
+#define MSR_MTRRfix64K_00000 0x00000250
+#define MSR_MTRRfix16K_80000 0x00000258
+#define MSR_MTRRfix16K_A0000 0x00000259
+#define MSR_MTRRfix4K_C0000 0x00000268
+#define MSR_MTRRfix4K_C8000 0x00000269
+#define MSR_MTRRfix4K_D0000 0x0000026a
+#define MSR_MTRRfix4K_D8000 0x0000026b
+#define MSR_MTRRfix4K_E0000 0x0000026c
+#define MSR_MTRRfix4K_E8000 0x0000026d
+#define MSR_MTRRfix4K_F0000 0x0000026e
+#define MSR_MTRRfix4K_F8000 0x0000026f
+#define MSR_MTRRdefType 0x000002ff
+
+#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
+#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
+
static inline void outl(int addr, int val)
{
asm volatile ("outl %1, %w0" : : "d" (addr), "a" (val));
@@ -135,6 +152,19 @@ static inline void putc(int c)
outb(INFO_PORT, c);
}
+static uint64_t rdmsr(unsigned index)
+{
+ unsigned long long ret;
+
+ asm ("rdmsr" : "=A"(ret) : "c"(index));
+ return ret;
+}
+
+static void wrmsr(unsigned index, uint64_t val)
+{
+ asm volatile ("wrmsr" : : "c"(index), "A"(val));
+}
+
static inline int isdigit(int c)
{
return c >= '0' && c <= '9';
@@ -469,6 +499,54 @@ static int cmos_readb(int addr)
return inb(0x71);
}
+void setup_mtrr(void)
+{
+ int i, vcnt, fix, wc;
+ uint32_t mtrr_cap;
+ union {
+ uint8_t valb[8];
+ uint64_t val;
+ } u;
+ uint64_t vbase, vmask;
+
+ mtrr_cap = rdmsr(MSR_MTRRcap);
+ vcnt = mtrr_cap & 0xff;
+ fix = mtrr_cap & 0x100;
+ wc = mtrr_cap & 0x400;
+ if (!vcnt || !fix)
+ return;
+ u.val = 0;
+ for (i = 0; i < 8; ++i)
+ if (ram_size >= 65536 * (i + 1))
+ u.valb[i] = 6;
+ wrmsr(MSR_MTRRfix64K_00000, u.val);
+ u.val = 0;
+ for (i = 0; i < 8; ++i)
+ if (ram_size >= 65536 * 8 + 16384 * (i + 1))
+ u.valb[i] = 6;
+ wrmsr(MSR_MTRRfix16K_80000, u.val);
+ wrmsr(MSR_MTRRfix16K_A0000, 0);
+ wrmsr(MSR_MTRRfix4K_C0000, 0);
+ wrmsr(MSR_MTRRfix4K_C8000, 0);
+ wrmsr(MSR_MTRRfix4K_D0000, 0);
+ wrmsr(MSR_MTRRfix4K_D8000, 0);
+ wrmsr(MSR_MTRRfix4K_E0000, 0);
+ wrmsr(MSR_MTRRfix4K_E8000, 0);
+ wrmsr(MSR_MTRRfix4K_F0000, 0);
+ wrmsr(MSR_MTRRfix4K_F8000, 0);
+ vbase = 0;
+ --vcnt; /* leave one mtrr for VRAM */
+ for (i = 0; i < vcnt && vbase < ram_size; ++i) {
+ vmask = (1ull << 40) - 1;
+ while (vbase + vmask + 1 > ram_size)
+ vmask >>= 1;
+ wrmsr(MTRRphysBase_MSR(i), vbase | 6);
+ wrmsr(MTRRphysMask_MSR(i), (~vmask & 0xfffffff000ull) | 0x800);
+ vbase += vmask + 1;
+ }
+ wrmsr(MSR_MTRRdefType, 0xc00);
+}
+
void ram_probe(void)
{
if (cmos_readb(0x34) | cmos_readb(0x35))
@@ -482,6 +560,7 @@ void ram_probe(void)
ebda_cur_addr = ((*(uint16_t *)(0x40e)) << 4) + 0x380;
BX_INFO("ebda_cur_addr: 0x%08lx\n", ebda_cur_addr);
#endif
+ setup_mtrr();
}
/****************************************************/

View File

@ -0,0 +1,126 @@
smp mtrr support (Avi Kivity)
Signed-off-by: Avi Kivity <avi@qumranet.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Index: bochs/bios/rombios.h
===================================================================
--- bochs.orig/bios/rombios.h
+++ bochs/bios/rombios.h
@@ -56,6 +56,7 @@
#define ACPI_DATA_SIZE 0x00010000L
#define PM_IO_BASE 0xb000
#define SMB_IO_BASE 0xb100
+#define SMP_MSR_ADDR 0xf010
// Define the application NAME
#if defined(BX_QEMU)
Index: bochs/bios/rombios32.c
===================================================================
--- bochs.orig/bios/rombios32.c
+++ bochs/bios/rombios32.c
@@ -472,6 +472,23 @@ void qemu_cfg_read(uint8_t *buf, int len
}
#endif
+void init_smp_msrs(void)
+{
+ *(uint32_t *)SMP_MSR_ADDR = 0;
+}
+
+void wrmsr_smp(uint32_t index, uint64_t val)
+{
+ static struct { uint32_t ecx, eax, edx; } *p = (void *)SMP_MSR_ADDR;
+
+ wrmsr(index, val);
+ p->ecx = index;
+ p->eax = val;
+ p->edx = val >> 32;
+ ++p;
+ p->ecx = 0;
+}
+
void uuid_probe(void)
{
#ifdef BX_QEMU
@@ -519,32 +536,32 @@ void setup_mtrr(void)
for (i = 0; i < 8; ++i)
if (ram_size >= 65536 * (i + 1))
u.valb[i] = 6;
- wrmsr(MSR_MTRRfix64K_00000, u.val);
+ wrmsr_smp(MSR_MTRRfix64K_00000, u.val);
u.val = 0;
for (i = 0; i < 8; ++i)
if (ram_size >= 65536 * 8 + 16384 * (i + 1))
u.valb[i] = 6;
- wrmsr(MSR_MTRRfix16K_80000, u.val);
- wrmsr(MSR_MTRRfix16K_A0000, 0);
- wrmsr(MSR_MTRRfix4K_C0000, 0);
- wrmsr(MSR_MTRRfix4K_C8000, 0);
- wrmsr(MSR_MTRRfix4K_D0000, 0);
- wrmsr(MSR_MTRRfix4K_D8000, 0);
- wrmsr(MSR_MTRRfix4K_E0000, 0);
- wrmsr(MSR_MTRRfix4K_E8000, 0);
- wrmsr(MSR_MTRRfix4K_F0000, 0);
- wrmsr(MSR_MTRRfix4K_F8000, 0);
+ wrmsr_smp(MSR_MTRRfix16K_80000, u.val);
+ wrmsr_smp(MSR_MTRRfix16K_A0000, 0);
+ wrmsr_smp(MSR_MTRRfix4K_C0000, 0);
+ wrmsr_smp(MSR_MTRRfix4K_C8000, 0);
+ wrmsr_smp(MSR_MTRRfix4K_D0000, 0);
+ wrmsr_smp(MSR_MTRRfix4K_D8000, 0);
+ wrmsr_smp(MSR_MTRRfix4K_E0000, 0);
+ wrmsr_smp(MSR_MTRRfix4K_E8000, 0);
+ wrmsr_smp(MSR_MTRRfix4K_F0000, 0);
+ wrmsr_smp(MSR_MTRRfix4K_F8000, 0);
vbase = 0;
--vcnt; /* leave one mtrr for VRAM */
for (i = 0; i < vcnt && vbase < ram_size; ++i) {
vmask = (1ull << 40) - 1;
while (vbase + vmask + 1 > ram_size)
vmask >>= 1;
- wrmsr(MTRRphysBase_MSR(i), vbase | 6);
- wrmsr(MTRRphysMask_MSR(i), (~vmask & 0xfffffff000ull) | 0x800);
+ wrmsr_smp(MTRRphysBase_MSR(i), vbase | 6);
+ wrmsr_smp(MTRRphysMask_MSR(i), (~vmask & 0xfffffff000ull) | 0x800);
vbase += vmask + 1;
}
- wrmsr(MSR_MTRRdefType, 0xc00);
+ wrmsr_smp(MSR_MTRRdefType, 0xc00);
}
void ram_probe(void)
@@ -2263,6 +2280,8 @@ void rombios32_init(uint32_t *s3_resume_
qemu_cfg_port = qemu_cfg_port_probe();
#endif
+ init_smp_msrs();
+
ram_probe();
cpu_probe();
Index: bochs/bios/rombios32start.S
===================================================================
--- bochs.orig/bios/rombios32start.S
+++ bochs/bios/rombios32start.S
@@ -49,6 +49,18 @@ _start:
smp_ap_boot_code_start:
xor %ax, %ax
mov %ax, %ds
+
+ mov $SMP_MSR_ADDR, %ebx
+11:
+ mov 0(%ebx), %ecx
+ test %ecx, %ecx
+ jz 12f
+ mov 4(%ebx), %eax
+ mov 8(%ebx), %edx
+ wrmsr
+ add $12, %ebx
+ jmp 11b
+12:
lock incw smp_cpus
1:
hlt

View File

@ -0,0 +1,62 @@
extend MTRRs to above 4G (Alex Williamson)
When I try to boot guests using a recent Linux kernel (2.6.26+), memory
above 3.5G gets thrown away with an error like this:
WARNING: BIOS bug: CPU MTRRs don't cover all of memory, losing 4608MB of RAM
This extends MTRRs to cover all of memory.
Signed-off-by: Alex Williamson <alex.williamson@hp.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Index: bochs/bios/rombios32.c
===================================================================
--- bochs.orig/bios/rombios32.c
+++ bochs/bios/rombios32.c
@@ -427,6 +427,7 @@ uint32_t cpuid_signature;
uint32_t cpuid_features;
uint32_t cpuid_ext_features;
unsigned long ram_size;
+uint64_t above4g_ram_size;
uint8_t bios_uuid[16];
#ifdef BX_USE_EBDA_TABLES
unsigned long ebda_cur_addr;
@@ -561,6 +562,14 @@ void setup_mtrr(void)
wrmsr_smp(MTRRphysMask_MSR(i), (~vmask & 0xfffffff000ull) | 0x800);
vbase += vmask + 1;
}
+ for (vbase = 1ull << 32; i < vcnt && vbase < above4g_ram_size; ++i) {
+ vmask = (1ull << 40) - 1;
+ while (vbase + vmask + 1 > above4g_ram_size)
+ vmask >>= 1;
+ wrmsr_smp(MTRRphysBase_MSR(i), vbase | 6);
+ wrmsr_smp(MTRRphysMask_MSR(i), (~vmask & 0xfffffff000ull) | 0x800);
+ vbase += vmask + 1;
+ }
wrmsr_smp(MSR_MTRRdefType, 0xc00);
}
@@ -572,11 +581,19 @@ void ram_probe(void)
else
ram_size = (cmos_readb(0x30) | (cmos_readb(0x31) << 8)) * 1024 +
1 * 1024 * 1024;
+ if (cmos_readb(0x5b) | cmos_readb(0x5c) | cmos_readb(0x5d))
+ above4g_ram_size = ((uint64_t)cmos_readb(0x5b) << 16) |
+ ((uint64_t)cmos_readb(0x5c) << 24) | ((uint64_t)cmos_readb(0x5d) << 32);
+
+ if (above4g_ram_size)
+ above4g_ram_size += 1ull << 32;
+
BX_INFO("ram_size=0x%08lx\n", ram_size);
#ifdef BX_USE_EBDA_TABLES
ebda_cur_addr = ((*(uint16_t *)(0x40e)) << 4) + 0x380;
BX_INFO("ebda_cur_addr: 0x%08lx\n", ebda_cur_addr);
#endif
+ BX_INFO("top of ram %ldMB\n", above4g_ram_size >> 20);
setup_mtrr();
}

View File

@ -0,0 +1,58 @@
cleanup/consolidate above 4G memory parsing (Alex Williamson)
Signed-off-by: Alex Williamson <alex.williamson@hp.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Index: bochs/bios/rombios32.c
===================================================================
--- bochs.orig/bios/rombios32.c
+++ bochs/bios/rombios32.c
@@ -427,7 +427,7 @@ uint32_t cpuid_signature;
uint32_t cpuid_features;
uint32_t cpuid_ext_features;
unsigned long ram_size;
-uint64_t above4g_ram_size;
+uint64_t ram_end;
uint8_t bios_uuid[16];
#ifdef BX_USE_EBDA_TABLES
unsigned long ebda_cur_addr;
@@ -562,9 +562,9 @@ void setup_mtrr(void)
wrmsr_smp(MTRRphysMask_MSR(i), (~vmask & 0xfffffff000ull) | 0x800);
vbase += vmask + 1;
}
- for (vbase = 1ull << 32; i < vcnt && vbase < above4g_ram_size; ++i) {
+ for (vbase = 1ull << 32; i < vcnt && vbase < ram_end; ++i) {
vmask = (1ull << 40) - 1;
- while (vbase + vmask + 1 > above4g_ram_size)
+ while (vbase + vmask + 1 > ram_end)
vmask >>= 1;
wrmsr_smp(MTRRphysBase_MSR(i), vbase | 6);
wrmsr_smp(MTRRphysMask_MSR(i), (~vmask & 0xfffffff000ull) | 0x800);
@@ -582,18 +582,19 @@ void ram_probe(void)
ram_size = (cmos_readb(0x30) | (cmos_readb(0x31) << 8)) * 1024 +
1 * 1024 * 1024;
if (cmos_readb(0x5b) | cmos_readb(0x5c) | cmos_readb(0x5d))
- above4g_ram_size = ((uint64_t)cmos_readb(0x5b) << 16) |
- ((uint64_t)cmos_readb(0x5c) << 24) | ((uint64_t)cmos_readb(0x5d) << 32);
+ ram_end = (((uint64_t)cmos_readb(0x5b) << 16) |
+ ((uint64_t)cmos_readb(0x5c) << 24) |
+ ((uint64_t)cmos_readb(0x5d) << 32)) + (1ull << 32);
+ else
+ ram_end = ram_size;
- if (above4g_ram_size)
- above4g_ram_size += 1ull << 32;
+ BX_INFO("end of ram=%ldMB\n", ram_end >> 20);
BX_INFO("ram_size=0x%08lx\n", ram_size);
#ifdef BX_USE_EBDA_TABLES
ebda_cur_addr = ((*(uint16_t *)(0x40e)) << 4) + 0x380;
BX_INFO("ebda_cur_addr: 0x%08lx\n", ebda_cur_addr);
#endif
- BX_INFO("top of ram %ldMB\n", above4g_ram_size >> 20);
setup_mtrr();
}

View File

@ -0,0 +1,54 @@
switch MTRRs to cover only the PCI range and default to WB (Alex Williamson)
This matches how some bare metal machines report MTRRs and avoids
the problem of running out of MTRRs to cover all of RAM.
Signed-off-by: Alex Williamson <alex.williamson@hp.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Index: bochs/bios/rombios32.c
===================================================================
--- bochs.orig/bios/rombios32.c
+++ bochs/bios/rombios32.c
@@ -525,7 +525,6 @@ void setup_mtrr(void)
uint8_t valb[8];
uint64_t val;
} u;
- uint64_t vbase, vmask;
mtrr_cap = rdmsr(MSR_MTRRcap);
vcnt = mtrr_cap & 0xff;
@@ -552,25 +551,10 @@ void setup_mtrr(void)
wrmsr_smp(MSR_MTRRfix4K_E8000, 0);
wrmsr_smp(MSR_MTRRfix4K_F0000, 0);
wrmsr_smp(MSR_MTRRfix4K_F8000, 0);
- vbase = 0;
- --vcnt; /* leave one mtrr for VRAM */
- for (i = 0; i < vcnt && vbase < ram_size; ++i) {
- vmask = (1ull << 40) - 1;
- while (vbase + vmask + 1 > ram_size)
- vmask >>= 1;
- wrmsr_smp(MTRRphysBase_MSR(i), vbase | 6);
- wrmsr_smp(MTRRphysMask_MSR(i), (~vmask & 0xfffffff000ull) | 0x800);
- vbase += vmask + 1;
- }
- for (vbase = 1ull << 32; i < vcnt && vbase < ram_end; ++i) {
- vmask = (1ull << 40) - 1;
- while (vbase + vmask + 1 > ram_end)
- vmask >>= 1;
- wrmsr_smp(MTRRphysBase_MSR(i), vbase | 6);
- wrmsr_smp(MTRRphysMask_MSR(i), (~vmask & 0xfffffff000ull) | 0x800);
- vbase += vmask + 1;
- }
- wrmsr_smp(MSR_MTRRdefType, 0xc00);
+ /* Mark 3.5-4GB as UC, anything not specified defaults to WB */
+ wrmsr_smp(MTRRphysBase_MSR(0), 0xe0000000ull | 0);
+ wrmsr_smp(MTRRphysMask_MSR(0), ~(0x20000000ull - 1) | 0x800);
+ wrmsr_smp(MSR_MTRRdefType, 0xc06);
}
void ram_probe(void)

View File

@ -0,0 +1,184 @@
resolve memory device roll over reporting issues with >32G guests (Bill Rieske)
The field within the Memory Device type 17 is only a word with the MSB being
used to report MB/KB. Thereby, a guest with 32G and greater would report
incorrect memory device information rolling over to 0.
This presents more than one memory device and associated memory structures
if the memory is larger than 16G
Signed-off-by: Bill Rieske <brieske@novell.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Index: bochs/bios/rombios32.c
===================================================================
--- bochs.orig/bios/rombios32.c
+++ bochs/bios/rombios32.c
@@ -381,6 +381,17 @@ int vsnprintf(char *buf, int buflen, con
return buf - buf0;
}
+int snprintf(char * buf, size_t size, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vsnprintf(buf,size,fmt,args);
+ va_end(args);
+ return i;
+}
+
void bios_printf(int flags, const char *fmt, ...)
{
va_list ap;
@@ -2039,7 +2050,7 @@ smbios_type_4_init(void *start, unsigned
/* Type 16 -- Physical Memory Array */
static void *
-smbios_type_16_init(void *start, uint32_t memsize)
+smbios_type_16_init(void *start, uint32_t memsize, int nr_mem_devs)
{
struct smbios_type_16 *p = (struct smbios_type_16*)start;
@@ -2052,7 +2063,7 @@ 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 = nr_mem_devs;
start += sizeof(struct smbios_type_16);
*((uint16_t *)start) = 0;
@@ -2062,20 +2073,19 @@ 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)
{
struct smbios_type_17 *p = (struct smbios_type_17 *)start;
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;
p->data_width = 64;
- /* truncate memory_size_mb to 16 bits and clear most significant
- bit [indicates size in MB] */
- p->size = (uint16_t) memory_size_mb & 0x7fff;
+/* TODO: should assert in case something is wrong ASSERT((memory_size_mb & ~0x7fff) == 0); */
+ p->size = memory_size_mb;
p->form_factor = 0x09; /* DIMM */
p->device_set = 0;
p->device_locator_str = 1;
@@ -2084,8 +2094,8 @@ smbios_type_17_init(void *start, uint32_
p->type_detail = 0;
start += sizeof(struct smbios_type_17);
- memcpy((char *)start, "DIMM 1", 7);
- start += 7;
+ snprintf(start, 8, "DIMM %d", instance);
+ start += strlen(start) + 1;
*((uint8_t *)start) = 0;
return start+1;
@@ -2093,16 +2103,16 @@ 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;
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 * 1024) - 1;
+ p->starting_address = instance << 24;
+ p->ending_address = p->starting_address + (memory_size_mb << 10) - 1;
p->memory_array_handle = 0x1000;
p->partition_width = 1;
@@ -2114,18 +2124,18 @@ smbios_type_19_init(void *start, uint32_
/* Type 20 -- Memory Device Mapped Address */
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)
{
struct smbios_type_20 *p = (struct smbios_type_20 *)start;
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 * 1024) - 1;
- p->memory_device_handle = 0x1100;
- p->memory_array_mapped_address_handle = 0x1300;
+ p->starting_address = instance << 24;
+ p->ending_address = p->starting_address + (memory_size_mb << 10) - 1;
+ p->memory_device_handle = 0x1100 + instance;
+ p->memory_array_mapped_address_handle = 0x1300 + instance;
p->partition_row_position = 1;
p->interleave_position = 0;
p->interleaved_data_depth = 0;
@@ -2176,6 +2186,7 @@ void smbios_init(void)
char *start, *p, *q;
int memsize = (ram_end == ram_size) ? ram_size / (1024 * 1024) :
(ram_end - (1ull << 32) + ram_size) / (1024 * 1024);
+ int i, nr_mem_devs;
#ifdef BX_USE_EBDA_TABLES
ebda_cur_addr = align(ebda_cur_addr, 16);
@@ -2187,23 +2198,32 @@ void smbios_init(void)
p = (char *)start + sizeof(struct smbios_entry_point);
-#define add_struct(fn) { \
+#define add_struct(fn) do{ \
q = (fn); \
nr_structs++; \
if ((q - p) > max_struct_size) \
max_struct_size = q - p; \
p = q; \
-}
+}while (0)
add_struct(smbios_type_0_init(p));
add_struct(smbios_type_1_init(p));
add_struct(smbios_type_3_init(p));
for (cpu_num = 1; cpu_num <= smp_cpus; cpu_num++)
add_struct(smbios_type_4_init(p, cpu_num));
- add_struct(smbios_type_16_init(p, memsize));
- add_struct(smbios_type_17_init(p, memsize));
- add_struct(smbios_type_19_init(p, ram_end / (1024 * 1024)));
- add_struct(smbios_type_20_init(p, ram_end / (1024 * 1024)));
+
+ /* Each 'memory device' covers up to 16GB of address space. */
+ nr_mem_devs = (memsize + 0x3fff) >> 14;
+ add_struct(smbios_type_16_init(p, memsize, nr_mem_devs));
+ for ( i = 0; i < nr_mem_devs; i++ )
+ {
+ uint32_t dev_memsize = ((i == (nr_mem_devs - 1))
+ ? (memsize & 0x3fff) : 0x4000);
+ add_struct(smbios_type_17_init(p, dev_memsize, i));
+ add_struct(smbios_type_19_init(p, dev_memsize, i));
+ add_struct(smbios_type_20_init(p, dev_memsize, i));
+ }
+
add_struct(smbios_type_32_init(p));
add_struct(smbios_type_127_init(p));

View File

@ -0,0 +1,23 @@
fix smbios memory device length boundary condition (Bill Rieske)
dev_memsize ends up 0 when it shouldn't be on 16G boundary conditions.
Signed-off-by: Bill Rieske <brieske@novell.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Index: bochs/bios/rombios32.c
===================================================================
--- bochs.orig/bios/rombios32.c
+++ bochs/bios/rombios32.c
@@ -2218,7 +2218,7 @@ void smbios_init(void)
for ( i = 0; i < nr_mem_devs; i++ )
{
uint32_t dev_memsize = ((i == (nr_mem_devs - 1))
- ? (memsize & 0x3fff) : 0x4000);
+ ? (((memsize-1) & 0x3fff)+1) : 0x4000);
add_struct(smbios_type_17_init(p, dev_memsize, i));
add_struct(smbios_type_19_init(p, dev_memsize, i));
add_struct(smbios_type_20_init(p, dev_memsize, i));

View File

@ -1 +1 @@
7342176bb0fa9d6cc63b37f6ac239e3f70b74219
36989b0d2e785ac9e5d6e8a226dbdeb82e876bfd

View File

@ -1 +1,10 @@
0001_bx-qemu.patch
0002_kvm-bios-update-smbios-table-to-report-memory-above-4g.patch
0003_kvm-bios-generate-mptable-unconditionally.patch
0004_kvm-bios-add-mtrr-support.patch
0005_kvm-bios-smp-mtrr-support.patch
0006_kvm-bios-extend-mtrrs-to-above-4g.patch
0007_kvm-bios-cleanup-consolidate-above-4g-memory-parsing.patch
0008_kvm-bios-switch-mtrrs-to-cover-only-the-pci-range-and--default-to-wb.patch
0009_kvm-bios-resolve-memory-device-roll-over-reporting--issues-with-32g-guests.patch
0010_kvm-bios-fix-smbios-memory-device-length-boundary--condition.patch

Binary file not shown.