qemu/hw/i386/acpi-dsdt-mem-hotplug.dsl
Igor Mammedov 2c6b94d84e pc: acpi-build: create memory hotplug IO region dynamically
it replaces a static complied in DSDT MMIO region
for memory hotplug with one created at runtime
leaving only truly static memory hotplug related
ASL bits in DSDT. And replaces template patching
of MEMORY_SLOTS_NUMBER value with ASL API created
named value.

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

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

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:18 +01:00

161 lines
6.7 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/>.
*/
External(MEMORY_SLOT_NOTIFY_METHOD, MethodObj)
Scope(\_SB.PCI0) {
Device(MEMORY_HOTPLUG_DEVICE) {
Name(_HID, "PNP0A06")
Name(_UID, "Memory hotplug resources")
External(MEMORY_SLOTS_NUMBER, IntObj)
/* Memory hotplug IO registers */
External(MEMORY_SLOT_ADDR_LOW, FieldUnitObj) // read only
External(MEMORY_SLOT_ADDR_HIGH, FieldUnitObj) // read only
External(MEMORY_SLOT_SIZE_LOW, FieldUnitObj) // read only
External(MEMORY_SLOT_SIZE_HIGH, FieldUnitObj) // read only
External(MEMORY_SLOT_PROXIMITY, FieldUnitObj) // read only
External(MEMORY_SLOT_ENABLED, FieldUnitObj) // 1 if enabled, read only
External(MEMORY_SLOT_INSERT_EVENT, FieldUnitObj) // (read) 1 if has a insert event. (write) 1 to clear event
External(MEMORY_SLOT_SLECTOR, FieldUnitObj) // DIMM selector, write only
External(MEMORY_SLOT_OST_EVENT, FieldUnitObj) // _OST event code, write only
External(MEMORY_SLOT_OST_STATUS, FieldUnitObj) // _OST status code, write only
Method(_STA, 0) {
If (LEqual(MEMORY_SLOTS_NUMBER, Zero)) {
Return(0x0)
}
/* present, functioning, decoding, not shown in UI */
Return(0xB)
}
Mutex (MEMORY_SLOT_LOCK, 0)
Method(MEMORY_SLOT_SCAN_METHOD, 0) {
If (LEqual(MEMORY_SLOTS_NUMBER, Zero)) {
Return(Zero)
}
Store(Zero, Local0) // Mem devs iterrator
Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
while (LLess(Local0, MEMORY_SLOTS_NUMBER)) {
Store(Local0, MEMORY_SLOT_SLECTOR) // select Local0 DIMM
If (LEqual(MEMORY_SLOT_INSERT_EVENT, One)) { // Memory device needs check
MEMORY_SLOT_NOTIFY_METHOD(Local0, 1)
Store(1, MEMORY_SLOT_INSERT_EVENT)
}
// TODO: handle memory eject request
Add(Local0, One, Local0) // goto next DIMM
}
Release(MEMORY_SLOT_LOCK)
Return(One)
}
Method(MEMORY_SLOT_STATUS_METHOD, 1) {
Store(Zero, Local0)
Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
If (LEqual(MEMORY_SLOT_ENABLED, One)) {
Store(0xF, Local0)
}
Release(MEMORY_SLOT_LOCK)
Return(Local0)
}
Method(MEMORY_SLOT_CRS_METHOD, 1, Serialized) {
Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
Name(MR64, ResourceTemplate() {
QWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x0000000000000000, // Address Space Granularity
0x0000000000000000, // Address Range Minimum
0xFFFFFFFFFFFFFFFE, // Address Range Maximum
0x0000000000000000, // Address Translation Offset
0xFFFFFFFFFFFFFFFF, // Address Length
,, MW64, AddressRangeMemory, TypeStatic)
})
CreateDWordField(MR64, 14, MINL)
CreateDWordField(MR64, 18, MINH)
CreateDWordField(MR64, 38, LENL)
CreateDWordField(MR64, 42, LENH)
CreateDWordField(MR64, 22, MAXL)
CreateDWordField(MR64, 26, MAXH)
Store(MEMORY_SLOT_ADDR_HIGH, MINH)
Store(MEMORY_SLOT_ADDR_LOW, MINL)
Store(MEMORY_SLOT_SIZE_HIGH, LENH)
Store(MEMORY_SLOT_SIZE_LOW, LENL)
// 64-bit math: MAX = MIN + LEN - 1
Add(MINL, LENL, MAXL)
Add(MINH, LENH, MAXH)
If (LLess(MAXL, MINL)) {
Add(MAXH, One, MAXH)
}
If (LLess(MAXL, One)) {
Subtract(MAXH, One, MAXH)
}
Subtract(MAXL, One, MAXL)
If (LEqual(MAXH, Zero)){
Name(MR32, ResourceTemplate() {
DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, // Address Space Granularity
0x00000000, // Address Range Minimum
0xFFFFFFFE, // Address Range Maximum
0x00000000, // Address Translation Offset
0xFFFFFFFF, // Address Length
,, MW32, AddressRangeMemory, TypeStatic)
})
CreateDWordField(MR32, MW32._MIN, MIN)
CreateDWordField(MR32, MW32._MAX, MAX)
CreateDWordField(MR32, MW32._LEN, LEN)
Store(MINL, MIN)
Store(MAXL, MAX)
Store(LENL, LEN)
Release(MEMORY_SLOT_LOCK)
Return(MR32)
}
Release(MEMORY_SLOT_LOCK)
Return(MR64)
}
Method(MEMORY_SLOT_PROXIMITY_METHOD, 1) {
Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
Store(MEMORY_SLOT_PROXIMITY, Local0)
Release(MEMORY_SLOT_LOCK)
Return(Local0)
}
Method(MEMORY_SLOT_OST_METHOD, 4) {
Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
Store(Arg1, MEMORY_SLOT_OST_EVENT)
Store(Arg2, MEMORY_SLOT_OST_STATUS)
Release(MEMORY_SLOT_LOCK)
}
} // Device()
} // Scope()