section .text global enable_sse enable_sse: mov rax, cr0 and ax, 0xFFFB ;clear coprocessor emulation CR0.EM or ax, 0x2 ;set coprocessor monitoring CR0.MP mov cr0, rax mov rax, cr4 or ax, 3 << 9 ;set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time mov cr4, rax ret global enable_write_protect enable_write_protect: mov rax, cr0 or eax, 0x80000 ;set write-protect CR0.WP mov cr0, rax ret global enable_nx enable_nx: mov rcx, 0xC0000080 ; IA32_EFER rdmsr or eax, 1 << 11 ; no-execute enable (NXE) wrmsr ret global load_gdt load_gdt: cli lgdt [rdi] mov ax, 0x10 mov ds, ax mov es, ax mov fs, ax mov gs, ax mov ss, ax push 0x08 lea rax, [rel .reload_CS] push rax retfq .reload_CS: ret global load_tr load_tr: mov rax, rdi ltr ax ret extern switch_task global kernel_yield kernel_yield: mov rdi, [rsp] ; return address is now in RDI mov rcx, rsp ; save current RSP add rcx, 8 ; skip over the return address mov eax, ss push rax ; SS push rcx ; RSP pushfq ; RFLAGS mov eax, cs push rax ; CS push rdi ; RIP sub rsp, 24 push rbx ; Preserve RBX sub rsp, 32 push rbp ; Preserve RBP sub rsp, 32 push r12 ; Preserve R12 push r13 ; Preserve R13 push r14 ; Preserve R14 push r15 ; Preserve R15 mov rdi, rsp call switch_task jmp _asm_interrupt_exit %macro ISR 1 global _isr%1 _isr%1: push byte 0 push byte %1 jmp _asm_interrupt_entry %endmacro %macro ISR_ERROR 1 global _isr%1 _isr%1: push byte %1 jmp _asm_interrupt_entry %endmacro %macro IRQ 2 global _isr%1 _isr%1: push byte %2 push byte %1 jmp _asm_interrupt_entry %endmacro extern arch_interrupt_entry extern arch_double_fault extern arch_machine_check _asm_interrupt_entry: push rax push rbx push rcx push rdx push rsi push rdi push rbp push r8 push r9 push r10 push r11 push r12 push r13 push r14 push r15 cld mov rdi, rsp call arch_interrupt_entry _asm_interrupt_exit: pop r15 pop r14 pop r13 pop r12 pop r11 pop r10 pop r9 pop r8 pop rbp pop rdi pop rsi pop rdx pop rcx pop rbx pop rax add rsp, 16 iretq ISR 0 ; divide by zero (#DE) ISR 1 ; debug (#DB) ISR 2 ; non-maskable interrupt ISR 3 ; breakpoint (#BP) ISR 4 ; overflow (#OF) ISR 5 ; bound range exceeded (#BR) ISR 6 ; invalid opcode (#UD) ISR 7 ; device not available (#NM) global _isr8 _isr8: ; double fault (#DF) jmp arch_double_fault ud2 ; we aren't even pushing a return address for arch_double_fault, this is truly UNREACHABLE ; ISR 9 obsolete ISR_ERROR 10 ; invalid tss (#TS) ISR_ERROR 11 ; segment not present (#NP) ISR_ERROR 12 ; stack-segment fault (#SS) ISR_ERROR 13 ; general protection fault (#GP) ISR_ERROR 14 ; page fault (#PF) ; ISR 15 reserved ISR 16 ; x87 floating-point exception (#MF) ISR_ERROR 17 ; alignment check (#AC) global _isr18 _isr18: ; machine check (#MC) jmp arch_machine_check ud2 ; same as above ISR 19 ; SIMD floating-point exception (#XM) ISR 20 ; virtualization exception (#VE) ISR_ERROR 21 ; control-protection exception (#CP) ; ISR 22-31 reserved IRQ 32, 0 ; timer interrupt IRQ 33, 0 ; keyboard interrupt ISR 66 ; system call