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. Signed-off-by: Jes Sorensen --- src/acpi.c | 12 ++++++++++++ src/mptable.c | 26 +++++++++++++++++++++++--- src/util.h | 3 +++ 3 files changed, 38 insertions(+), 3 deletions(-) Index: seabios/src/acpi.c =================================================================== --- seabios.orig/src/acpi.c +++ seabios/src/acpi.c @@ -331,6 +331,18 @@ build_madt(struct rsdt_descriptor_rev1 * io_apic->interrupt = cpu_to_le32(0); struct madt_intsrcovr *intsrcovr = (void*)&io_apic[1]; + + 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++; + madt_size += sizeof(struct madt_intsrcovr); + } + for (i = 0; i < 16; i++) { if (!(PCI_ISA_IRQ_MASK & (1 << i))) /* No need for a INT source override structure. */ Index: seabios/src/mptable.c =================================================================== --- seabios.orig/src/mptable.c +++ seabios/src/mptable.c @@ -10,6 +10,12 @@ #include "config.h" // CONFIG_* #include "mptable.h" // MPTABLE_SIGNATURE +#if CONFIG_KVM +int irq0override = 1; +#else +int irq0override = 0; +#endif + void mptable_init(void) { @@ -28,7 +34,10 @@ mptable_init(void) + sizeof(struct mpt_cpu) * smp_cpus + sizeof(struct mpt_bus) + sizeof(struct mpt_ioapic) - + sizeof(struct mpt_intsrc) * 16); + + sizeof(struct mpt_intsrc) * 15); + if (!irq0override) + length += sizeof(struct mpt_intsrc); + void *start = malloc_fseg(length); if (!start) { dprintf(1, "No room for MPTABLE!\n"); @@ -95,13 +104,24 @@ mptable_init(void) /* irqs */ struct mpt_intsrc *intsrcs = (void *)&ioapic[1]; + int j = 0; for(i = 0; i < 16; i++) { - struct mpt_intsrc *isrc = &intsrcs[i]; + struct mpt_intsrc *isrc; + /* One entry per ioapic interrupt destination. Destination 2 is covered + by irq0->inti2 override (i == 0). Source IRQ 2 is unused */ + if (irq0override && i == 2) { + j = 1; + continue; + } + isrc = &intsrcs[i - j]; memset(isrc, 0, sizeof(*isrc)); isrc->type = MPT_TYPE_INTSRC; isrc->srcbusirq = i; isrc->dstapic = ioapic_id; - isrc->dstirq = i; + if (irq0override && i == 0) + isrc->dstirq = 2; + else + isrc->dstirq = i; } // Set checksum. Index: seabios/src/util.h =================================================================== --- seabios.orig/src/util.h +++ seabios/src/util.h @@ -244,4 +244,7 @@ void reset_vector() __attribute__ ((nore // misc.c extern u8 BiosChecksum; +// mptable.c +extern int irq0override; + #endif // util.h