]> pd.if.org Git - zos/blobdiff - taskx64.s
processes and multitasking
[zos] / taskx64.s
diff --git a/taskx64.s b/taskx64.s
new file mode 100644 (file)
index 0000000..5b2f815
--- /dev/null
+++ b/taskx64.s
@@ -0,0 +1,274 @@
+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