Index | Thread | Search

From:
Miguel Landaeta <miguel@miguel.cc>
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

Download raw body.

Thread
  • Miguel Landaeta:

    [3/5] acpimadt: fix null dereference and mp_busses misuse without I/O APIC

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