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@sgi.com>

---
 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@sgi.com>
+ *
+ * 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);
