From: Miguel Landaeta Subject: [3/5] acpimadt: fix null dereference and mp_busses misuse without I/O APIC To: tech@openbsd.org Date: Tue, 9 Jun 2026 13:27:11 +0000 This is a series of commits to expose ACPI tables to vmd guests. These were committed and tested individually. They can be reviewed in their entirety here: https://github.com/openbsd/src/compare/master...nomadium:src:add-support-for-acpi-in-vmd.patch --- sys/dev/acpi/acpimadt.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/sys/dev/acpi/acpimadt.c b/sys/dev/acpi/acpimadt.c index 275f2b1e6ce..99832a2f125 100644 --- a/sys/dev/acpi/acpimadt.c +++ b/sys/dev/acpi/acpimadt.c @@ -198,6 +198,7 @@ acpimadt_attach(struct device *parent, struct device *self, void *aux) struct mp_intr_map *map; struct ioapic_softc *apic; int nlapic_nmis = 0; + int nioapic = 0; int pin; /* Do some sanity checks before committing to run in APIC mode. */ @@ -218,8 +219,6 @@ acpimadt_attach(struct device *parent, struct device *self, void *aux) aml_evalname(acpi_sc, NULL, "\\_PIC", 1, &arg, NULL); - mp_busses = acpimadt_busses; - mp_nbusses = nitems(acpimadt_busses); mp_isa_bus = &acpimadt_isa_bus; lapic_boot_init(madt->local_apic_address); @@ -292,6 +291,7 @@ acpimadt_attach(struct device *parent, struct device *self, void *aux) aaa.apic_vecbase = entry->madt_ioapic.global_int_base; config_found(mainbus, &aaa, acpimadt_print); + nioapic++; break; case ACPI_MADT_LAPIC_NMI: nlapic_nmis++; @@ -337,6 +337,18 @@ acpimadt_attach(struct device *parent, struct device *self, void *aux) addr += entry->madt_lapic.length; } + /* + * Only switch to APIC-mode bus tables when at least one I/O APIC + * was found. Without an I/O APIC, PCI interrupt routing must use + * the legacy PIC path; setting mp_busses to a non-NULL empty table + * would cause pci_intr_map to search the table, find nothing, and + * fail instead of falling back to the IRQ line. + */ + if (nioapic) { + mp_busses = acpimadt_busses; + mp_nbusses = nitems(acpimadt_busses); + } + mp_intrs = mallocarray(nlapic_nmis, sizeof(struct mp_intr_map), M_DEVBUF, M_NOWAIT); if (mp_intrs == NULL) @@ -361,6 +373,8 @@ acpimadt_attach(struct device *parent, struct device *self, void *aux) pin = entry->madt_override.global_int; apic = ioapic_find_bybase(pin); + if (apic == NULL) + break; map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT | M_ZERO); if (map == NULL) @@ -443,6 +457,8 @@ acpimadt_attach(struct device *parent, struct device *self, void *aux) continue; apic = ioapic_find_bybase(pin); + if (apic == NULL) + continue; map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT | M_ZERO); if (map == NULL) -- 2.54.0