On Thu, 2008-01-31 at 16:36 -0600, Anthony Liguori wrote: > KVM supports more than 2GB of memory for x86_64 hosts. The following patch > fixes a number of type related issues where int's were being used when they > shouldn't have been. It also introduces CMOS support so the BIOS can build > the appropriate e820 tables. the CMOS addresses that we used to register the above 4 giga memory are reserved and therefor the qemu bios does not know them you have to patch the bios as well to make it work with above 4 giga
i once wrote this patch to qemu, hope it still apply. commit 21ea5f8286fd9cd7124dfa0865a213613b51add5 Author: Izik Eidus <[EMAIL PROTECTED]> Date: Mon Aug 20 17:46:04 2007 +0300 kvm: bios: add support to memory above the pci hole the new memory region is mapped after address 0x100000000, the bios take the size of the memory after the 0x100000000 from three new cmos bytes. diff --git a/bios/rombios.c b/bios/rombios.c index 9ea2dbc..ac918ad 100644 --- a/bios/rombios.c +++ b/bios/rombios.c @@ -4078,22 +4078,25 @@ BX_DEBUG_INT15("case default:\n"); #endif -void set_e820_range(ES, DI, start, end, type) +void set_e820_range(ES, DI, start, end, extra_start, extra_end, type) Bit16u ES; Bit16u DI; Bit32u start; Bit32u end; + Bit8u extra_start; + Bit8u extra_end; Bit16u type; { write_word(ES, DI, start); write_word(ES, DI+2, start >> 16); - write_word(ES, DI+4, 0x00); + write_word(ES, DI+4, extra_start); write_word(ES, DI+6, 0x00); end -= start; + extra_end -= extra_start; write_word(ES, DI+8, end); write_word(ES, DI+10, end >> 16); - write_word(ES, DI+12, 0x0000); + write_word(ES, DI+12, extra_end); write_word(ES, DI+14, 0x0000); write_word(ES, DI+16, type); @@ -4106,7 +4109,9 @@ int15_function32(regs, ES, DS, FLAGS) Bit16u ES, DS, FLAGS; { Bit32u extended_memory_size=0; // 64bits long + Bit32u extra_lowbits_memory_size=0; Bit16u CX,DX; + Bit8u extra_highbits_memory_size=0; BX_DEBUG_INT15("int15 AX=%04x\n",regs.u.r16.ax); @@ -4179,11 +4184,18 @@ ASM_END extended_memory_size *= 1024; } + extra_lowbits_memory_size = inb_cmos(0x5c); + extra_lowbits_memory_size <<= 8; + extra_lowbits_memory_size |= inb_cmos(0x5b); + extra_lowbits_memory_size *= 64; + extra_lowbits_memory_size *= 1024; + extra_highbits_memory_size = inb_cmos(0x5d); + switch(regs.u.r16.bx) { case 0: set_e820_range(ES, regs.u.r16.di, - 0x0000000L, 0x0009fc00L, 1); + 0x0000000L, 0x0009fc00L, 0, 0, 1); regs.u.r32.ebx = 1; regs.u.r32.eax = 0x534D4150; regs.u.r32.ecx = 0x14; @@ -4192,7 +4204,7 @@ ASM_END break; case 1: set_e820_range(ES, regs.u.r16.di, - 0x0009fc00L, 0x000a0000L, 2); + 0x0009fc00L, 0x000a0000L, 0, 0, 2); regs.u.r32.ebx = 2; regs.u.r32.eax = 0x534D4150; regs.u.r32.ecx = 0x14; @@ -4201,7 +4213,7 @@ ASM_END break; case 2: set_e820_range(ES, regs.u.r16.di, - 0x000e8000L, 0x00100000L, 2); + 0x000e8000L, 0x00100000L, 0, 0, 2); regs.u.r32.ebx = 3; regs.u.r32.eax = 0x534D4150; regs.u.r32.ecx = 0x14; @@ -4211,7 +4223,7 @@ ASM_END case 3: set_e820_range(ES, regs.u.r16.di, 0x00100000L, - extended_memory_size - ACPI_DATA_SIZE, 1); + extended_memory_size - ACPI_DATA_SIZE ,0, 0, 1); regs.u.r32.ebx = 4; regs.u.r32.eax = 0x534D4150; regs.u.r32.ecx = 0x14; @@ -4221,7 +4233,7 @@ ASM_END case 4: set_e820_range(ES, regs.u.r16.di, extended_memory_size - ACPI_DATA_SIZE, - extended_memory_size, 3); // ACPI RAM + extended_memory_size ,0, 0, 3); // ACPI RAM regs.u.r32.ebx = 5; regs.u.r32.eax = 0x534D4150; regs.u.r32.ecx = 0x14; @@ -4231,7 +4243,20 @@ ASM_END case 5: /* 256KB BIOS area at the end of 4 GB */ set_e820_range(ES, regs.u.r16.di, - 0xfffc0000L, 0x00000000L, 2); + 0xfffc0000L, 0x00000000L ,0, 0, 2); + if (extra_highbits_memory_size || extra_lowbits_memory_size) + regs.u.r32.ebx = 6; + else + regs.u.r32.ebx = 0; + regs.u.r32.eax = 0x534D4150; + regs.u.r32.ecx = 0x14; + CLEAR_CF(); + return; + case 6: + /* Maping of memory above 4 GB */ + set_e820_range(ES, regs.u.r16.di, 0x00000000L, + extra_lowbits_memory_size, 1, extra_highbits_memory_size + + 1, 1); regs.u.r32.ebx = 0; regs.u.r32.eax = 0x534D4150; regs.u.r32.ecx = 0x14;