struc idt_entry .handler_low: resw 1 .selector: resw 1 .ist: resb 1 .flags: resb 1 .handler_high: resw 1 .handler_highest: resd 1 .reserved: resd 1 endstruc align 16 global set_idt_entry:function ;void set_idt_entry( ; struct idt_entry *entry, rdi ; uintptr_t handler, rsi ; uint16_t selector, rdx ; uint8_t flags, rcx ; uint8_t ist r8 set_idt_entry: mov [rdi + idt_entry.flags], cl mov [rdi + idt_entry.ist], r8b mov [rdi + idt_entry.selector], dx mov [rdi + idt_entry.handler_low], si shr rsi, 16 mov [rdi + idt_entry.handler_high], si shr rsi, 16 mov [rdi + idt_entry.handler_highest], esi mov [rdi + idt_entry.reserved], dword 0x0 global load_idt:function load_idt: ; size_t limit = sizeof(struct idt_entry) * length - 1; shl rsi, 4 sub rsi, 1 sub rsp, 10 mov [rsp], si mov [rsp + 2], rdi lidt [rsp] add rsp, 10 ret section .text extern interrupt_handler extern global_errno extern printk %macro makeisr 2 global isr%1:function isr%1: push %2 ; err_code push %1 ; int_no jmp interrupt_handler_prepare %endmacro %macro makeisr 1 global isr%1:function isr%1: ; error code pushed by processor push %1 ; int_no jmp interrupt_handler_prepare %endmacro %macro makeirq 2 global irq%1:function irq%1: push 0 ; err_code push %2 ; int_no jmp interrupt_handler_prepare %endmacro ; create isr 0-7, which need an error code pushed %assign i 0 %rep 8 makeisr i,0 %assign i i+1 %endrep makeisr 8 makeisr 9,0 makeisr 10 makeisr 11 makeisr 12 makeisr 13 makeisr 14 ; make isr 15-31 %assign i 15 %rep 17 makeisr i,0 %assign i i+1 %endrep ; make irqs %assign i 32 %assign j 0 %rep 16 makeirq j,i %assign i i+1 %assign j j+1 %endrep ; make remaining interrupts %assign i 48 %rep 208 makeisr i,0 %assign i i+1 %endrep interrupt_handler_prepare: push r15 push r14 push r13 push r12 push r11 push r10 push r9 push r8 push rax push rcx push rdx push rbx push rsp push rbp push rsi push rdi ; CR2 for page faults, always push for consistent frame mov rbp, cr2 push rbp mov eax, [qword global_errno] push rax mov rdi, rsp ; context stack frame pointer mov rbx, rsp ; rbx is preserved by the abi, so save it and rsp, 0xFFFFFFF0 ; should be sign extended call interrupt_handler mov rsp, rbx ; restore the stack load_interrupted_registers: ; Restore the previous kernel errno. pop rax mov [qword global_errno], eax add rsp, 8 ; remove CR2 pop rdi pop rsi pop rbp add rsp, 8 ; skip rsp pop rbx pop rdx pop rcx pop rax pop r8 pop r9 pop r10 pop r11 pop r12 pop r13 pop r14 pop r15 ; Remove int_no and err_code add rsp, 16 iretq ;.size interrupt_handler_prepare, . - interrupt_handler_prepare global interrupt_handler_null:function align 16 interrupt_handler_null: iretq ;.size interrupt_handler_null, . - interrupt_handler_null rfprintf: db 'rflags : %llx', 10, 0 csprintf: db 'cs : %hx', 10, 0 ripprintf: db 'rip : %llx', 10, 0 rspprintf: db 'rsp : %llx', 10, 0 ssprintf: db 'ss : %hx', 10, 0 csvprintf: db 'gdt : %016llx', 10, 0 global interrupts_enabled:function interrupts_enabled: pushf pop rax shr rax, 9 and rax, 0x1 ret global enable_interrupts:function enable_interrupts: sti ret global disable_interrupts:function disable_interrupts: cli ret