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

Miguel Landaeta <[email protected]>
Newsgroups gmane.os.openbsd.tech
Message-ID <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.