~pixelherodev/LIMNOS

0737d6184d6f32f6a8d5302e96b8f4c40189d810 — Noam Preil 3 months 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
    );
}