mptable and madt irq override
authorKevin O'Connor <kevin@koconnor.net>
Wed, 29 Jul 2009 23:20:03 +0000 (19:20 -0400)
committerKevin O'Connor <kevin@koconnor.net>
Wed, 29 Jul 2009 23:20:03 +0000 (19:20 -0400)
Implement irq override support for timer interrupts. This matches what
QEMU+BOCHS has been doing for the latest 8 months, and is also what
real hardware does.

Windows expects this according to Beth Kon.

Based on patch by Jes Sorensen <jes@sgi.com>

src/acpi.c
src/mptable.c
src/util.h

index bafdd6b9ddcb5361271a9083d515fff95b230d4c..ef4eaf938f41cb3d3560189dce7f001e096bf8b5 100644 (file)
@@ -331,7 +331,16 @@ build_madt(struct rsdt_descriptor_rev1 *rsdt)
     io_apic->interrupt = cpu_to_le32(0);
 
     struct madt_intsrcovr *intsrcovr = (void*)&io_apic[1];
-    for (i = 0; i < 16; i++) {
+    if (irq0override) {
+        memset(intsrcovr, 0, sizeof(*intsrcovr));
+        intsrcovr->type   = APIC_XRUPT_OVERRIDE;
+        intsrcovr->length = sizeof(*intsrcovr);
+        intsrcovr->source = 0;
+        intsrcovr->gsi    = 2;
+        intsrcovr->flags  = 0; /* conforms to bus specifications */
+        intsrcovr++;
+    }
+    for (i = 1; i < 16; i++) {
         if (!(PCI_ISA_IRQ_MASK & (1 << i)))
             /* No need for a INT source override structure. */
             continue;
index 5758b28de5cac30fdc09777bbafe1b0c37dbc8ff..dd3b10afe2eff281ca07c2b55c91b376ced1ec5a 100644 (file)
 #include "config.h" // CONFIG_*
 #include "mptable.h" // MPTABLE_SIGNATURE
 
+#if CONFIG_KVM
+int irq0override = 1;
+#else
+int irq0override = 0;
+#endif
+
 void
 mptable_init(void)
 {
@@ -48,7 +54,6 @@ mptable_init(void)
     // Config structure.
     memset(config, 0, sizeof(*config));
     config->signature = MPCONFIG_SIGNATURE;
-    config->length = length - sizeof(*floating);
     config->spec = 4;
     memcpy(config->oemid, CONFIG_CPUNAME8, sizeof(config->oemid));
     memcpy(config->productid, "0.1         ", sizeof(config->productid));
@@ -94,19 +99,28 @@ mptable_init(void)
     ioapic->apicaddr = BUILD_IOAPIC_ADDR;
 
     /* irqs */
-    struct mpt_intsrc *intsrcs = (void *)&ioapic[1];
-    for(i = 0; i < 16; i++) {
-        struct mpt_intsrc *isrc = &intsrcs[i];
-        memset(isrc, 0, sizeof(*isrc));
-        isrc->type = MPT_TYPE_INTSRC;
-        isrc->srcbusirq = i;
-        isrc->dstapic = ioapic_id;
-        isrc->dstirq = i;
+    struct mpt_intsrc *intsrc = (void*)&ioapic[1];
+    for (i = 0; i < 16; i++) {
+        memset(intsrc, 0, sizeof(*intsrc));
+        intsrc->type = MPT_TYPE_INTSRC;
+        intsrc->srcbusirq = i;
+        intsrc->dstapic = ioapic_id;
+        intsrc->dstirq = i;
+        if (irq0override) {
+            /* Destination 2 is covered by irq0->inti2 override (i ==
+               0). Source IRQ 2 is unused */
+            if (i == 0)
+                intsrc->dstirq = 2;
+            else if (i == 2)
+                intsrc--;
+        }
+        intsrc++;
     }
 
     // Set checksum.
+    config->length = (void*)intsrc - (void*)config;
     config->checksum -= checksum(config, config->length);
 
     dprintf(1, "MP table addr=%p MPC table addr=%p size=%d\n",
-            floating, config, length);
+            floating, config, config->length);
 }
index 22b58bcc9dcdfefcce6726c66ffcf33a746f07e4..6cdcffef782eb32f1bd159976a2130bf68d53ba7 100644 (file)
@@ -244,4 +244,7 @@ void reset_vector() __attribute__ ((noreturn));
 // misc.c
 extern u8 BiosChecksum;
 
+// mptable.c
+extern int irq0override;
+
 #endif // util.h