]> pd.if.org Git - zos/commitdiff
syscalls and a user mode process
authorNathan Wagner <nw@hydaspes.if.org>
Tue, 25 Oct 2016 01:35:17 +0000 (20:35 -0500)
committerNathan Wagner <nw@hydaspes.if.org>
Tue, 25 Oct 2016 01:40:32 +0000 (20:40 -0500)
syscall.h [new file with mode: 0644]
syscalls.s [new file with mode: 0644]

diff --git a/syscall.h b/syscall.h
new file mode 100644 (file)
index 0000000..04aebb6
--- /dev/null
+++ b/syscall.h
@@ -0,0 +1,3 @@
+void ksyscall(int call);
+void syscall_entry();
+void init_syscalls(void);
diff --git a/syscalls.s b/syscalls.s
new file mode 100644 (file)
index 0000000..2dd2f6a
--- /dev/null
@@ -0,0 +1,125 @@
+global syscall_entry:function
+global ksyscall:function
+
+extern printk
+extern allstop
+extern need_schedule
+
+; syscall to kernel
+; syscall number in rax
+; fourth argument (rcx) on stack?
+ksyscall:
+       ; syscall over-writes rcx, save it
+       push rcx
+       syscall
+       pop rcx
+       ret
+
+%define STAR 0xC0000081
+%define LSTAR 0xC0000082
+%define FMASK 0xC0000084
+
+extern enable_syscall
+
+global init_syscalls:function
+init_syscalls:
+       ; STAR register
+       mov ecx, STAR
+       rdmsr
+       mov edx, 0x23 ; user code segment / user data segment / 64 bit user code segment
+       shr edx, 16
+       or edx, 0x10 ; kernel code segment
+       wrmsr
+
+       ; syscall rip
+       mov rax, qword syscall_entry
+       mov rdx, qword syscall_entry
+       shr rdx, 32
+       mov ecx, LSTAR
+       wrmsr
+
+       ; rflags mask
+       mov ecx, FMASK
+       rdmsr
+       mov eax, ~0x202
+       wrmsr
+
+       ; turn on the enable bit (bit 1 of EFER, iirc)
+       call enable_syscall
+       ret
+       
+; still using user stack and memory map
+; can't use user's stack because user may lie about where it is
+; causing us to overwrite memory.
+
+extern sleep
+extern timer_ticks
+
+syscall_entry:
+       mov dr0, rcx
+       mov dr1, rax
+       mov dr2, rdi
+
+       ; TODO switch to kernel stack
+
+       ; save values for sysret
+       push r11
+       push rcx
+       mov r10, rcx ; fourth arg in r10, since syscall clobbers rcx
+
+       push rax
+       push rdi
+       push rsi
+       mov r8, rdi
+       mov r9, rsi
+
+       mov rdi, qword sleepstr
+       mov rdx, qword timer_ticks
+       mov rsi, [rdx]
+       mov edx, 0
+       mov ecx, eax
+
+       call printk
+       pop rsi
+       pop rdi
+       pop rax
+
+       call sleep
+
+       ; syscall number in rax
+       ; rcx would be the fourth argument, but over-written by syscall
+       ; so we pass it in r10, another scratch register
+
+       ; may not need to check for schedule, the syscall itself
+       ; should do a yield if it wants to
+
+       ; need to check for schedule, could possible just do
+       ; an interrupt if it needed scheduling
+       call need_schedule
+       mov dr1, rax
+       ;call allstop
+       test eax,eax
+       jz .nosched
+       mov eax, 0x1123f982
+       mov dr0, rax
+       call allstop
+       int 0x81 ; force a schedule call, any int would do actually
+.nosched:
+
+       mov eax, __LINE__
+       mov dr3, rax
+       mov dr2, r11
+       mov dr1, rcx
+       ;call allstop
+
+       pop rcx
+       pop r11
+       db 0x48 ; no sysretq in yasm
+       sysret
+
+ign:
+db     'ignoring syscall %u', 0xa, 0
+
+sleepstr:
+       db '%u pid %u syscall %u : %u %u', 0xa, 0
+