- Joined
- Oct 4, 2018
- Messages
- 1,484
- Motherboard
- Gigabyte C246-WU4
- CPU
- E-2278G
- Graphics
- WX7100
- Mac
The problem
OS X expects processors to be declared in ACPI through
Fortunately for our hacks, most motherboard manufacturers still use the deprecated style in their declarations. But when they change to current standards, OS X simply cannot find any processor to run on and boot stalls at an early stage.
The solution
Define old-style Processor() objects in a SSDT, wrapping the processor devices.
Attached are three SSDTs for Xeon-based systems.
SSDT-CPU-WRAP.aml is suitable for uni-socket C621 systems and known to be working on Gigabyte C621-SU8 and Asus PRO WS C621-64L SAGE/10G.
SSDT-CPU-WRAP2.aml is known to work with Supermicro X11SPA-F (C422); it should be suitable for C621 systems with a PBaseAdress of 0x1810 (this appears to be the case for dual-socket Gigabyte C621-WD12… but adding the second socket if left as an exercise for the reader).
SSDT-CPU-WRAP3.aml was written for Supermicro X12SPA-TF (C621A, 3rd generation Xeon Scalable). (As of this writing, the board has not yet successfully booted OS X, but is getting ever closer.)
AMD users on B550 or A520 can use Acidanthera's SSDT-CPUR.aml.
Who needs such a SSDT?
The typical symptom is OS X verbose boot stalling just after loading the ACPI tables ("oops, there's no processor!"). The diagnostic is confirmed by dropping ACPI tables (OpenCore: use DEBUG version with Misc>Debug>SysReport:True; Clover: F4), decompiling DSDT.aml with MaciASL (or SSDT*.aml for AMD-based systems, which may not define CPUs in the DSDT) and looking for "Processor".
If you see something like
If you see something like
CPU wrapping is needed.
The issue first affected C621 systems for Xeon Scalable or Xeon W-3200 CPUs, possibly through a BIOS update switching from the old style to the new style. Recently, the issue creped on a C422 system for Xeon W-2000 through a BIOS update (namely Supermicro X11SRA-F on BIOS v.2.4). C621A systems for 3rd generation Xeon Scalable or Xeon W-3300 are affected from the outset.
On the consumer side, AMD B550 and A520 are affected (Acidanthera SSDT-CPUR), but curiously not X570 and earlier. Z690 for Alder Lake CPUs appears to be affected from the outset; Intel has likely taken the opportunity of this major architectural style to update its reference ACPI code.
Z590 and earlier are fine so far, and may remain so if manufacturers do not bother rewriting their ACPI tables for "old" boards. But there's a risk that the issue could propagate through BIOS updates. HEDT systems on X299 are possibly most at risk for this, seeing what happened on C422.
Virtualisation with HyperV is also affected (Acidanthera SSDT-HV-CPU).
How to adapt?
The base code unit is:
corresponding to ACPI declaration
Obviously, ACPI path to the CPU is to be adapted; consumer platforms would not have multiple sockets in the way (_SB.CP## rather than _SB.SCK#.CP##).
Fake
Per the specification,
Typical values for
The ACPI compiler will not yet you forget to also adapt all the
What else?
When using a CPU wrapping SSDT, any further SSDT which refers to the CPU—typically SSDT-PLUG for power management on Intel platforms—should: 1) load after SSDT-CPU-WRAP; and 2) target the fake Processor() objects in SSDT-CPU-WRAP and not to to the real CPU Device() in the DSDT (so _SB.SCK0.PR00 with SSDT-CPU-WRAP(2) as provided, and not _SB.SCK0.CP00).
Thanks to @metacollin for identifying the issue and writing the first wrapping SSDT, to @yapan4 and @obus for their enduring moral support while I was hacking my C621 system, to @yapan4 and @ramazarusx for additional testing, to the zero-post user who tipped me on simplifying wrapping through a private message, to Pike R. Alpha for ssdtPRGen.sh and computing PBaseAddress, and to the Acidanthera team for their ACPI guides which greatly helped me grasp how to write SSDTs. (I've not yet adopted the ACPI specification as bedtime reading, but I've got a little closer…)
OS X expects processors to be declared in ACPI through
Processor()
objects, in accordance with versions 1.0 (December 1996) and 2.0 (July 2000) of the ACPI specification. Version 3.0 (September 2004) of the ACPI specification introduced (and obviously favoured) declaring processors as generic ACPI Device()
with a specific hardware ID (_HID="ACPI0007"
). From version 6.0 onwards (April 2015), the old Processor() object is officially deprecated. The current specification is version 6.4.Fortunately for our hacks, most motherboard manufacturers still use the deprecated style in their declarations. But when they change to current standards, OS X simply cannot find any processor to run on and boot stalls at an early stage.
The solution
Define old-style Processor() objects in a SSDT, wrapping the processor devices.
Attached are three SSDTs for Xeon-based systems.
SSDT-CPU-WRAP.aml is suitable for uni-socket C621 systems and known to be working on Gigabyte C621-SU8 and Asus PRO WS C621-64L SAGE/10G.
SSDT-CPU-WRAP2.aml is known to work with Supermicro X11SPA-F (C422); it should be suitable for C621 systems with a PBaseAdress of 0x1810 (this appears to be the case for dual-socket Gigabyte C621-WD12… but adding the second socket if left as an exercise for the reader).
SSDT-CPU-WRAP3.aml was written for Supermicro X12SPA-TF (C621A, 3rd generation Xeon Scalable). (As of this writing, the board has not yet successfully booted OS X, but is getting ever closer.)
AMD users on B550 or A520 can use Acidanthera's SSDT-CPUR.aml.
Who needs such a SSDT?
The typical symptom is OS X verbose boot stalling just after loading the ACPI tables ("oops, there's no processor!"). The diagnostic is confirmed by dropping ACPI tables (OpenCore: use DEBUG version with Misc>Debug>SysReport:True; Clover: F4), decompiling DSDT.aml with MaciASL (or SSDT*.aml for AMD-based systems, which may not define CPUs in the DSDT) and looking for "Processor".
If you see something like
Processor (CP00, 0x00, 0x00000510, 0x06)
, you're fine.If you see something like
Code:
Device (CP00)
{
Name (_HID, "ACPI0007" /* Processor Device */) // _HID: Hardware ID
The issue first affected C621 systems for Xeon Scalable or Xeon W-3200 CPUs, possibly through a BIOS update switching from the old style to the new style. Recently, the issue creped on a C422 system for Xeon W-2000 through a BIOS update (namely Supermicro X11SRA-F on BIOS v.2.4). C621A systems for 3rd generation Xeon Scalable or Xeon W-3300 are affected from the outset.
On the consumer side, AMD B550 and A520 are affected (Acidanthera SSDT-CPUR), but curiously not X570 and earlier. Z690 for Alder Lake CPUs appears to be affected from the outset; Intel has likely taken the opportunity of this major architectural style to update its reference ACPI code.
Z590 and earlier are fine so far, and may remain so if manufacturers do not bother rewriting their ACPI tables for "old" boards. But there's a risk that the issue could propagate through BIOS updates. HEDT systems on X299 are possibly most at risk for this, seeing what happened on C422.
Virtualisation with HyperV is also affected (Acidanthera SSDT-HV-CPU).
How to adapt?
The base code unit is:
Code:
Processor (PR00, 0x00, 0x00000510, 0x06)
{
Return (\_SB.SCK0.CP00)
}
Processor (ProcessorName, ProcessorID, PBlockAddress, PBlockLength)
Obviously, ACPI path to the CPU is to be adapted; consumer platforms would not have multiple sockets in the way (_SB.CP## rather than _SB.SCK#.CP##).
Fake
Processor()
objects cannot have the same ProcessorName
as the CPU Device()
s. SSDT-CPU-WRAP and WRAP2 wrap CP00 to PR00; SSDT-CPU-WRAP3 wraps C000 to CP00. Adapt the names within Return()
if your motherboard defines CPUs with names other than CP## ('#' being any decimal or hexadecimal digit). If your processors are named PR##, pick another name for the fake Processor()
objects (beside PR##, CP## and C### are typical) and change the returned devices. The names are arbitrary, and the "numbers" in there are not a real counter, but it helps writing ("Find & Replace" is your friend!) and checking the SSDT, if the real and fake CPUs have the same "number" and this also matches ProcessorID
.ProcessorID
must be unique to each processor.Per the specification,
PBlockLength
only has two valid values: 0 or 6. For us, it will always be 6.Typical values for
PBlockAddress
would be 0x510, 0x1810, 0x810 (AMD) or 0x410 (old Intel). If the right value for the board is not known from a previous DSDT, it can be computed from the FACP.aml ACPI table: Add 0x10 to the hexadecimal value at offet 0x98.This indicates that the processor base address register is 0x1810 (0x1800 at offset 0x98, plus 0x10):
External()
references.What else?
When using a CPU wrapping SSDT, any further SSDT which refers to the CPU—typically SSDT-PLUG for power management on Intel platforms—should: 1) load after SSDT-CPU-WRAP; and 2) target the fake Processor() objects in SSDT-CPU-WRAP and not to to the real CPU Device() in the DSDT (so _SB.SCK0.PR00 with SSDT-CPU-WRAP(2) as provided, and not _SB.SCK0.CP00).
Thanks to @metacollin for identifying the issue and writing the first wrapping SSDT, to @yapan4 and @obus for their enduring moral support while I was hacking my C621 system, to @yapan4 and @ramazarusx for additional testing, to the zero-post user who tipped me on simplifying wrapping through a private message, to Pike R. Alpha for ssdtPRGen.sh and computing PBaseAddress, and to the Acidanthera team for their ACPI guides which greatly helped me grasp how to write SSDTs. (I've not yet adopted the ACPI specification as bedtime reading, but I've got a little closer…)
Attachments
Last edited: