Added support for bochs/kvm broken mptables, added pit reroute test, fixed imcr bug
authorPaul Pearce <pearce@eecs.berkeley.edu>
Wed, 29 Jul 2009 02:17:32 +0000 (19:17 -0700)
committerPaul Pearce <pearce@eecs.berkeley.edu>
Wed, 29 Jul 2009 02:17:32 +0000 (19:17 -0700)
Added support for mismatched pci bus and mptables settings. Specifically, fixed
an issue where bochs and kvm say there is no pci bus in the mptable, but have
a pci bus that is readable. The missing devices seem to show up as isa devices
in the mptable. This code trys to gracefully handle this. It is untested, in
terms of interrupts coming from pci devices in bochs/kvm, as we don't have a
way to generate such interrupts right now (quickly).

Added test_ioapic_pic_reroute() in testing.c that routes the pit to a core,
using the given ioapic_reroute_irq() interface, enables the pit, then unroutes
it using ioapic_unroute_irq().

Fixed a bug where the interupt mode bit mask in the mptable was a 16 bit field
instead of an 8 bit field.

include/arch/ioapic.h
include/mptables.h
include/testing.h
kern/src/ioapic.c
kern/src/testing.c

index 4e4ea1b..5033041 100644 (file)
@@ -20,6 +20,7 @@
 #define IOAPIC_PCI_FLAGS                       0xa0
 #define IOAPIC_ISA_FLAGS                       0x00
 #define IOAPIC_PIC_FLAGS                       0x07 // Not used. 
+#define IOAPIC_BROKEN_PCI_FLAGS                IOAPIC_ISA_FLAGS // No idea if this is correct, or it should be pci.
 
 #define IOAPIC_MAX_ID                          256
 
index 53041c8..f9a8e69 100644 (file)
@@ -18,7 +18,7 @@
 #define EBDA_SIZE              1024
 
 #define TOPOFMEM_POINTER       0x0413          /* BIOS: base memory size */
-#define IMCRP_MASK             0x8000
+#define IMCRP_MASK             0x80
 
 #define NUM_ENTRY_TYPES 5
 
index 33be6a5..702a3ff 100644 (file)
@@ -11,6 +11,7 @@
 
 void test_ipi_sending(void);
 void test_pic_reception(void);
+void test_ioapic_pic_reroute(void);
 void test_print_info(void);
 void test_barrier(void);
 void test_interrupts_irqsave(void);
index 5bb938e..773f750 100644 (file)
@@ -33,6 +33,8 @@ void ioapic_init() {
        memset(ioapic_redirects, 0x0, sizeof(ioapic_redirects));
        
        extern uint8_t num_cpus;
+       uint32_t inconsistent_pci_mappings = 0;  // Set high if we find inconsistent mappings between
+                                                                                        //  mptables and the pci bus.
        
        // Pull in all the stuff we need from mptables and the pci parsing
        extern pci_irq_entry irq_pci_map[NUM_IRQS];
@@ -54,8 +56,12 @@ void ioapic_init() {
                
                // MP Tables uses 8 bits to store the apic id. If our value is larger, is invalid entry
                // If we have a valid bus in the irq->pci map, and the pic->int entry doesnt exist, we have a major problem
-               if (dstApicID == 0xFFFF)
-                       panic("IRQ->PCI map and PCI->IOAPIC map are out of sync");
+               if (dstApicID == 0xFFFF) {
+                       if (!inconsistent_pci_mappings)
+                               cprintf("WARNING: INCONSISTENT IRQ->PCI AND PCI->IOAPIC MAPPINGS. Trying to cope...\n");
+                       inconsistent_pci_mappings++;
+                       continue;
+               }
                
                // If the lowest bit of the apic flags is set to 0, it means the ioapic is not usable.
                // We also use this to denote non-existent ioapics in our map
@@ -83,12 +89,29 @@ void ioapic_init() {
                        //  because this shouldnt really happen
                        panic("BOTH PCI AND ISA CLAIM TO SHARE AN IRQ. BAD");
                }
+               
+               // Code to check if this isa irq entry claims to be pci
+               uint16_t pci_bus = irq_pci_map[i].bus;
+               if (pci_bus != INVALID_BUS) {
+                       // PCI bus had an entry for this irq, but we didn't set it during our pci run
+                       //  This means it is likely a broken mptable implimentation. this happens on bochs and kvm
+                       //  lets just set the flags as if its broken, and move on. Hopefully it will work out.
+                       ioapic_redirects[i].ioapic_flags = IOAPIC_BROKEN_PCI_FLAGS;
+                       inconsistent_pci_mappings--;
+               }
+               else {
+                       ioapic_redirects[i].ioapic_flags = IOAPIC_ISA_FLAGS;
+               }
+               
 
                ioapic_redirects[i].ioapic_address = ioapic_entries[dstApicID].apicAddress;
                ioapic_redirects[i].ioapic_int = dstApicINT;
-               ioapic_redirects[i].ioapic_flags = IOAPIC_ISA_FLAGS;
        }
        
+       // Things didn't balance out when we scanned the isa bus for the missing pci devices. Die.
+       if (inconsistent_pci_mappings != 0) 
+               panic("FAILED TO COPE WITH INCONSISTENT IRQ->PCI AND PCI->IOAPIC MAPPINGS!");
+       
        // Support for other type of IRQ's goes here.
 }
 
index 9457568..c3916bb 100644 (file)
@@ -75,6 +75,22 @@ void test_pic_reception(void)
        while(1);
 }
 
+void test_ioapic_pic_reroute(void) 
+{
+       register_interrupt_handler(interrupt_handlers, 0x20, test_hello_world_handler, 0);
+       ioapic_route_irq(0, 3); 
+
+       cprintf("Starting pit on core 3....\n");
+       udelay(3000000);
+       pit_set_timer(100000,TIMER_RATEGEN); // totally arbitrary time
+       
+       udelay(3000000);
+       ioapic_unroute_irq(0);
+       udelay(300000);
+       cprintf("Masked pit. Waiting before return...\n");
+       udelay(30000000);
+}
+
 void test_print_info(void)
 {
        cprintf("\nCORE 0 asking all cores to print info:\n");