92 lines
4.2 KiB
Diff
92 lines
4.2 KiB
Diff
Subject: [PATCH] acpi: keep the CPU objects macOS needs without the FIRMWARE tell
|
|
|
|
Targets VMAware check: FIRMWARE (CPU hotplug I/O signature)
|
|
|
|
macOS references \_SB.CPUS.Cxxx from its own CpuPlug SSDT, so the guest needs
|
|
QEMU's build_cpus_aml output (the \_SB.PCI0.PRES controller and the \_SB.CPUS
|
|
Processor objects) or it hangs in ACPI namespace init. 01-firmware dropped that
|
|
block because build_cpus_aml emits the CPU-hotplug register region at I/O port
|
|
0x0CD8, which VMAware v2.8.1 FIRMWARE byte-matches as the WordData sequence
|
|
0x0B 0xD8 0x0C and flips to a QEMU verdict. HEAD has no such check.
|
|
|
|
This re-adds the block for every guest (no opt-in) and removes that one tell at
|
|
the source rather than removing the whole block:
|
|
|
|
- the controller _UID is renamed from "CPU Hotplug resources" to "Reserved
|
|
resources C", clearing the FIRMWARE string match the same way 01-firmware
|
|
renamed the other reserved-resource devices.
|
|
|
|
- the PRST OperationRegion base is emitted as Add(0x0C00, 0xD8) for a SystemIO
|
|
base. It evaluates to the identical 0x0CD8 at namespace load, so the port
|
|
QEMU decodes and the port OVMF's SMM code reads directly are both unchanged.
|
|
Relocating the base instead was tried and breaks every SMM/OVMF guest (macOS
|
|
hangs at boot, Windows too), because OVMF hardcodes 0x0CD8. Splitting the
|
|
operand keeps 0x0CD8 live but never places the three matched bytes next to
|
|
each other in the AML.
|
|
|
|
The _CRS IO descriptor keeps 0x0CD8 untouched: a small-resource IO descriptor
|
|
encodes its base as 0xD8 0x0C preceded by the 0x47/0x01 descriptor bytes, never
|
|
by 0x0B, so it is not the sequence the scanner matches.
|
|
|
|
Verified against QEMU 11.1.2: macOS boots to login and powers off via S5;
|
|
VMAware v2.8.1 and HEAD both read bare metal with FIRMWARE clear on the stealth
|
|
guest; Windows and Linux boot unchanged.
|
|
|
|
Applies to QEMU v11.1.2, on top of 01-firmware. From the source root:
|
|
patch -p1 < 11-macos-cpu-hotplug.patch
|
|
|
|
--- a/hw/i386/acpi-build.c
|
|
+++ b/hw/i386/acpi-build.c
|
|
@@ -1002,6 +1002,16 @@
|
|
}
|
|
aml_append(dsdt, scope);
|
|
|
|
+ {
|
|
+ CPUHotplugFeatures opts = {
|
|
+ .acpi_1_compatible = true,
|
|
+ .smi_path = pm->smi_on_cpuhp ? "\\_SB.PCI0.SMI0.SMIC" : NULL,
|
|
+ .fw_unplugs_cpu = pm->smi_on_cpu_unplug,
|
|
+ };
|
|
+ build_cpus_aml(dsdt, machine, opts, pc_madt_cpu_entry,
|
|
+ pm->cpu_hp_io_base, "\\_SB.PCI0", "\\_GPE._E02",
|
|
+ AML_SYSTEM_IO);
|
|
+ }
|
|
|
|
crs_range_set_init(&crs_range_set);
|
|
bus = PC_MACHINE(machine)->pcibus;
|
|
--- a/hw/acpi/cpu.c
|
|
+++ b/hw/acpi/cpu.c
|
|
@@ -363,7 +363,7 @@
|
|
aml_append(cpu_ctrl_dev,
|
|
aml_name_decl("_HID", aml_eisaid("PNP0A06")));
|
|
aml_append(cpu_ctrl_dev,
|
|
- aml_name_decl("_UID", aml_string("CPU Hotplug resources")));
|
|
+ aml_name_decl("_UID", aml_string("Reserved resources C")));
|
|
aml_append(cpu_ctrl_dev, aml_mutex(CPU_LOCK, 0));
|
|
|
|
assert((rs == AML_SYSTEM_IO) || (rs == AML_SYSTEM_MEMORY));
|
|
@@ -379,9 +379,21 @@
|
|
|
|
aml_append(cpu_ctrl_dev, aml_name_decl("_CRS", crs));
|
|
|
|
- /* declare CPU hotplug MMIO region with related access fields */
|
|
+ /*
|
|
+ * Declare the CPU hotplug register block. The region is at the same
|
|
+ * fixed base QEMU decodes and firmware (OVMF SMM) reads directly, so
|
|
+ * that is unchanged. Only the base operand's AML encoding is split
|
|
+ * across an Add() for a SystemIO base: emitting the 16-bit port as a
|
|
+ * single WordData leaks the exact three-byte sequence a VM-detection
|
|
+ * scanner byte-matches on. The Add() evaluates to the identical base
|
|
+ * at namespace load but never places those bytes contiguously.
|
|
+ */
|
|
+ Aml *region_base = (rs == AML_SYSTEM_IO)
|
|
+ ? aml_add(aml_int(base_addr & 0xff00),
|
|
+ aml_int(base_addr & 0x00ff), NULL)
|
|
+ : aml_int(base_addr);
|
|
aml_append(cpu_ctrl_dev,
|
|
- aml_operation_region("PRST", rs, aml_int(base_addr),
|
|
+ aml_operation_region("PRST", rs, region_base,
|
|
ACPI_CPU_HOTPLUG_REG_LEN));
|
|
|
|
field = aml_field("PRST", AML_BYTE_ACC, AML_NOLOCK,
|