aboutsummaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
authorTianhao Wang <shrik3@mailbox.org>2024-04-17 21:49:43 +0200
committerTianhao Wang <shrik3@mailbox.org>2024-06-11 15:16:33 +0200
commitb5a8b9ba0f1461031c39b5a5abf1c544a9dc7ab8 (patch)
tree74aa419d91622a03fd9575b50f2ec818273a88c1 /src/arch
parent6609d771d429df9ef810d39f2180c9b651fc15d0 (diff)
split idt and vectors from startup code
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/x86_64/asm/vectors.s88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/arch/x86_64/asm/vectors.s b/src/arch/x86_64/asm/vectors.s
new file mode 100644
index 0000000..c3fa12f
--- /dev/null
+++ b/src/arch/x86_64/asm/vectors.s
@@ -0,0 +1,88 @@
+; vectors.s - idt for x86_64
+
+[GLOBAL idt]
+[GLOBAL idt_descr]
+[GLOBAL vectors_start]
+[EXTERN interrupt_gate]
+
+[SECTION .data.idt]
+;
+; Interrupt descriptor table with 256 entries
+; TODO: use a interrupt stack instead of the current stack.
+;
+idt:
+%macro idt_entry 1
+ dw (wrapper_%1 - wrapper_0) & 0xffff ; offset 0 .. 15
+ dw 0x0000 | 0x8 * 2 ; selector points to 64-bit code segment selector (GDT)
+ dw 0x8e00 ; 8 -> interrupt is present, e -> 80386 32-bit interrupt gate
+ dw ((wrapper_%1 - wrapper_0) & 0xffff0000) >> 16 ; offset 16 .. 31
+ dd ((wrapper_%1 - wrapper_0) & 0xffffffff00000000) >> 32 ; offset 32..63
+ dd 0x00000000 ; reserved
+%endmacro
+
+%assign i 0
+%rep 256
+idt_entry i
+%assign i i+1
+%endrep
+
+idt_descr:
+ dw 256*8 - 1 ; 256 entries
+ dq idt
+
+; template for header for each interrupt-handling routine
+%macro wrapper 1
+wrapper_%1:
+ push rbp
+ mov rbp, rsp
+ push rax
+ mov al, %1
+ jmp wrapper_body
+%endmacro
+
+; automatic generation of 256 interrupt-handling routines, based on above macro
+
+[SECTION .data.vectors]
+vectors_start:
+%assign i 0
+%rep 256
+wrapper i
+%assign i i+1
+%endrep
+
+; common handler body
+wrapper_body:
+ ; GCC expects the direction flag to be 0
+ cld
+ ; save volatile registers
+ push rcx
+ push rdx
+ push rdi
+ push rsi
+ push r8
+ push r9
+ push r10
+ push r11
+
+ ; the generated wrapper only gives us 8 bits, mask the rest
+ and rax, 0xff
+ ; call the interrupt handling code with interrupt number as parameter
+ mov rdi, rax
+ call interrupt_gate
+
+ ; restore volatile registers
+ pop r11
+ pop r10
+ pop r9
+ pop r8
+ pop rsi
+ pop rdi
+ pop rdx
+ pop rcx
+
+ ; ... also those from the wrapper
+ pop rax
+ pop rbp
+
+ ; done
+ iretq