From ad1757252e43d6fc2e682df1d95b1d9f3a0f1fbd Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Tue, 10 May 2011 09:29:57 +0000 Subject: [PATCH] Check hardwired and chosen IRQs against the maximum we can address. Try to fail gracefully in such cases (resulting in the IO-APIC not being used). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41415 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/arch/x86/arch_int.cpp | 3 +- .../kernel/arch/x86/irq_routing_table.cpp | 56 ++++++++++++++----- .../kernel/arch/x86/irq_routing_table.h | 3 +- 3 files changed, 46 insertions(+), 16 deletions(-) diff --git a/src/system/kernel/arch/x86/arch_int.cpp b/src/system/kernel/arch/x86/arch_int.cpp index d57a7cf711..eda2cfdba5 100644 --- a/src/system/kernel/arch/x86/arch_int.cpp +++ b/src/system/kernel/arch/x86/arch_int.cpp @@ -651,7 +651,8 @@ ioapic_init(kernel_args* args) } IRQRoutingTable table; - status = read_irq_routing_table(acpiModule, &table); + status = read_irq_routing_table(acpiModule, &table, + sIOAPICMaxRedirectionEntry + 1); if (status != B_OK) { dprintf("reading IRQ routing table failed, not configuring ioapic.\n"); acpi_set_interrupt_model(acpiModule, ACPI_INTERRUPT_MODEL_PIC); diff --git a/src/system/kernel/arch/x86/irq_routing_table.cpp b/src/system/kernel/arch/x86/irq_routing_table.cpp index 7aead229ae..3b616a8ce4 100644 --- a/src/system/kernel/arch/x86/irq_routing_table.cpp +++ b/src/system/kernel/arch/x86/irq_routing_table.cpp @@ -254,6 +254,11 @@ configure_link_devices(acpi_module_info* acpi, IRQRoutingTable& routingTable, uint16 bestIRQUsage = UINT16_MAX; for (int j = 0; j < link->possible_irqs.Count(); j++) { irq_descriptor& possibleIRQ = link->possible_irqs.ElementAt(j); + if (possibleIRQ.irq >= maxIRQCount) { + // we can't address this pin + continue; + } + if (possibleIRQ.irq < kMaxISAInterrupts && (validForPCI & (1 << possibleIRQ.irq)) == 0) { // better avoid that if possible @@ -269,6 +274,12 @@ configure_link_devices(acpi_module_info* acpi, IRQRoutingTable& routingTable, // pick that one and update the counts irq_descriptor& chosenDescriptor = link->possible_irqs.ElementAt(bestIRQIndex); + if (chosenDescriptor.irq >= maxIRQCount) { + panic("chosen irq %u is not addressable (max %lu)", + chosenDescriptor.irq, maxIRQCount); + return B_ERROR; + } + irqUsage[chosenDescriptor.irq] += link->used_by.Count(); status_t status = set_current_irq(acpi, link->handle, chosenDescriptor); @@ -368,10 +379,10 @@ handle_routing_table_entry(acpi_module_info* acpi, pci_module_info* pci, } -static void +static status_t read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci, acpi_handle device, const pci_address& parentAddress, - IRQRoutingTable* table, bool rootBridge) + IRQRoutingTable* table, bool rootBridge, uint32 maxIRQCount) { acpi_data buffer; buffer.pointer = NULL; @@ -379,7 +390,7 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci, status_t status = acpi->get_irq_routing_table(device, &buffer); if (status != B_OK) { // simply not a bridge - return; + return B_OK; } TRACE("found irq routing table\n"); @@ -401,7 +412,7 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci, pciAddress.device, pciAddress.function, PCI_secondary_bus, 1); if (secondaryBus == 255) { // The bus below this bridge is inactive, nothing to do. - return; + return B_OK; } // The secondary bus cannot be the same as the current one. @@ -409,7 +420,7 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci, dprintf("invalid secondary bus %u on primary bus %u," " can't configure irq routing of devices below\n", secondaryBus, parentAddress.bus); - return; + return B_ERROR; } // Everything below is now on the secondary bus. @@ -421,8 +432,16 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci, irq_routing_entry irqEntry; status = handle_routing_table_entry(acpi, pci, acpiTable, pciAddress, irqEntry); - if (status == B_OK) + if (status == B_OK) { + if (irqEntry.source == NULL && irqEntry.irq >= maxIRQCount) { + dprintf("hardwired irq %u not addressable (max %lu)\n", + irqEntry.irq, maxIRQCount); + free(buffer.pointer); + return B_ERROR; + } + table->PushBack(irqEntry); + } acpiTable = (acpi_pci_routing_table*)((uint8*)acpiTable + acpiTable->Length); @@ -434,9 +453,10 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci, acpi_data pathBuffer; pathBuffer.pointer = NULL; pathBuffer.length = ACPI_ALLOCATE_BUFFER; - if (acpi->ns_handle_to_pathname(device, &pathBuffer) != B_OK) { + status = acpi->ns_handle_to_pathname(device, &pathBuffer); + if (status != B_OK) { dprintf("failed to resolve handle to path\n"); - return; + return status; } char childName[255]; @@ -448,20 +468,24 @@ read_irq_routing_table_recursive(acpi_module_info* acpi, pci_module_info* pci, status = acpi->get_handle(NULL, childName, &childHandle); if (status != B_OK) { dprintf("failed to get handle to child \"%s\"\n", childName); - continue; + break; } TRACE("recursing down to child \"%s\"\n", childName); - read_irq_routing_table_recursive(acpi, pci, childHandle, pciAddress, - table, false); + status = read_irq_routing_table_recursive(acpi, pci, childHandle, + pciAddress, table, false, maxIRQCount); + if (status != B_OK) + break; } free(pathBuffer.pointer); + return status; } status_t -read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable* table) +read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable* table, + uint32 maxIRQCount) { char rootPciName[255]; acpi_handle rootPciHandle; @@ -494,10 +518,14 @@ read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable* table) return status; } - read_irq_routing_table_recursive(acpi, pci, rootPciHandle, rootPciAddress, - table, true); + status = read_irq_routing_table_recursive(acpi, pci, rootPciHandle, + rootPciAddress, table, true, maxIRQCount); put_module(B_PCI_MODULE_NAME); + + if (status != B_OK) + return status; + return table->Count() > 0 ? B_OK : B_ERROR; } diff --git a/src/system/kernel/arch/x86/irq_routing_table.h b/src/system/kernel/arch/x86/irq_routing_table.h index 71b8b6e64b..01cf7975bd 100644 --- a/src/system/kernel/arch/x86/irq_routing_table.h +++ b/src/system/kernel/arch/x86/irq_routing_table.h @@ -71,7 +71,8 @@ void print_irq_descriptor(irq_descriptor* descriptor); void print_irq_routing_table(IRQRoutingTable* table); -status_t read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable* table); +status_t read_irq_routing_table(acpi_module_info* acpi, IRQRoutingTable* table, + uint32 maxIRQCount); status_t enable_irq_routing(acpi_module_info* acpi, IRQRoutingTable& routingTable, uint32 maxIRQCount);