; ke_syscall.asm - INT 0x40 kernel entry (MASM64) ; ; On entry the CPU has pushed (ring-3 -> ring-0 transition): ; SS, RSP, RFLAGS, CS, RIP (on the kernel stack via TSS.RSP0) ; RAX = syscall number ; RCX, RDX, R8, R9 = args 0-3 (MS x64) ; R10, R11 = args 4-5 (our extension) EXTERN KeSyscallDispatch:PROC .CODE KeSyscallEntry PROC sub rsp, 8 ; 16-byte align the stack frame ; We need to allocate 32 bytes for shadow space, plus 24 bytes for ; the 3 stack arguments (a3, a4, a5), plus 8 bytes of padding to keep ; the stack 16-byte aligned. Total = 64. sub rsp, 64 ; Place the 5th, 6th, and 7th arguments onto the stack for KeSyscallDispatch mov [rsp + 32], r9 ; a3 mov [rsp + 40], r10 ; a4 mov [rsp + 48], r11 ; a5 ; Shift the first 4 registers down one slot mov r9, r8 ; a2 mov r8, rdx ; a1 mov rdx, rcx ; a0 mov rcx, rax ; nr (syscall number) ; Call the C dispatcher call KeSyscallDispatch add rsp, 72 ; Clean up (64 + 8) iretq KeSyscallEntry ENDP ; --------------------------------------------------------------------------- ; Fault stubs - print a message and halt. ; --------------------------------------------------------------------------- EXTERN KePanic:PROC .data ; We define separate strings to maximize the info we can print StrKernel DB "Kernel Mode", 0 StrUser DB "User Mode", 0 MsgFaultDE DB "PANIC: Divide Error (#0) | RIP: %016llx | Mode: %s", 0Ah, 0 MsgFaultGP DB "PANIC: General Protection (#13) | RIP: %016llx | Code: %04x | Mode: %s", 0Ah, 0 MsgFaultPF DB "PANIC: Page Fault (#14) | RIP: %016llx | Code: %04x | CR2: %016llx | %s", 0Ah, 0 .code ; --------------------------------------------------------- ; Divide Error (#0) - NO Error Code pushed by CPU ; Stack: [rsp] = RIP, [rsp+8] = CS, [rsp+16] = RFLAGS ; --------------------------------------------------------- KeFaultDE PROC mov rdx, [rsp] ; Arg 2: RIP ; Determine User/Kernel mode from CS mov rax, [rsp + 8] ; Read CS and rax, 3 ; Isolate the bottom 2 bits (RPL) lea r8, StrKernel lea r9, StrUser test rax, rax ; If 0, it's Kernel. If >0, it's User. cmovnz r8, r9 ; Arg 3: Mode String (moves r9 into r8 if Not Zero) lea rcx, MsgFaultDE ; Arg 1: Format string ; Safely align stack and allocate shadow space for the call and rsp, -16 ; Force 16-byte ABI stack alignment sub rsp, 20h ; Allocate 32 bytes of shadow space call KePanic KeFaultDE ENDP ; --------------------------------------------------------- ; General Protection Fault (#13) - Error Code PUSHED ; Stack: [rsp] = ErrCode, [rsp+8] = RIP, [rsp+16] = CS ; --------------------------------------------------------- KeFaultGP PROC mov r8, [rsp] ; Arg 3: Error Code mov rdx, [rsp + 8] ; Arg 2: RIP ; Determine User/Kernel mode from CS mov rax, [rsp + 16] ; Read CS and rax, 3 lea r9, StrKernel lea r10, StrUser test rax, rax cmovnz r9, r10 ; Arg 4: Mode String lea rcx, MsgFaultGP ; Arg 1: Format string and rsp, -16 ; Align stack sub rsp, 20h ; 32 bytes shadow space call KePanic KeFaultGP ENDP ; --------------------------------------------------------- ; Page Fault (#14) - Error Code PUSHED ; Stack: [rsp] = ErrCode, [rsp+8] = RIP, [rsp+16] = CS ; --------------------------------------------------------- KeFaultPF PROC mov r8, [rsp] ; Arg 3: Error Code mov rdx, [rsp + 8] ; Arg 2: RIP mov r9, cr2 ; Arg 4: CR2 (The faulting virtual address) ; Determine User/Kernel mode from CS mov rax, [rsp + 16] ; Read CS and rax, 3 lea r10, StrKernel lea r11, StrUser test rax, rax cmovnz r10, r11 ; r10 now holds the Mode String lea rcx, MsgFaultPF ; Arg 1: Format string ; We have 5 arguments for PF! (rcx, rdx, r8, r9, and the stack) ; x64 ABI dictates the 5th argument goes on the stack just above the shadow space. and rsp, -16 ; Align stack sub rsp, 30h ; 32 bytes shadow space + 16 bytes for 5th arg and padding mov [rsp + 20h], r10 ; Arg 5: Mode String (placed exactly after shadow space) call KePanic KeFaultPF ENDP EXTERN KeIrqDispatch:PROC IrqStub MACRO num PUBLIC KeIrqStub&num KeIrqStub&num PROC push rax mov al, num jmp KeIrqCommon KeIrqStub&num ENDP ENDM IrqStub 0 IrqStub 1 IrqStub 2 IrqStub 3 IrqStub 4 IrqStub 5 IrqStub 6 IrqStub 7 IrqStub 8 IrqStub 9 IrqStub 10 IrqStub 11 IrqStub 12 IrqStub 13 IrqStub 14 IrqStub 15 IrqStub 16 IrqStub 17 IrqStub 18 IrqStub 19 IrqStub 20 IrqStub 21 IrqStub 22 IrqStub 23 KeIrqCommon PROC ; al = irq number, rax saved on stack ; Build a minimal calling-convention-safe frame push rcx push rdx push r8 push r9 push r10 push r11 movzx ecx, al ; first arg = irq number (rcx, Win64 ABI) sub rsp, 32 ; shadow space call KeIrqDispatch add rsp, 32 pop r11 pop r10 pop r9 pop r8 pop rdx pop rcx pop rax iretq KeIrqCommon ENDP END