From a90b9b0221951bdc75d261200046eb62b5344b6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= Date: Fri, 23 Dec 2011 16:58:58 +0100 Subject: [PATCH] Guard against buggy PCI bridges * panic on pci controller init failure. No reason to continue just to crash later on. * guard against buggy or misconfigured bridges (like the VIA Apollo MVP3 in my K6-2) by limiting the recursion depth in FixupDevices and DiscoverBus. --- src/add-ons/kernel/bus_managers/pci/pci.cpp | 23 +++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/add-ons/kernel/bus_managers/pci/pci.cpp b/src/add-ons/kernel/bus_managers/pci/pci.cpp index 0c6ba9c58a..39146f8543 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci.cpp +++ b/src/add-ons/kernel/bus_managers/pci/pci.cpp @@ -469,6 +469,7 @@ pci_init(void) if (pci_controller_init() != B_OK) { TRACE(("PCI: pci_controller_init failed\n")); + panic("PCI: pci_controller_init failed\n"); return B_ERROR; } @@ -830,6 +831,15 @@ PCI::_FixupDevices(int domain, uint8 bus) FLOW("PCI: FixupDevices domain %u, bus %u\n", domain, bus); int maxBusDevices = _GetDomainData(domain)->max_bus_devices; + static int recursed = 0; + + if (recursed++ > 10) { + // guard against buggy chipsets + // XXX: is there any official limit ? + dprintf("PCI: FixupDevices: too many recursions (buggy chipset?)\n"); + recursed--; + return; + } for (int dev = 0; dev < maxBusDevices; dev++) { uint16 vendorId = ReadConfig(domain, bus, dev, 0, PCI_vendor_id, 2); @@ -857,9 +867,12 @@ PCI::_FixupDevices(int domain, uint8 bus) int busBehindBridge = ReadConfig(domain, bus, dev, function, PCI_secondary_bus, 1); + TRACE(("PCI: FixupDevices: checking bus %d behind %04x:%04x\n", + busBehindBridge, vendorId, deviceId)); _FixupDevices(domain, busBehindBridge); } } + recursed--; } @@ -981,6 +994,15 @@ PCI::_DiscoverBus(PCIBus *bus) FLOW("PCI: DiscoverBus, domain %u, bus %u\n", bus->domain, bus->bus); int maxBusDevices = _GetDomainData(bus->domain)->max_bus_devices; + static int recursed = 0; + + if (recursed++ > 10) { + // guard against buggy chipsets + // XXX: is there any official limit ? + dprintf("PCI: DiscoverBus: too many recursions (buggy chipset?)\n"); + recursed--; + return; + } for (int dev = 0; dev < maxBusDevices; dev++) { uint16 vendorID = ReadConfig(bus->domain, bus->bus, dev, 0, @@ -995,6 +1017,7 @@ PCI::_DiscoverBus(PCIBus *bus) if (bus->next) _DiscoverBus(bus->next); + recursed--; }