64 lines
1.4 KiB
NASM
64 lines
1.4 KiB
NASM
;
|
|
; Context.asm
|
|
; Context switch: save/restore callee-saved registers, stack pointer, CR3, and FPU state
|
|
; Copyright (c) 2025 Daniel Hammer
|
|
;
|
|
|
|
[bits 64]
|
|
section .text
|
|
|
|
; void SchedContextSwitch(uint64_t* oldRsp, uint64_t newRsp, uint64_t newCR3,
|
|
; uint8_t* oldFpuArea, uint8_t* newFpuArea)
|
|
; rdi = pointer to save old RSP
|
|
; rsi = new RSP to restore
|
|
; rdx = new PML4 physical address (for CR3)
|
|
; rcx = old FPU state area (may be null)
|
|
; r8 = new FPU state area (may be null)
|
|
global SchedContextSwitch
|
|
SchedContextSwitch:
|
|
; Save FPU state before pushing registers (rcx/r8 are caller-saved)
|
|
test rcx, rcx
|
|
jz .skip_fxsave
|
|
fxsave [rcx]
|
|
.skip_fxsave:
|
|
|
|
; Stash r8 in r9 (callee-saved registers will clobber r8 slot on stack)
|
|
mov r9, r8
|
|
|
|
; Save callee-saved registers on the current stack
|
|
push rbp
|
|
push rbx
|
|
push r12
|
|
push r13
|
|
push r14
|
|
push r15
|
|
|
|
; Save current RSP into *oldRsp
|
|
mov [rdi], rsp
|
|
|
|
; Load new RSP
|
|
mov rsp, rsi
|
|
|
|
; Switch address space if CR3 differs (avoid unnecessary TLB flush)
|
|
mov rax, cr3
|
|
cmp rax, rdx
|
|
je .skip_cr3
|
|
mov cr3, rdx
|
|
.skip_cr3:
|
|
|
|
; Restore callee-saved registers from the new stack
|
|
pop r15
|
|
pop r14
|
|
pop r13
|
|
pop r12
|
|
pop rbx
|
|
pop rbp
|
|
|
|
; Restore FPU state
|
|
test r9, r9
|
|
jz .skip_fxrstor
|
|
fxrstor [r9]
|
|
.skip_fxrstor:
|
|
|
|
ret
|