Handle all APIC IRQ redirects specified in MADT

This commit is contained in:
Josh Holtrop 2023-11-07 17:19:56 -05:00
parent 31bf82e2ae
commit f2839cdd0f

View File

@ -17,7 +17,7 @@ struct Apic
private enum DEFAULT_IO_APIC_ADDRESS = 0xFEC0_0000u; private enum DEFAULT_IO_APIC_ADDRESS = 0xFEC0_0000u;
private enum uint PERIODIC_MODE = 0x2_0000u; private enum uint PERIODIC_MODE = 0x2_0000u;
private enum ulong IRQ_PIT = 2u; private enum ulong IRQ_PIT = 0u;
private enum ulong IRQ_RTC = 8u; private enum ulong IRQ_RTC = 8u;
/** /**
@ -180,6 +180,14 @@ struct Apic
case Entry.IO_APIC_INTERRUPT_SOURCE_OVERRIDE: case Entry.IO_APIC_INTERRUPT_SOURCE_OVERRIDE:
Entry2 * e = cast(Entry2 *)entry; Entry2 * e = cast(Entry2 *)entry;
if (e.global_system_interrupt < Idt.INT_APIC_COUNT)
{
irq_redirects[e.irq_source] = cast(ubyte)e.global_system_interrupt;
}
else
{
Klog.writefln("Warning: unexpected interrupt source override global system interrupt value: %u", e.global_system_interrupt);
}
if (DEBUG) if (DEBUG)
{ {
Klog.writefln(" Bus %u IRQ %u GSI %u Flags: 0x%x", Klog.writefln(" Bus %u IRQ %u GSI %u Flags: 0x%x",
@ -296,8 +304,11 @@ struct Apic
ApicRegister data; ApicRegister data;
} }
alias ISRHandler = void function();
private static __gshared ApicRegisters * apic_registers; private static __gshared ApicRegisters * apic_registers;
private static __gshared IoApicRegisters * io_apic_registers; private static __gshared IoApicRegisters * io_apic_registers;
private static __gshared ISRHandler[Idt.INT_APIC_COUNT] irq_handlers;
private static __gshared ubyte[Idt.INT_APIC_COUNT] irq_redirects;
/** /**
* Initialize APIC. * Initialize APIC.
@ -306,6 +317,10 @@ struct Apic
{ {
Klog.writefln("\a3Initializing APIC"); Klog.writefln("\a3Initializing APIC");
io_apic_registers = cast(IoApicRegisters *)DEFAULT_IO_APIC_ADDRESS; io_apic_registers = cast(IoApicRegisters *)DEFAULT_IO_APIC_ADDRESS;
for (ubyte i = 0u; i < Idt.INT_APIC_COUNT; i++)
{
irq_redirects[i] = i;
}
MADT * madt = cast(MADT *)Acpi.get_table("APIC"); MADT * madt = cast(MADT *)Acpi.get_table("APIC");
madt.scan(); madt.scan();
Klog.writefln("APIC found at %p", apic_registers); Klog.writefln("APIC found at %p", apic_registers);
@ -321,21 +336,23 @@ struct Apic
apic_registers.lvt_lint[0].value = Idt.INT_APIC_LINT0; apic_registers.lvt_lint[0].value = Idt.INT_APIC_LINT0;
apic_registers.lvt_lint[1].value = Idt.INT_APIC_LINT1; apic_registers.lvt_lint[1].value = Idt.INT_APIC_LINT1;
/* Enable PIT interrupt. */ /* Enable PIT interrupt. */
configure_io_apic_irq(IRQ_PIT, Idt.INT_APIC_BASE + IRQ_PIT); configure_io_apic_irq(IRQ_PIT, &Pit.isr);
/* Enable RTC interrupt. */ /* Enable RTC interrupt. */
configure_io_apic_irq(IRQ_RTC, Idt.INT_APIC_BASE + IRQ_RTC); configure_io_apic_irq(IRQ_RTC, &Rtc.isr);
} }
/** /**
* Configure routing for an I/O APIC IRQ. * Configure routing for an I/O APIC IRQ.
*/ */
private static void configure_io_apic_irq(size_t io_apic_irq, size_t interrupt_id) private static void configure_io_apic_irq(size_t orig_irq, ISRHandler isr_handler)
{ {
ulong entry = interrupt_id; size_t io_apic_irq = irq_redirects[orig_irq];
ulong entry = Idt.INT_APIC_BASE + io_apic_irq;
io_apic_registers.address.value = cast(uint)(0x10u + io_apic_irq * 2u); io_apic_registers.address.value = cast(uint)(0x10u + io_apic_irq * 2u);
io_apic_registers.data.value = entry & 0xFFFF_FFFFu; io_apic_registers.data.value = entry & 0xFFFF_FFFFu;
io_apic_registers.address.value = cast(uint)(0x10u + io_apic_irq * 2u + 1u); io_apic_registers.address.value = cast(uint)(0x10u + io_apic_irq * 2u + 1u);
io_apic_registers.data.value = entry >> 32u; io_apic_registers.data.value = entry >> 32u;
irq_handlers[io_apic_irq] = isr_handler;
} }
/** /**
@ -351,19 +368,14 @@ struct Apic
*/ */
public static void isr(ulong vector) public static void isr(ulong vector)
{ {
switch (vector) ulong io_apic_irq = vector - Idt.INT_APIC_BASE;
if ((io_apic_irq < Idt.INT_APIC_COUNT) && (irq_handlers[io_apic_irq] != null))
{
irq_handlers[io_apic_irq]();
}
else
{ {
case Idt.INT_APIC_BASE + IRQ_PIT:
Pit.isr();
break;
case Idt.INT_APIC_BASE + IRQ_RTC:
Rtc.isr();
break;
default:
Klog.writefln("Unhandled APIC ISR %u", vector); Klog.writefln("Unhandled APIC ISR %u", vector);
break;
} }
eoi(); eoi();
} }