Files
Astral/kernel-src/arch/x86-64/context.asm
T
2025-12-07 12:06:32 -03:00

100 lines
2.1 KiB
NASM

section .text
global arch_context_switch
arch_context_switch:
xor rsi, rsi ; is syscall? (no)
extern sched_userspacecheck
call sched_userspacecheck ; compiled with no_caller_saved_registers
cli
; rdi is the pointer to the context struct
mov rsp, rdi
add rsp, 24 ; cr2 gs and fs are not popped.
pop rax
mov es,rax
pop rax
mov ds,rax
pop rax
pop rbx
pop rcx
pop rdx
pop r8
pop r9
pop r10
pop r11
pop r12
pop r13
pop r14
pop r15
pop rdi
pop rsi
add rsp,8 ; remove irq
pop rbp
add rsp,8 ; remove error code
; check if swapgs is needed
cmp qword [rsp+8], 0x23
jne .notneeded2
swapgs
.notneeded2:
o64 iret
; saves context on the stack and passes as the argument to a function
; since this uses the C system V abi, some registers can be clobbered (in this case, r10 and r11)
; rdi has the pointer to the function to call
; rsi has the pointer to the stack the function should have on call. if NULL the stack is not changed
; rdx has the pointer to the arguments to pass to the function
; if the main function returns, do a context switch as the registers could have been changed
global arch_context_saveandcall
arch_context_saveandcall:
mov r11, [rsp] ; save return address on scratch register
mov r10, rsp
add r10, 8 ; stack pointer before the call instruction
test rsi,rsi
jz .nostackchange
mov rsp, rsi ; use desired stack
.nostackchange:
push qword 0x10 ; SS
push r10 ; RSP
pushf ; movs and pushes don't affect flags
push qword 0x08 ; CS
push r11 ; return address
sub rsp, 8 ; error code
push rbp
sub rsp, 8 ; irq
push rsi
push rdi
push r15
push r14
push r13
push r12
push r11
push r10
push r9
push r8
push rdx
push rcx
push rbx
push rax
push qword 0x10 ; ES
push qword 0x10 ; DS
push qword 0 ; FS
push qword 0 ; GS
sub rsp, 8 ; cr2
test rsi, rsi
jz .nostackchange2
xor rbp, rbp ; the old stack will no longer be in our ownership, so zero rbp
.nostackchange2:
mov r11, rdi ; save function to call
mov rdi, rsp ; first argument is the context struct
mov rsi, rdx ; pass argument
call r11 ; jump to the desired function
; do context switch to return
cli
mov rdi, rsp
call arch_context_switch