extern allstop extern printk extern print_decode_p extern test_address global getrflags:function getrflags: pushf mov rax, [rsp] popf ret global switch_task:function ; this needs to be in sync with the definition in process.h struc reg .kerrno resq 1 ; .rax resq 1 ; .rbx resq 1 ; .rcx resq 1 ; .rdx resq 1 ; .rdi resq 1 ; .rsi resq 1 ; .rsp resq 1 ; .rbp resq 1 ; .r8 resq 1 ; .r9 resq 1 ; .r10 resq 1 ; .r11 resq 1 ; .r12 resq 1 ; .r13 resq 1 ; .r14 resq 1 ; .r15 resq 1 ; .rip resq 1 ; .rflags resq 1 ; .cr3 resq 1 ; .kernel_stack resq 1 ; .cs resq 1 ; .ss resq 1 ; endstruc %macro multipush 1-* %rep %0 push %1 %rotate 1 %endrep %endmacro ; first arg rdi is old register pointer, second arg is new register pointer switch_task: ; save old registers mov [rdi + reg.rax], rax mov [rdi + reg.rbx], rbx mov [rdi + reg.rcx], rcx mov [rdi + reg.rdx], rdx mov [rdi + reg.rdi], rdi ; a pointer to the current task mov [rdi + reg.rsi], rsi ; though rsi is just a pointer to the new task... mov [rdi + reg.rbp], rbp mov [rdi + reg.r8], r8 mov [rdi + reg.r9], r9 mov [rdi + reg.r10], r10 mov [rdi + reg.r11], r11 mov [rdi + reg.r12], r12 mov [rdi + reg.r13], r13 mov [rdi + reg.r14], r14 mov [rdi + reg.r15], r15 ; save rip for return from stack ; mov? we're going to switch the stack anyway pop rax mov [rdi + reg.rip], rax ; push rdi ; push rsi ; mov rdi, qword printrrip ; mov rsi, [rsp] ; call printk ; pop rsi ; pop rdi mov [rdi + reg.rsp], rsp ; save rflags pushf pop rax mov [rdi + reg.rflags], rax ; and the address space ; TODO skip, shouldn't change mov rax, cr3 mov [rdi + reg.cr3], rax .loadregisters ; Ok. now load up the new registers ; we're going to use rax and rbx, and rsi needs ; to be last mov rcx, [rsi + reg.rcx] mov rdx, [rsi + reg.rdx] mov rdi, [rsi + reg.rdi] mov rbp, [rsi + reg.rbp] mov r8, [rsi + reg.r8] mov r9, [rsi + reg.r9] mov r10, [rsi + reg.r10] mov r11, [rsi + reg.r11] mov r12, [rsi + reg.r12] mov r13, [rsi + reg.r13] mov r14, [rsi + reg.r14] mov r15, [rsi + reg.r15] ; push rdi ; push rsi ; mov rdi, qword printsp ; mov rsi, [rsi + reg.rsp] ; call printk ; pop rsi ; pop rdi ; and the address space ; rsi should be pointing into the kernel ; memory, so we can still load from that ; address mov rax, cr3 mov rbx, [rsi + reg.cr3] mov dr1, rax mov dr2, rbx cmp rbx, rax je .skipspaceload mov cr3, rbx mov rbx, cr3 mov dr3, rbx ; switch to new stack, has to be after the address space switch, otherwise the ; stack isn't mapped .skipspaceload: mov rsp, [rsi + reg.rsp] ; load rflags mov rax, [rsi + reg.rflags] ;call printrax push rax popf ; push rip for return from stack ; must be done after we switch address space mov rax, [rsi + reg.rip] push rax ; push rdi ; push rsi ; mov rdi, qword printrip ; ;mov rsi, [rsi + reg.rip] ; mov rsi, [rsp] ; call printk ; pop rsi ; pop rdi ; restore registers we used for the switch mov rbx, [rsi + reg.rbx] mov rax, [rsi + reg.rax] mov rsi, [rsi + reg.rsi] ; have to do this one last ret global usermodetrampoline:function usermodetrampoline: ; sysret wants return rip in rcx ; rflags in r11 ; user mode function in rdi (i.e. first argument) push rdi mov rax, rdi call printrax mov ecx, 0xc0000082 rdmsr shl rdx, 32 or rdx, rax mov rax, rdx call printrax ; TODO clear out all the other registers to not leak anything ; to userspace pop rcx mov r11, 0x202 ; make sure interrupts will be enabled mov dr0, rdi thesysret: db 0x48 ; need rex prefix for 64 bit mode returns sysret section .data printcr3: db 'cr3 = %llx', 0xA, 0 printsp: db 'setting rsp %llx', 0xA, 0 printrip: db 'returning to %llx', 0xA, 0 printrrip: db 'saving return to %llx', 0xA, 0 printcr3s: db 'old cr3 = %llx, new cr3 = %llx', 0xA, 0 section .text dumpcr3: push rdi push rsi push rdx push rbx push rax mov rdi, qword printcr3s mov rsi, rax mov rdx, rbx call printk pop rax pop rbx pop rdx pop rsi pop rdi ret printraxs: push rdi push rsi push rax mov rdi, qword raxprintf mov rsi, rax call printk call allstop pop rax pop rsi pop rdi ret printrax: push rdi push rsi push rax mov rdi, qword raxprintf mov rsi, rax call printk pop rax pop rsi pop rdi ret global printistack:function printistack: push rdi push rsi mov rdi, qword ssprintf mov rsi, [rbx + 32] call printk mov rdi, qword rspprintf mov rsi, [rbx + 24] call printk mov rdi, qword rfprintf mov rsi, [rbx + 16] call printk mov rdi, qword csprintf mov rsi, [rbx + 8] call printk mov rdi, qword ripprintf mov rsi, [rbx + 0] call printk pop rsi pop rdi ret rfprintf: db 'rflags : %llx', 10, 0 csprintf: db 'cs : %hx', 10, 0 ripprintf: db 'rip : %llx', 10, 0 raxprintf: db 'rax : %llx', 10, 0 rspprintf: db 'rsp : %llx', 10, 0 ssprintf: db 'ss : %hx', 10, 0 csvprintf: db 'gdt : %016llx', 10, 0