[haiku-commits] r41415 - haiku/trunk/src/system/kernel/arch/x86

  • From: mmlr@xxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 10 May 2011 11:29:57 +0200 (CEST)

Author: mmlr
Date: 2011-05-10 11:29:57 +0200 (Tue, 10 May 2011)
New Revision: 41415
Changeset: https://dev.haiku-os.org/changeset/41415

Modified:
   haiku/trunk/src/system/kernel/arch/x86/arch_int.cpp
   haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.cpp
   haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.h
Log:
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).


Modified: haiku/trunk/src/system/kernel/arch/x86/arch_int.cpp
===================================================================
--- haiku/trunk/src/system/kernel/arch/x86/arch_int.cpp 2011-05-10 08:50:57 UTC 
(rev 41414)
+++ haiku/trunk/src/system/kernel/arch/x86/arch_int.cpp 2011-05-10 09:29:57 UTC 
(rev 41415)
@@ -651,7 +651,8 @@
        }
 
        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);

Modified: haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.cpp
===================================================================
--- haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.cpp        
2011-05-10 08:50:57 UTC (rev 41414)
+++ haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.cpp        
2011-05-10 09:29:57 UTC (rev 41415)
@@ -254,6 +254,11 @@
                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 @@
                // 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 @@
 }
 
 
-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 @@
        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 @@
                        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 @@
                        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 @@
                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 @@
        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 @@
                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 @@
                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;
 }
 

Modified: haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.h
===================================================================
--- haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.h  2011-05-10 
08:50:57 UTC (rev 41414)
+++ haiku/trunk/src/system/kernel/arch/x86/irq_routing_table.h  2011-05-10 
09:29:57 UTC (rev 41415)
@@ -71,7 +71,8 @@
 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);
 


Other related posts:

  • » [haiku-commits] r41415 - haiku/trunk/src/system/kernel/arch/x86 - mmlr