hachem.wtf
aboutsummaryrefslogtreecommitdiff
path: root/boot/user.zig
diff options
context:
space:
mode:
Diffstat (limited to 'boot/user.zig')
-rw-r--r--boot/user.zig39
1 files changed, 21 insertions, 18 deletions
diff --git a/boot/user.zig b/boot/user.zig
index 61345e5..4272269 100644
--- a/boot/user.zig
+++ b/boot/user.zig
@@ -1,7 +1,7 @@
// ring3 entry + the syscall boundary
// drop user mode with iretq, and come back to the kernel
//
-// see: - https://wiki.osdev.org/System_Calls
+// see: - https://wiki.osdev.org/System_Calls
// - https://wiki.osdev.org/Getting_to_Ring_3
const serial = @import("serial.zig");
@@ -52,17 +52,7 @@ pub fn enterUser(entry: u64, ustack: u64) void {
g_user_stack = ustack;
// this is the truest most correct statement ever
// get this man a true
- asm volatile ("call enterUserAsm" ::: .{
- .memory = true,
- .rax = true,
- .rcx = true,
- .rdx = true,
- .rsi = true,
- .rdi = true,
- .r8 = true,
- .r9 = true,
- .r10 = true,
- .r11 = true });
+ asm volatile ("call enterUserAsm" ::: .{ .memory = true, .rax = true, .rcx = true, .rdx = true, .rsi = true, .rdi = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true });
}
export fn enterUserAsm() callconv(.naked) void {
@@ -134,15 +124,28 @@ export fn syscallStub() callconv(.naked) void {
);
}
-// returns 0 to resume the program, 1 to return to the kernel (exit).
+pub fn runProcess(pml4: u64, entry: u64, ustack: u64) void {
+ const prev = vmm.activePml4();
+ vmm.loadPml4(pml4);
+ enterUser(entry, ustack);
+ vmm.loadPml4(prev);
+}
+
export fn syscallHandler(frame: *SyscallFrame) callconv(.c) u64 {
switch (frame.rax) {
- 0 => { // exit
- serial.write("[syscall] exit -> back to kernel\r\n");
- return 1;
+ 0 => { // exit(code): code in rdi
+ return 1; // tell the stub to unwind back into the kernel
},
- 1 => { // "hello" -- a fixed message, no user pointer to validate yet
- serial.write("[syscall] hello from ring 3!\r\n");
+ 1 => { // write(ptr, len): rdi = user pointer, rsi = length
+ const len = frame.rsi;
+ // the process's address space is active during the syscall, so the
+ // kernel can read the user pointer directly. cap the length so a
+ // bogus arg can't run us off into unmapped memory.
+ if (len > 0 and len <= 4096) {
+ const bytes: [*]const u8 = @ptrFromInt(frame.rdi);
+ serial.write(bytes[0..len]); // mirrored -> the revo console renders it
+ }
+ frame.rax = len; // syscall return value
return 0;
},
else => {