context: misc useful macros and functions

This commit is contained in:
Matheus
2023-04-27 23:32:25 -03:00
parent bebf7a832a
commit 06e755e36a
2 changed files with 124 additions and 2 deletions
+81
View File
@@ -0,0 +1,81 @@
section .text
global arch_context_switch
arch_context_switch:
; 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
pop rbp
add rsp,8 ; remove error code
; check if swapgs is needed
cmp qword [rsp+8], 0x18
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, rsi and r11)
; rdi has the pointer to the function to call
; if the main function returns, just return normally
global arch_context_saveandcall
arch_context_saveandcall:
mov r11, [rsp] ; save return address on scratch register
mov rsi, rsp
add rsi, 8 ; stack pointer before the call instruction
push qword 0x10 ; SS
push rsi ; RSP
pushf ; movs and pushes don't affect flags
push qword 0x08 ; CS
push r11 ; return address
sub rsp, 8 ; error code
push rbp
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
mov r11, rdi ; save function to call
mov rdi, rsp ; first argument is the context struct
push rsi ; save old stack
call r11 ; jump to the desired function
pop rsp ; restore old stack
sub rsp, 8
ret
+43 -2
View File
@@ -4,6 +4,10 @@
#include <stdint.h>
#include <printf.h>
#include <arch/msr.h>
typedef uint64_t ctxreg_t;
typedef struct {
uint64_t cr2;
uint64_t gs;
@@ -33,11 +37,48 @@ typedef struct {
uint64_t ss;
} __attribute__((packed)) context_t;
#define CTX_SP(x) x->rsp;
#define CTX_IP(x) x->rip;
typedef struct {
uint64_t gsbase;
uint64_t fsbase;
} extracontext_t;
#define CTX_INIT(x,u) \
if (u) { \
(x)->cs = 0x18; \
(x)->ds = (x)->es = (x)->ss = 0x20; \
} else { \
(x)->cs = 0x8; \
(x)->ds = (x)->es = (x)->ss = 0x10; \
} \
(x)->rflags = 0x200;
#define CTX_SP(x) (x)->rsp
#define CTX_IP(x) (x)->rip
#define PRINT_CTX(x) { \
printf("cr2: %016lx gs: %04x\nrax: %016lx fs: %04x\nrbx: %016lx es: %04x\nrcx: %016lx ds: %04x\nrdx: %016lx cs: %04x\n r8: %016lx ss: %04x\n r9: %016lx r10: %016lx\nr11: %016lx r12: %016lx\nr13: %016lx r14: %016lx\nr15: %016lx rdi: %016lx\nrsi: %016lx rbp: %016lx\nrip: %016lx rsp: %016lx\nerr: %016lx rfl: %016lx\n", \
x->cr2, x->gs, x->rax, x->fs, x->rbx, x->es, x->rcx, x->ds, x->rdx, x->cs, x->r8, x->ss, x->r9, x->r10, x->r11, x->r12, x->r13, x->r14, x->r15, x->rdi, x->rsi, x->rbp, x->rip, x->rsp, x->error, x->rflags); \
}
void arch_context_switch(context_t *context);
void arch_context_saveandcall(void (*fn)(context_t *context));
#include <string.h>
// kernelgsbase is set as user because they'll be swapped in the context switch
// TODO FPU stuff on all context macros
#define ARCH_CONTEXT_SWITCHTHREAD(x) \
_cpu()->ist.rsp0 = (uint64_t)(x)->kernelstacktop; \
wrmsr(MSR_KERNELGSBASE, (x)->extracontext.gsbase); \
wrmsr(MSR_FSBASE, (x)->extracontext.fsbase); \
arch_context_switch(&thread->context);
#define ARCH_CONTEXT_THREADSAVE(t, c) \
memcpy(&(t)->context, c, sizeof(context_t));
#define ARCH_CONTEXT_THREADLOAD(t, c) \
memcpy(c, &(t)->context, sizeof(context_t)); \
_cpu()->ist.rsp0 = (uint64_t)(t)->kernelstacktop; \
wrmsr(MSR_KERNELGSBASE, (t)->extracontext.gsbase); \
wrmsr(MSR_FSBASE, (t)->extracontext.fsbase);
#endif