x86: Add DSDT table for supporting ACPI on QEMU
The DSDT table contains a bytecode that is executed by a driver in the kernel.
Signed-off-by: Saket Sinha <saket.sinha89@gmail.com>
Tested with QEMU '-M q35'
Tested-by: Bin Meng <bmeng.cn@gmail.com>
diff --git a/arch/x86/cpu/qemu/acpi/cpu-hotplug.asl b/arch/x86/cpu/qemu/acpi/cpu-hotplug.asl
new file mode 100644
index 0000000..a290a4c
--- /dev/null
+++ b/arch/x86/cpu/qemu/acpi/cpu-hotplug.asl
@@ -0,0 +1,80 @@
+/* CPU hotplug */
+
+Scope(\_SB) {
+ /* Objects filled in by run-time generated SSDT */
+ External(NTFY, MethodObj)
+ External(CPON, PkgObj)
+
+ /* Methods called by run-time generated SSDT Processor objects */
+ Method(CPMA, 1, NotSerialized) {
+ /*
+ * _MAT method - create an madt apic buffer
+ * Arg0 = Processor ID = Local APIC ID
+ * Local0 = CPON flag for this cpu
+ */
+ Store(DerefOf(Index(CPON, Arg0)), Local0)
+ /* Local1 = Buffer (in madt apic form) to return */
+ Store(Buffer(8) {0x00, 0x08, 0x00, 0x00, 0x00, 0, 0, 0}, Local1)
+ /* Update the processor id, lapic id, and enable/disable status */
+ Store(Arg0, Index(Local1, 2))
+ Store(Arg0, Index(Local1, 3))
+ Store(Local0, Index(Local1, 4))
+ Return (Local1)
+ }
+ Method(CPST, 1, NotSerialized) {
+ /*
+ * _STA method - return ON status of cpu
+ * Arg0 = Processor ID = Local APIC ID
+ * Local0 = CPON flag for this cpu
+ */
+ Store(DerefOf(Index(CPON, Arg0)), Local0)
+ If (Local0) {
+ Return (0xf)
+ } Else {
+ Return (0x0)
+ }
+ }
+ Method(CPEJ, 2, NotSerialized) {
+ /* _EJ0 method - eject callback */
+ Sleep(200)
+ }
+
+ /* CPU hotplug notify method */
+ OperationRegion(PRST, SystemIO, 0xaf00, 32)
+ Field(PRST, ByteAcc, NoLock, Preserve) {
+ PRS, 256
+ }
+ Method(PRSC, 0) {
+ /* Local5 = active cpu bitmap */
+ Store(PRS, Local5)
+ /* Local2 = last read byte from bitmap */
+ Store(Zero, Local2)
+ /* Local0 = Processor ID / APIC ID iterator */
+ Store(Zero, Local0)
+ While (LLess(Local0, SizeOf(CPON))) {
+ /* Local1 = CPON flag for this cpu */
+ Store(DerefOf(Index(CPON, Local0)), Local1)
+ If (And(Local0, 0x07)) {
+ /* Shift down previously read bitmap byte */
+ ShiftRight(Local2, 1, Local2)
+ } Else {
+ /* Read next byte from cpu bitmap */
+ Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
+ }
+ /* Local3 = active state for this cpu */
+ Store(And(Local2, 1), Local3)
+
+ If (LNotEqual(Local1, Local3)) {
+ /* State change - update CPON with new state */
+ Store(Local3, Index(CPON, Local0))
+ /* Do CPU notify */
+ If (LEqual(Local3, 1)) {
+ NTFY(Local0, 1)
+ } Else {
+ NTFY(Local0, 3)
+ }
+ }
+ Increment(Local0)
+ }
+ }
+}
diff --git a/arch/x86/cpu/qemu/acpi/dbug.asl b/arch/x86/cpu/qemu/acpi/dbug.asl
new file mode 100644
index 0000000..38a6526
--- /dev/null
+++ b/arch/x86/cpu/qemu/acpi/dbug.asl
@@ -0,0 +1,25 @@
+/* Debugging */
+
+Scope(\) {
+ /* Debug Output */
+ OperationRegion(DBG, SystemIO, 0x0402, 0x01)
+ Field(DBG, ByteAcc, NoLock, Preserve) {
+ DBGB, 8,
+ }
+ /*
+ * Debug method - use this method to send output to the QEMU
+ * BIOS debug port. This method handles strings, integers,
+ * and buffers. For example: DBUG("abc") DBUG(0x123)
+ */
+ Method(DBUG, 1) {
+ ToHexString(Arg0, Local0)
+ ToBuffer(Local0, Local0)
+ Subtract(SizeOf(Local0), 1, Local1)
+ Store(Zero, Local2)
+ While (LLess(Local2, Local1)) {
+ Store(DerefOf(Index(Local0, Local2)), DBGB)
+ Increment(Local2)
+ }
+ Store(0x0a, dbgb)
+ }
+}
diff --git a/arch/x86/cpu/qemu/acpi/hpet.asl b/arch/x86/cpu/qemu/acpi/hpet.asl
new file mode 100644
index 0000000..983151e
--- /dev/null
+++ b/arch/x86/cpu/qemu/acpi/hpet.asl
@@ -0,0 +1,31 @@
+/* HPET */
+
+Scope(\_SB) {
+ Device(HPET) {
+ Name(_HID, EISAID("PNP0103"))
+ Name(_UID, 0)
+ OperationRegion(HPTM, SystemMemory, 0xfed00000, 0x400)
+ Field(HPTM, DWordAcc, Lock, Preserve) {
+ VEND, 32,
+ PRD, 32,
+ }
+ Method(_STA, 0, NotSerialized) {
+ Store(VEND, Local0)
+ Store(PRD, Local1)
+ ShiftRight(Local0, 16, Local0)
+ If (LOr(LEqual(Local0, 0), LEqual(Local0, 0xffff))) {
+ Return (0x0)
+ }
+ If (LOr(LEqual(Local1, 0), LGreater(Local1, 100000000))) {
+ Return (0x0)
+ }
+ Return (0x0f)
+ }
+ Name(_CRS, ResourceTemplate() {
+ Memory32Fixed(ReadOnly,
+ 0xfed00000, /* Address Base */
+ 0x00000400, /* Address Length */
+ )
+ })
+ }
+}
diff --git a/arch/x86/cpu/qemu/acpi/isa.asl b/arch/x86/cpu/qemu/acpi/isa.asl
new file mode 100644
index 0000000..d6b3d9b
--- /dev/null
+++ b/arch/x86/cpu/qemu/acpi/isa.asl
@@ -0,0 +1,102 @@
+/* Common legacy ISA style devices. */
+Scope(\_SB.PCI0.ISA) {
+
+ Device(RTC) {
+ Name(_HID, EisaId("PNP0B00"))
+ Name(_CRS, ResourceTemplate() {
+ IO(Decode16, 0x0070, 0x0070, 0x10, 0x02)
+ IRQNoFlags() { 8 }
+ IO(Decode16, 0x0072, 0x0072, 0x02, 0x06)
+ })
+ }
+
+ Device(KBD) {
+ Name(_HID, EisaId("PNP0303"))
+ Method(_STA, 0, NotSerialized) {
+ Return (0x0f)
+ }
+ Name(_CRS, ResourceTemplate() {
+ IO(Decode16, 0x0060, 0x0060, 0x01, 0x01)
+ IO(Decode16, 0x0064, 0x0064, 0x01, 0x01)
+ IRQNoFlags() { 1 }
+ })
+ }
+
+ Device(MOU) {
+ Name(_HID, EisaId("PNP0F13"))
+ Method(_STA, 0, NotSerialized) {
+ Return (0x0f)
+ }
+ Name(_CRS, ResourceTemplate() {
+ IRQNoFlags() { 12 }
+ })
+ }
+
+ Device(FDC0) {
+ Name(_HID, EisaId("PNP0700"))
+ Method(_STA, 0, NotSerialized) {
+ Store(FDEN, Local0)
+ If (LEqual(Local0, 0)) {
+ Return (0x00)
+ } Else {
+ Return (0x0f)
+ }
+ }
+ Name(_CRS, ResourceTemplate() {
+ IO(Decode16, 0x03f2, 0x03f2, 0x00, 0x04)
+ IO(Decode16, 0x03f7, 0x03f7, 0x00, 0x01)
+ IRQNoFlags() { 6 }
+ DMA(Compatibility, NotBusMaster, Transfer8) { 2 }
+ })
+ }
+
+ Device(LPT) {
+ Name(_HID, EisaId("PNP0400"))
+ Method(_STA, 0, NotSerialized) {
+ Store(LPEN, Local0)
+ If (LEqual(Local0, 0)) {
+ Return (0x00)
+ } Else {
+ Return (0x0f)
+ }
+ }
+ Name(_CRS, ResourceTemplate() {
+ IO(Decode16, 0x0378, 0x0378, 0x08, 0x08)
+ IRQNoFlags() { 7 }
+ })
+ }
+
+ Device(COM1) {
+ Name(_HID, EisaId("PNP0501"))
+ Name(_UID, 0x01)
+ Method(_STA, 0, NotSerialized) {
+ Store(CAEN, Local0)
+ If (LEqual(Local0, 0)) {
+ Return (0x00)
+ } Else {
+ Return (0x0f)
+ }
+ }
+ Name(_CRS, ResourceTemplate() {
+ IO(Decode16, 0x03f8, 0x03f8, 0x00, 0x08)
+ IRQNoFlags() { 4 }
+ })
+ }
+
+ Device(COM2) {
+ Name(_HID, EisaId("PNP0501"))
+ Name(_UID, 0x02)
+ Method(_STA, 0, NotSerialized) {
+ Store(CBEN, Local0)
+ If (LEqual(Local0, 0)) {
+ Return (0x00)
+ } Else {
+ Return (0x0f)
+ }
+ }
+ Name(_CRS, ResourceTemplate() {
+ IO(Decode16, 0x02f8, 0x02f8, 0x00, 0x08)
+ IRQNoFlags() { 3 }
+ })
+ }
+}
diff --git a/arch/x86/cpu/qemu/acpi/pci-crs.asl b/arch/x86/cpu/qemu/acpi/pci-crs.asl
new file mode 100644
index 0000000..a336dce
--- /dev/null
+++ b/arch/x86/cpu/qemu/acpi/pci-crs.asl
@@ -0,0 +1,61 @@
+/* PCI CRS (current resources) definition. */
+Scope(\_SB.PCI0) {
+
+ Name(CRES, ResourceTemplate() {
+ WordBusNumber(ResourceProducer, MinFixed, MaxFixed, PosDecode,
+ 0x0000, /* Address Space Granularity */
+ 0x0000, /* Address Range Minimum */
+ 0x00ff, /* Address Range Maximum */
+ 0x0000, /* Address Translation Offset */
+ 0x0100, /* Address Length */
+ ,, )
+ IO(Decode16,
+ 0x0cf8, /* Address Range Minimum */
+ 0x0cf8, /* Address Range Maximum */
+ 0x01, /* Address Alignment */
+ 0x08, /* Address Length */
+ )
+ WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+ 0x0000, /* Address Space Granularity */
+ 0x0000, /* Address Range Minimum */
+ 0x0cf7, /* Address Range Maximum */
+ 0x0000, /* Address Translation Offset */
+ 0x0cf8, /* Address Length */
+ ,, , TypeStatic)
+ WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+ 0x0000, /* Address Space Granularity */
+ 0x0d00, /* Address Range Minimum */
+ 0xffff, /* Address Range Maximum */
+ 0x0000, /* Address Translation Offset */
+ 0xf300, /* Address Length */
+ ,, , TypeStatic)
+ DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
+ 0x00000000, /* Address Space Granularity */
+ 0x000a0000, /* Address Range Minimum */
+ 0x000bffff, /* Address Range Maximum */
+ 0x00000000, /* Address Translation Offset */
+ 0x00020000, /* Address Length */
+ ,, , AddressRangeMemory, TypeStatic)
+ DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
+ 0x00000000, /* Address Space Granularity */
+ 0xe0000000, /* Address Range Minimum */
+ 0xfebfffff, /* Address Range Maximum */
+ 0x00000000, /* Address Translation Offset */
+ 0x1ec00000, /* Address Length */
+ ,, PW32, AddressRangeMemory, TypeStatic)
+ })
+
+ Name(CR64, ResourceTemplate() {
+ QWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
+ 0x00000000, /* Address Space Granularity */
+ 0x80000000, /* Address Range Minimum */
+ 0xffffffff, /* Address Range Maximum */
+ 0x00000000, /* Address Translation Offset */
+ 0x80000000, /* Address Length */
+ ,, PW64, AddressRangeMemory, TypeStatic)
+ })
+
+ Method(_CRS, 0) {
+ Return (CRES)
+ }
+}