feat: amd64 interrupts

This commit is contained in:
Loïc Grégoire
2026-03-30 22:15:44 -04:00
parent 827e8bf0ca
commit 55379d671f
9 changed files with 842 additions and 464 deletions
+6 -4
View File
@@ -5,6 +5,8 @@ const amd64 = b.arch;
const std = @import("std");
pub const early_init = @import("init.zig").early_init;
pub const Cpu = struct {
self_ptr: *Cpu,
percpu_offset: usize,
@@ -122,15 +124,15 @@ pub inline fn set_hardware_ipl(ipl: ke.Ipl) void {
}
pub inline fn enable_interrupts() void {
amd64.cpu.sti();
amd64.sti();
}
pub inline fn disable_interrupts() bool {
const rflags = amd64.cpu.rflags();
const ie = amd64.rflags().interrupt_enable;
amd64.cpu.cli();
amd64.cli();
return rflags & (1 << 9) != 0;
return ie;
}
pub inline fn restore_interrupts(state: bool) void {
+37
View File
@@ -0,0 +1,37 @@
const amd64 = @import("arch");
const int = @import("int.zig");
const b = @import("base");
var gdt = extern struct {
entries: [9]u64 align(1),
tss: amd64.TssDescriptor align(1),
}{
.entries = .{
0, // null
0x00009a000000ffff, // code16
0x000093000000ffff, // data16
0x00cf9a000000ffff, // code32
0x00cf93000000ffff, // data32
0x00af9b000000ffff, // kernel code64
0x00af93000000ffff, // kernel data64
0x00aff3000000ffff, // user code64
0x00affb000000ffff, // user data64
},
.tss = undefined,
};
extern fn gdt_load(gdtr: *const amd64.Gdtr) callconv(.{ .x86_64_sysv = .{} }) void;
pub fn early_init() linksection(b.init) void {
const gdtr: amd64.Gdtr = .{
.limit = @sizeOf(@TypeOf(gdt)) - 1,
.base = @intFromPtr(&gdt),
};
gdt_load(&gdtr);
int.init();
asm volatile ("int3");
}
+73
View File
@@ -0,0 +1,73 @@
const amd64 = @import("arch");
const std = @import("std");
const b = @import("base");
extern const __interrupt_vectors: [256]usize;
var idt: [256]amd64.IdtEntry align(16) = undefined;
const exception_msg = [32][]const u8{
"Divide Error",
"Debug",
"Non-Maskable Interrupt",
"Breakpoint",
"Overflow",
"Bound Range Exceeded",
"Invalid Opcode",
"Device Not Available",
"Double Fault",
"Coprocessor Segment Overrun",
"Invalid TSS",
"Segment Not Present",
"Stack-Segment Fault",
"General Protection Fault",
"Page Fault",
"???",
"x87 Floating-Point Exception",
"Alignment Check",
"Machine Check",
"SIMD Floating-Point Exception",
"Virtualization Exception",
"Control Protection Exception",
"???",
"???",
"???",
"???",
"???",
"???",
"???",
"???",
"???",
"Security Exception",
};
export fn isr_handler_main(frame: *const amd64.IrqFrame) callconv(.{ .x86_64_sysv = .{} }) void {
if (frame.intno < 32) {
std.log.info("Unhandled exception: 0x{x} ({s}), err=0x{x}, pc=0x{x}", .{ frame.intno, exception_msg[frame.intno], frame.errcode, frame.rip });
std.log.info("RAX=0x{x:0>16} RBX=0x{x:0>16} RCX=0x{x:0>16} RDX=0x{x:0>16}", .{ frame.rax, frame.rbx, frame.rcx, frame.rdx });
std.log.info("RSI=0x{x:0>16} RDI=0x{x:0>16} RBP=0x{x:0>16} RSP=0x{x:0>16}", .{ frame.rsi, frame.rdi, frame.rbp, frame.rsp });
std.log.info("R8= 0x{x:0>16} R9=0x{x:0>16} R10=0x{x:0>16} R11=0x{x:0>16}", .{ frame.r8, frame.r9, frame.r10, frame.r11 });
std.log.info("R12=0x{x:0>16} R13=0x{x:0>16} R14=0x{x:0>16} R15=0x{x:0>16}", .{ frame.r12, frame.r13, frame.r14, frame.r15 });
const cr2 = amd64.read_cr(2);
const cr3 = amd64.read_cr(3);
const rflags = amd64.rflags();
std.log.info("CR2=0x{x:0>16} CR3=0x{x:0>16} RFLAGS={x}", .{ cr2, cr3, @as(u64, @bitCast(rflags)) });
@panic("Unhandled exception");
}
}
extern fn idt_load(idt_ptr: *const amd64.Idtr) callconv(.{ .x86_64_sysv = .{} }) void;
pub fn init() linksection(b.init) void {
const idtr: amd64.Idtr = .{
.limit = @sizeOf(@TypeOf(idt)) - 1,
.base = @intFromPtr(&idt),
};
for (&idt, 0..256) |*entry, i| {
entry.* = .init(0x28, 0, .InterruptGate, __interrupt_vectors[i]);
}
idt_load(&idtr);
}
+133
View File
@@ -0,0 +1,133 @@
.altmacro
.code64
.section .text
.globl gdt_load
gdt_load:
lgdt (%rdi)
/* Set ss, ds and es to data segment */
mov $0x30, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %ss
/* Save return address */
pop %rdi
/* Push CS so the CPU will pop it off with retfq */
mov $0x28, %rax
push %rax
push %rdi
lretq
.globl idt_load
idt_load:
lidt (%rdi)
ret
.macro pushall
push %rax
push %rbx
push %rcx
push %rdx
push %rbp
push %rdi
push %rsi
push %r8
push %r9
push %r10
push %r11
push %r12
push %r13
push %r14
push %r15
.endm
.macro popall
pop %r15
pop %r14
pop %r13
pop %r12
pop %r11
pop %r10
pop %r9
pop %r8
pop %rsi
pop %rdi
pop %rbp
pop %rdx
pop %rcx
pop %rbx
pop %rax
.endm
.extern isr_handler_main
isr_handler:
cld
pushall
mov %rsp, %rdi
call isr_handler_main
popall
cli
add $16, %rsp
iretq
.macro INTERRUPT_NOERR num
.globl isr\num
isr\num :
pushq $0
pushq $\num
jmp isr_handler
.endm
.macro INTERRUPT_ERR num
.globl isr\num
isr\num :
pushq $\num
jmp isr_handler
.endm
INTERRUPT_NOERR 0
INTERRUPT_NOERR 1
INTERRUPT_NOERR 2
INTERRUPT_NOERR 3
INTERRUPT_NOERR 4
INTERRUPT_NOERR 5
INTERRUPT_NOERR 6
INTERRUPT_NOERR 7
INTERRUPT_ERR 8
INTERRUPT_NOERR 9
INTERRUPT_ERR 10
INTERRUPT_ERR 11
INTERRUPT_ERR 12
INTERRUPT_ERR 13
INTERRUPT_ERR 14
INTERRUPT_NOERR 15
INTERRUPT_NOERR 16
INTERRUPT_ERR 17
INTERRUPT_NOERR 18
INTERRUPT_NOERR 19
INTERRUPT_NOERR 20
INTERRUPT_NOERR 21
INTERRUPT_NOERR 22
INTERRUPT_NOERR 23
INTERRUPT_NOERR 24
INTERRUPT_NOERR 25
INTERRUPT_NOERR 26
INTERRUPT_NOERR 27
INTERRUPT_NOERR 28
INTERRUPT_NOERR 29
INTERRUPT_ERR 30
INTERRUPT_NOERR 31
.rept 224
INTERRUPT_NOERR %32+\+
.endr
.global __interrupt_vectors
__interrupt_vectors:
.rept 256
.quad isr\()\+
.endr