qemu-patch-raspberry4/hw/i386/acpi-dsdt-cpu-hotplug.dsl
Igor Mammedov ddf1ec2ffe pc: acpi-build: create CPU hotplug IO region dynamically
it replaces a static complied in DSDT MMIO region
for CPU hotplug with one created at runtime
leaving only truly static CPU hotplug related ASL
bits in DSDT.
It also puts CPU_HOTPLUG_RESOURCE_DEVICE into
PCI0 scope and reserves resources from it,
preparing for dropping manual hole punching
in PCI0._CRS.

Later it also would make easier to reuse current
ACPI CPU hotplug on other targets.

Also later it would be possible to move remaining
CPU hotplug ASL methods into build_ssdt() and
add all CPU hotplug related AML into SSDT only
when CPU hotplug is enabled, further reducing
ACPI tables blob if CPU hotplug isn't used.

impl. detail:
Windows XP can't handle /BSODs/ OperationRegion
declaration in DSDT when variable from SSDT is used
for specifying its address/length and also when
Field declared in DSDT with OperationRegion from
SSDT if DSDT is being parsed before SSDT.
But it works just fine when referencing named
fields from another table. Hence OperationRegion
and Field declaration are moved to SSDT to make
XP based editions work.

PS:
Later Windows editions seem to be fine with above
conditions.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-02-26 13:04:17 +01:00

91 lines
3.2 KiB
Plaintext

/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************
* CPU hotplug
****************************************************************/
Scope(\_SB) {
/* Objects filled in by run-time generated SSDT */
External(NTFY, MethodObj)
External(CPON, PkgObj)
External(PRS, FieldUnitObj)
/* 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)
}
#define CPU_STATUS_LEN ACPI_GPE_PROC_LEN
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)
}
}
}