189 lines
5.4 KiB
NASM
189 lines
5.4 KiB
NASM
; 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
|