; 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 - thin wrappers that collect the CPU exception frame and ; forward to KeFaultDispatch (C), which handles both kernel panics and ; user-process bugchecks. ; ; KeFaultDispatch signature (MS x64): ; void KeFaultDispatch(int vector, // rcx ; UINT64 rip, // rdx ; UINT64 errCode, // r8 ; UINT64 cr2, // r9 ; UINT64 cs) // [rsp+20h] (5th arg, on stack) ; --------------------------------------------------------------------------- EXTERN KeFaultDispatch:PROC ; Allocation for a 5-argument call (MS x64): ; 32 bytes shadow space (0x00..0x1F) ; 8 bytes for 5th arg (0x20..0x27) ; Total = 0x28 bytes. ; After "and rsp,-16" rsp%16==0; sub 0x28 (40) → rsp%16==8, ; so the subsequent "call" push makes rsp 16-byte aligned at callee entry. ✓ FAULT_FRAME_SIZE EQU 28h ; --------------------------------------------------------- ; Divide Error (#0) - NO error code pushed by CPU ; Exception frame at entry: [rsp]=RIP [rsp+8]=CS [rsp+16]=RFLAGS ; --------------------------------------------------------- KeFaultDE PROC mov rdx, [rsp] ; Arg2: rip xor r8, r8 ; Arg3: errCode = 0 (no error code for #DE) xor r9, r9 ; Arg4: cr2 = 0 (not a page fault) mov r10, [rsp+8] ; cs (save before we clobber rsp) mov ecx, 0 ; Arg1: vector = 0 and rsp, -16 sub rsp, FAULT_FRAME_SIZE mov [rsp+20h], r10 ; Arg5: cs call KeFaultDispatch ; _Noreturn - never returns KeFaultDE ENDP ; --------------------------------------------------------- ; General Protection Fault (#13) - error code pushed by CPU ; Exception frame at entry: [rsp]=ErrCode [rsp+8]=RIP [rsp+16]=CS ; --------------------------------------------------------- KeFaultGP PROC mov r8, [rsp] ; Arg3: errCode mov rdx, [rsp+8] ; Arg2: rip xor r9, r9 ; Arg4: cr2 = 0 (not a page fault) mov r10, [rsp+16] ; cs mov ecx, 13 ; Arg1: vector = 13 and rsp, -16 sub rsp, FAULT_FRAME_SIZE mov [rsp+20h], r10 ; Arg5: cs call KeFaultDispatch KeFaultGP ENDP ; --------------------------------------------------------- ; Page Fault (#14) - error code pushed by CPU ; Exception frame at entry: [rsp]=ErrCode [rsp+8]=RIP [rsp+16]=CS ; --------------------------------------------------------- KeFaultPF PROC mov r8, [rsp] ; Arg3: errCode mov rdx, [rsp+8] ; Arg2: rip mov r9, cr2 ; Arg4: cr2 (faulting virtual address) mov r10, [rsp+16] ; cs mov ecx, 14 ; Arg1: vector = 14 and rsp, -16 sub rsp, FAULT_FRAME_SIZE mov [rsp+20h], r10 ; Arg5: cs call KeFaultDispatch 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