0737d6184d6f32f6a8d5302e96b8f4c40189d810 — Noam Preil 21 days ago 45697b7 preVM
Cleanup interrupts (move from boatload of inline asm to comptime loop)
1 files changed, 77 insertions(+), 380 deletions(-)

M src/interrupts.zig
M src/interrupts.zig => src/interrupts.zig +77 -380
@@ 6,7 6,8 @@ const IDTEntry = packed struct {
     zero: u8,
     type_attr: u8,
     offset_upper: u16,
-    fn Encode(function_address: u32) IDTEntry {
+    fn Encode(function: ?nakedcc fn() void) IDTEntry {
+        const function_address = @ptrToInt(function);
         return IDTEntry{
             .offset_lower = @intCast(u16, function_address & 0xFFFF),
             // The code selector set in the GDT


@@ 45,9 46,9 @@ const PIC_REGISTER_IRR = 0x02;
 const PIC_REGISTER_ISR = 0x03;
 
 fn pic_read_register(register: u8) u16 {
-    io.outb(PIC1_COMMAND, register | (1<<3));
-    io.outb(PIC2_COMMAND, register | (1<<3));
-    return (@intCast(u16,io.inb(PIC2_COMMAND)) << 8) | io.inb(PIC1_COMMAND);
+    io.outb(PIC1_COMMAND, register | (1 << 3));
+    io.outb(PIC2_COMMAND, register | (1 << 3));
+    return (@intCast(u16, io.inb(PIC2_COMMAND)) << 8) | io.inb(PIC1_COMMAND);
 }
 
 const ICW1_ICW4 = 0x01; // ICW4 (not) needed


@@ 63,49 64,24 @@ const ICW4_BUF_MASTER = 0x0C; // Buffered mode/master
 const ICW4_SFNM = 0x10; // Special fully nested (not)
 
 pub fn setup() void {
-    for (IDT[0..]) |*entry| {
-        entry.* = @bitCast(IDTEntry, u64(0));
-    }
     for (interrupt_handlers[0..]) |*handler| {
         handler.* = null;
     }
+    comptime var index: u8 = 0;
+    inline while (index < 32) : (index += 1) {
+        IDT[index] = IDTEntry.Encode(getInterruptStub(false, index));
+    }
+    inline while (index < 48) : (index += 1) {
+        IDT[index] = IDTEntry.Encode(getInterruptStub(true, index - 32));
+    }
+    for (IDT[47..]) |*entry| {
+        entry.* = @bitCast(IDTEntry, u64(0));
+    }
     IDTD = IDTDescriptor{
         .size = 256 * @sizeOf(IDTEntry) - 1,
         .base = @intCast(u32, @ptrToInt(&IDT)),
     };
     asm volatile ("lidt IDTD");
-    IDT[0] = IDTEntry.Encode(@ptrToInt(isr0));
-    IDT[1] = IDTEntry.Encode(@ptrToInt(isr1));
-    IDT[2] = IDTEntry.Encode(@ptrToInt(isr2));
-    IDT[3] = IDTEntry.Encode(@ptrToInt(isr3));
-    IDT[4] = IDTEntry.Encode(@ptrToInt(isr4));
-    IDT[5] = IDTEntry.Encode(@ptrToInt(isr5));
-    IDT[6] = IDTEntry.Encode(@ptrToInt(isr6));
-    IDT[7] = IDTEntry.Encode(@ptrToInt(isr7));
-    IDT[8] = IDTEntry.Encode(@ptrToInt(isr8));
-    IDT[9] = IDTEntry.Encode(@ptrToInt(isr9));
-    IDT[10] = IDTEntry.Encode(@ptrToInt(isr10));
-    IDT[11] = IDTEntry.Encode(@ptrToInt(isr11));
-    IDT[12] = IDTEntry.Encode(@ptrToInt(isr12));
-    IDT[13] = IDTEntry.Encode(@ptrToInt(isr13));
-    IDT[14] = IDTEntry.Encode(@ptrToInt(isr14));
-    IDT[15] = IDTEntry.Encode(@ptrToInt(isr15));
-    IDT[16] = IDTEntry.Encode(@ptrToInt(isr16));
-    IDT[17] = IDTEntry.Encode(@ptrToInt(isr17));
-    IDT[18] = IDTEntry.Encode(@ptrToInt(isr18));
-    IDT[19] = IDTEntry.Encode(@ptrToInt(isr19));
-    IDT[20] = IDTEntry.Encode(@ptrToInt(isr20));
-    IDT[21] = IDTEntry.Encode(@ptrToInt(isr21));
-    IDT[22] = IDTEntry.Encode(@ptrToInt(isr22));
-    IDT[23] = IDTEntry.Encode(@ptrToInt(isr23));
-    IDT[24] = IDTEntry.Encode(@ptrToInt(isr24));
-    IDT[25] = IDTEntry.Encode(@ptrToInt(isr25));
-    IDT[26] = IDTEntry.Encode(@ptrToInt(isr26));
-    IDT[27] = IDTEntry.Encode(@ptrToInt(isr27));
-    IDT[28] = IDTEntry.Encode(@ptrToInt(isr28));
-    IDT[29] = IDTEntry.Encode(@ptrToInt(isr29));
-    IDT[30] = IDTEntry.Encode(@ptrToInt(isr30));
-    IDT[31] = IDTEntry.Encode(@ptrToInt(isr31));
     io.outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4);
     io.wait();
     io.outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);


@@ 129,22 105,6 @@ pub fn setup() void {
     // Enable all IRQs
     io.outb(PIC1_DATA, 0);
     io.outb(PIC2_DATA, 0);
-    IDT[32] = IDTEntry.Encode(@ptrToInt(irq0));
-    IDT[33] = IDTEntry.Encode(@ptrToInt(irq1));
-    IDT[34] = IDTEntry.Encode(@ptrToInt(irq2));
-    IDT[35] = IDTEntry.Encode(@ptrToInt(irq3));
-    IDT[36] = IDTEntry.Encode(@ptrToInt(irq4));
-    IDT[37] = IDTEntry.Encode(@ptrToInt(irq5));
-    IDT[38] = IDTEntry.Encode(@ptrToInt(irq6));
-    IDT[39] = IDTEntry.Encode(@ptrToInt(irq7));
-    IDT[40] = IDTEntry.Encode(@ptrToInt(irq8));
-    IDT[41] = IDTEntry.Encode(@ptrToInt(irq9));
-    IDT[42] = IDTEntry.Encode(@ptrToInt(irq10));
-    IDT[43] = IDTEntry.Encode(@ptrToInt(irq11));
-    IDT[44] = IDTEntry.Encode(@ptrToInt(irq12));
-    IDT[45] = IDTEntry.Encode(@ptrToInt(irq13));
-    IDT[46] = IDTEntry.Encode(@ptrToInt(irq14));
-    IDT[47] = IDTEntry.Encode(@ptrToInt(irq15));
 }
 
 const InterruptState = packed struct {


@@ 165,12 125,21 @@ const InterruptState = packed struct {
 };
 
 const ExceptionContext = struct {
+    edi: u32,
+    esi: u32,
+    ebp: u32,
+    esp: u32,
+    ebx: u32,
+    edx: u32,
+    ecx: u32,
+    eax: u32,
     id: u32,
+    error_code: u32,
     eip: u32,
     cs: u32,
     eflags: u32,
     useresp: u32,
-    ss: u32
+    ss: u32,
 };
 
 export fn exception_handler(context: *ExceptionContext) noreturn {


@@ 179,10 148,10 @@ export fn exception_handler(context: *ExceptionContext) noreturn {
         @import("root").print("Invalid opcode: 0x{x} at 0x{x}\n", instr.*, context.eip);
     }
     @import("std").debug.dumpStackTraceFromBase(@intCast(usize, context.eip), 0);
-    while(true){}
+    while (true) {}
 }
 
-const IRQHandler : type = fn()void;
+const IRQHandler: type = fn () void;
 var interrupt_handlers: [32]?*const IRQHandler = undefined;
 
 pub fn set_handler(irq: u5, handler: ?*const IRQHandler) void {


@@ 195,12 164,10 @@ export fn irq_handler(state: *InterruptState) void {
         if (state.irq_no > 7) {
             io.outb(PIC1_COMMAND, PIC_EOI);
         }
-    }
-    else {
+    } else {
         if (interrupt_handlers[state.irq_no]) |handler| {
             handler.*();
-        }
-        else {
+        } else {
             //@import("std").debug.warn("Unhandled IRQ: '{}'\n", state.irq_no);
         }
         if (state.irq_no > 7) {


@@ 210,323 177,53 @@ export fn irq_handler(state: *InterruptState) void {
     }
 }
 
-comptime {
-    asm (
-        \\isr0:
-        \\  cli
-        \\  pushl $0
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr1:
-        \\  cli
-        \\  pushl $1
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr2:
-        \\  cli
-        \\  pushl $2
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr3:
-        \\  cli
-        \\  pushl $3
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr4:
-        \\  cli
-        \\  pushl $4
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr5:
-        \\  cli
-        \\  pushl $5
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr6:
-        \\  cli
-        \\  pushl $6
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr7:
-        \\  cli
-        \\  pushl $7
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr8:
-        \\  cli
-        \\  pushl $8
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr9:
-        \\  cli
-        \\  pushl $9
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr10:
-        \\  cli
-        \\  pushl $10
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr11:
-        \\  cli
-        \\  pushl $11
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr12:
-        \\  cli
-        \\  pushl $12
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr13:
-        \\  cli
-        \\  pushl $13
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr14:
-        \\  cli
-        \\  pushl $14
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr15:
-        \\  cli
-        \\  pushl $15
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr16:
-        \\  cli
-        \\  pushl $16
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr17:
-        \\  cli
-        \\  pushl $17
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr18:
-        \\  cli
-        \\  pushl $18
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr19:
-        \\  cli
-        \\  pushl $19
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr20:
-        \\  cli
-        \\  pushl $20
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr21:
-        \\  cli
-        \\  pushl $21
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr22:
-        \\  cli
-        \\  pushl $22
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr23:
-        \\  cli
-        \\  pushl $23
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr24:
-        \\  cli
-        \\  pushl $24
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr25:
-        \\  cli
-        \\  pushl $25
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr26:
-        \\  cli
-        \\  pushl $26
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr27:
-        \\  cli
-        \\  pushl $27
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr28:
-        \\  cli
-        \\  pushl $28
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr29:
-        \\  cli
-        \\  pushl $29
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr30:
-        \\  cli
-        \\  pushl $30
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\isr31:
-        \\  cli
-        \\  pushl $31
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call exception_handler
-        \\
-        \\irq0:
-        \\  cli
-        \\  pushl $0
-        \\  jmp irq_stub
-        \\irq1:
-        \\  cli
-        \\  pushl $1
-        \\  jmp irq_stub
-        \\irq2:
-        \\  cli
-        \\  pushl $2
-        \\  jmp irq_stub
-        \\irq3:
-        \\  cli
-        \\  pushl $3
-        \\  jmp irq_stub
-        \\irq4:
-        \\  cli
-        \\  pushl $4
-        \\  jmp irq_stub
-        \\irq5:
-        \\  cli
-        \\  pushl $5
-        \\  jmp irq_stub
-        \\irq6:
-        \\  cli
-        \\  pushl $6
-        \\  jmp irq_stub
-        \\irq7:
-        \\  cli
-        \\  pushl $7
-        \\  jmp irq_stub
-        \\irq8:
-        \\  cli
-        \\  pushl $8
-        \\  jmp irq_stub
-        \\irq9:
-        \\  cli
-        \\  pushl $9
-        \\  jmp irq_stub
-        \\irq10:
-        \\  cli
-        \\  pushl $10
-        \\  jmp irq_stub
-        \\irq11:
-        \\  cli
-        \\  pushl $11
-        \\  jmp irq_stub
-        \\irq12:
-        \\  cli
-        \\  pushl $12
-        \\  jmp irq_stub
-        \\irq13:
-        \\  cli
-        \\  pushl $13
-        \\  jmp irq_stub
-        \\irq14:
-        \\  cli
-        \\  pushl $14
-        \\  jmp irq_stub
-        \\irq15:
-        \\  cli
-        \\  pushl $15
-        \\  jmp irq_stub
-        \\irq_stub:
-        \\  pusha
-        \\  movl %esp, %eax
-        \\  pushl %eax
-        \\  call irq_handler
-        \\  popl %eax
-        \\  popa
-        \\  addl $4, %esp
-        \\  iret
-    );
+fn getInterruptStub(comptime IRQ: bool, comptime i: u32) nakedcc fn () void {
+    const Wrapper = struct {
+        nakedcc fn stub_with_zero() void {
+            asm volatile (
+                \\ pushl $0
+                \\ pushl %[nr]
+                \\ jmp isr_stub
+                :
+                : [nr] "n" (i)
+            );
+        }
+        nakedcc fn stub_with_errorcode() void {
+            asm volatile (
+                \\ pushl %[nr]
+                \\ jmp isr_stub
+                :
+                : [nr] "n" (i)
+            );
+        }
+        nakedcc fn irq_stub() void {
+            asm volatile(
+                \\ pushl %[nr]
+                \\ pusha
+                \\ pushl %%esp
+                \\ call irq_handler
+                \\ popl %%esp
+                \\ popa
+                \\ addl $4, %%esp
+                \\ iret
+                :: [nr] "n" (i)
+            );
+        }
+    };
+    return if (IRQ) Wrapper.irq_stub else switch (i) {
+        8, 10...14, 17 => Wrapper.stub_with_errorcode,
+        else => Wrapper.stub_with_zero,
+    };
 }
 
-extern fn isr0() void;
-extern fn isr1() void;
-extern fn isr2() void;
-extern fn isr3() void;
-extern fn isr4() void;
-extern fn isr5() void;
-extern fn isr6() void;
-extern fn isr7() void;
-extern fn isr8() void;
-extern fn isr9() void;
-extern fn isr10() void;
-extern fn isr11() void;
-extern fn isr12() void;
-extern fn isr13() void;
-extern fn isr14() void;
-extern fn isr15() void;
-extern fn isr16() void;
-extern fn isr17() void;
-extern fn isr18() void;
-extern fn isr19() void;
-extern fn isr20() void;
-extern fn isr21() void;
-extern fn isr22() void;
-extern fn isr23() void;
-extern fn isr24() void;
-extern fn isr25() void;
-extern fn isr26() void;
-extern fn isr27() void;
-extern fn isr28() void;
-extern fn isr29() void;
-extern fn isr30() void;
-extern fn isr31() void;
-
-extern fn irq0() void;
-extern fn irq1() void;
-extern fn irq2() void;
-extern fn irq3() void;
-extern fn irq4() void;
-extern fn irq5() void;
-extern fn irq6() void;
-extern fn irq7() void;
-extern fn irq8() void;
-extern fn irq9() void;
-extern fn irq10() void;
-extern fn irq11() void;
-extern fn irq12() void;
-extern fn irq13() void;
-extern fn irq14() void;
-extern fn irq15() void;
+export nakedcc fn isr_stub() void {
+    asm volatile(
+        \\ pusha
+        \\ pushl %%esp
+        \\ call exception_handler
+        \\ popl %%esp
+        \\ popa
+        \\ addl $8, %%esp
+        \\ iret
+    );
+}