Hi, I figured out why Windows wasn't booting with the previous version of the patch. It seems it didn't like the forward declaration of the _PR.PRSC method. Instead I found that it does seem to work if I add the calling method _GRE.L02 in the SSDT, while the rest of the _GRE is declared in the DSDT. It boots, it's perfect! Cheers, Jes
Move _PR block from the DSDT to a new SSDT in the KVM BIOS. As AML, or at least Windows doesn't allow forward declarations of Methods, it is necessary to declare the _GPE._L02 Method in the SSDT as well. This will make it possible to plug in different SSDTs with different processor counts in the future. Signed-off-by: Jes Sorensen <jes@xxxxxxx> --- kvm/bios/Makefile | 12 +++- kvm/bios/acpi-dsdt.dsl | 105 ------------------------------------ kvm/bios/acpi-ssdt.dsl | 140 +++++++++++++++++++++++++++++++++++++++++++++++++ kvm/bios/rombios32.c | 16 ++++- 4 files changed, 161 insertions(+), 112 deletions(-) Index: qemu-kvm/kvm/bios/Makefile =================================================================== --- qemu-kvm.orig/kvm/bios/Makefile +++ qemu-kvm/kvm/bios/Makefile @@ -71,7 +71,7 @@ bios: biossums BIOS-bochs-latest BIOS-bo clean: rm -f *.o *.a *.s _rombios*_.c rombios*.txt rombios*.sym rm -f usage biossums rombios16.bin - rm -f rombios32.bin rombios32.out acpi-dsdt.hex + rm -f rombios32.bin rombios32.out acpi-dsdt.hex acpi-ssdt.hex dist-clean: clean rm -f Makefile @@ -108,13 +108,19 @@ rombios32.bin: rombios32.out rombios.h rombios32.out: rombios32start.o rombios32.o vapic.o rombios32.ld ld -o $@ -T rombios32.ld rombios32start.o vapic.o rombios32.o -rombios32.o: rombios32.c acpi-dsdt.hex +rombios32.o: rombios32.c acpi-dsdt.hex acpi-ssdt.hex $(GCC) -m32 -O2 -Wall -c -o $@ $< acpi-dsdt.hex: acpi-dsdt.dsl cpp -P $< $<.i iasl -tc -p $@ $<.i - sed -i -e's/^unsigned/const unsigned/' $@ + sed -i -e's/^unsigned char AmlCode/const unsigned char DSDTCode/' $@ + rm $<.i + +acpi-ssdt.hex: acpi-ssdt.dsl + cpp -P $< $<.i + iasl -tc -p $@ $<.i + sed -i -e's/^unsigned char AmlCode/const unsigned char SSDTCode/' $@ rm $<.i rombios32start.o: rombios32start.S Index: qemu-kvm/kvm/bios/acpi-dsdt.dsl =================================================================== --- qemu-kvm.orig/kvm/bios/acpi-dsdt.dsl +++ qemu-kvm/kvm/bios/acpi-dsdt.dsl @@ -25,108 +25,6 @@ DefinitionBlock ( 0x1 // OEM Revision ) { - Scope (\_PR) - { - /* pointer to first element of MADT APIC structures */ - OperationRegion(ATPR, SystemMemory, 0x0514, 4) - Field (ATPR, DwordAcc, NoLock, Preserve) - { - ATP, 32 - } - -#define madt_addr(nr) Add (ATP, Multiply(nr, 8)) - -#define gen_processor(nr, name) \ - Processor (CPU##name, nr, 0x0000b010, 0x06) { \ - OperationRegion (MATR, SystemMemory, madt_addr(nr), 8) \ - Field (MATR, ByteAcc, NoLock, Preserve) \ - { \ - MAT, 64 \ - } \ - Field (MATR, ByteAcc, NoLock, Preserve) \ - { \ - Offset(4), \ - FLG, 1 \ - } \ - Method(_MAT, 0) { \ - Return(MAT) \ - } \ - Method (_STA) { \ - If (FLG) { Return(0xF) } Else { Return(0x9) } \ - } \ - } \ - - - gen_processor(0, 0) - gen_processor(1, 1) - gen_processor(2, 2) - gen_processor(3, 3) - gen_processor(4, 4) - gen_processor(5, 5) - gen_processor(6, 6) - gen_processor(7, 7) - gen_processor(8, 8) - gen_processor(9, 9) - gen_processor(10, A) - gen_processor(11, B) - gen_processor(12, C) - gen_processor(13, D) - gen_processor(14, E) - - Method (NTFY, 2) { -#define gen_ntfy(nr) \ - If (LEqual(Arg0, 0x##nr)) { \ - If (LNotEqual(Arg1, \_PR.CPU##nr.FLG)) { \ - Store (Arg1, \_PR.CPU##nr.FLG) \ - If (LEqual(Arg1, 1)) { \ - Notify(CPU##nr, 1) \ - } Else { \ - Notify(CPU##nr, 3) \ - } \ - } \ - } - gen_ntfy(0) - gen_ntfy(1) - gen_ntfy(2) - gen_ntfy(3) - gen_ntfy(4) - gen_ntfy(5) - gen_ntfy(6) - gen_ntfy(7) - gen_ntfy(8) - gen_ntfy(9) - gen_ntfy(A) - gen_ntfy(B) - gen_ntfy(C) - gen_ntfy(D) - gen_ntfy(E) - Return(One) - } - - OperationRegion(PRST, SystemIO, 0xaf00, 32) - Field (PRST, ByteAcc, NoLock, Preserve) - { - PRS, 256 - } - - Method(PRSC, 0) { - Store(PRS, Local3) - Store(Zero, Local0) - While(LLess(Local0, 32)) { - Store(Zero, Local1) - Store(DerefOf(Index(Local3, Local0)), Local2) - While(LLess(Local1, 8)) { - NTFY(Add(Multiply(Local0, 8), Local1), - And(Local2, 1)) - ShiftRight(Local2, 1, Local2) - Increment(Local1) - } - Increment(Local0) - } - Return(One) - } - } - Scope (\) { /* Debug Output */ @@ -803,9 +701,6 @@ DefinitionBlock ( Return(0x01) } - Method(_L02) { - Return(\_PR.PRSC()) - } Method(_L03) { Return(0x01) } Index: qemu-kvm/kvm/bios/acpi-ssdt.dsl =================================================================== --- /dev/null +++ qemu-kvm/kvm/bios/acpi-ssdt.dsl @@ -0,0 +1,140 @@ +/* + * Bochs/QEMU ACPI SSDT ASL definition + * + * Copyright (c) 2006 Fabrice Bellard + * Copyright (c) 2009 SGI, Jes Sorensen <jes@xxxxxxx> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +DefinitionBlock ( + "acpi-ssdt.aml", // Output Filename + "SSDT", // Signature + 0x01, // DSDT Compliance Revision + "BXPC", // OEMID + "BXSSDT", // TABLE ID + 0x1 // OEM Revision + ) +{ + Scope (\_PR) + { + /* pointer to first element of MADT APIC structures */ + OperationRegion(ATPR, SystemMemory, 0x0514, 4) + Field (ATPR, DwordAcc, NoLock, Preserve) + { + ATP, 32 + } + +#define madt_addr(nr) Add (ATP, Multiply(nr, 8)) + +#define gen_processor(nr, name) \ + Processor (C##name, nr, 0x0000b010, 0x06) { \ + OperationRegion (MATR, SystemMemory, madt_addr(nr), 8) \ + Field (MATR, ByteAcc, NoLock, Preserve) \ + { \ + MAT, 64 \ + } \ + Field (MATR, ByteAcc, NoLock, Preserve) \ + { \ + Offset(4), \ + FLG, 1 \ + } \ + Method(_MAT, 0) { \ + Return(MAT) \ + } \ + Method (_STA) { \ + If (FLG) { Return(0xF) } Else { Return(0x9) } \ + } \ + } \ + + + gen_processor(0, 0) + gen_processor(1, 1) + gen_processor(2, 2) + gen_processor(3, 3) + gen_processor(4, 4) + gen_processor(5, 5) + gen_processor(6, 6) + gen_processor(7, 7) + gen_processor(8, 8) + gen_processor(9, 9) + gen_processor(10, A) + gen_processor(11, B) + gen_processor(12, C) + gen_processor(13, D) + gen_processor(14, E) + + Method (NTFY, 2) { +#define gen_ntfy(nr) \ + If (LEqual(Arg0, 0x##nr)) { \ + If (LNotEqual(Arg1, \_PR.C##nr.FLG)) { \ + Store (Arg1, \_PR.C##nr.FLG) \ + If (LEqual(Arg1, 1)) { \ + Notify(C##nr, 1) \ + } Else { \ + Notify(C##nr, 3) \ + } \ + } \ + } + gen_ntfy(0) + gen_ntfy(1) + gen_ntfy(2) + gen_ntfy(3) + gen_ntfy(4) + gen_ntfy(5) + gen_ntfy(6) + gen_ntfy(7) + gen_ntfy(8) + gen_ntfy(9) + gen_ntfy(A) + gen_ntfy(B) + gen_ntfy(C) + gen_ntfy(D) + gen_ntfy(E) + Return(One) + } + + OperationRegion(PRST, SystemIO, 0xaf00, 32) + Field (PRST, ByteAcc, NoLock, Preserve) + { + PRS, 256 + } + + Method(PRSC, 0) { + Store(PRS, Local3) + Store(Zero, Local0) + While(LLess(Local0, 32)) { + Store(Zero, Local1) + Store(DerefOf(Index(Local3, Local0)), Local2) + While(LLess(Local1, 8)) { + NTFY(Add(Multiply(Local0, 8), Local1), + And(Local2, 1)) + ShiftRight(Local2, 1, Local2) + Increment(Local1) + } + Increment(Local0) + } + Return(One) + } + } + + /* + * Add the missing _L02 method for CPU notification + */ + Scope (\_GPE) + { + Method(_L02) { + Return(\_PR.PRSC()) + } + } +} Index: qemu-kvm/kvm/bios/rombios32.c =================================================================== --- qemu-kvm.orig/kvm/bios/rombios32.c +++ qemu-kvm/kvm/bios/rombios32.c @@ -1526,6 +1526,7 @@ struct madt_int_override #endif #include "acpi-dsdt.hex" +#include "acpi-ssdt.hex" static inline uint16_t cpu_to_le16(uint16_t x) { @@ -1646,7 +1647,11 @@ void acpi_bios_init(void) dsdt_addr = addr; dsdt = (void *)(addr); - addr += sizeof(AmlCode); + addr += sizeof(DSDTCode); + + ssdt_addr = addr; + ssdt = (void *)(addr); + addr += sizeof(SSDTCode); #ifdef BX_QEMU qemu_cfg_select(QEMU_CFG_NUMA); @@ -1739,7 +1744,10 @@ void acpi_bios_init(void) BX_INFO("Firmware waking vector %p\n", &facs->firmware_waking_vector); /* DSDT */ - memcpy(dsdt, AmlCode, sizeof(AmlCode)); + memcpy(dsdt, DSDTCode, sizeof(DSDTCode)); + + /* SSDT */ + memcpy(ssdt, SSDTCode, sizeof(SSDTCode)); /* MADT */ { @@ -1895,9 +1903,9 @@ void acpi_bios_init(void) /* RSDT */ rsdt->table_offset_entry[nb_rsdt_entries++] = cpu_to_le32(fadt_addr); + /* On real hardware the SSDT seems to come before the MADT (APIC) */ + rsdt->table_offset_entry[nb_rsdt_entries++] = cpu_to_le32(ssdt_addr); rsdt->table_offset_entry[nb_rsdt_entries++] = cpu_to_le32(madt_addr); - /* kvm has no ssdt (processors are in dsdt) */ -// rsdt->table_offset_entry[nb_rsdt_entries++] = cpu_to_le32(ssdt_addr); #ifdef BX_QEMU /* No HPET (yet) */ // rsdt->table_offset_entry[nb_rsdt_entries++] = cpu_to_le32(hpet_addr);