From e52b0bcf772fa2acbc830a59ab5de170283b0f2b Mon Sep 17 00:00:00 2001 From: Gabriel Date: Sat, 22 Feb 2025 22:58:56 +0100 Subject: [PATCH] core+system: Add a bunch of syscalls related to thread creation --- core/src/sys/mem.zig | 2 +- core/src/sys/sched.zig | 54 ++++++++++++++++++++++++++++++++++++- core/src/sys/syscall.zig | 7 +++++ system/lib/kernel.zig | 13 ++++++--- system/lib/syscalls.zig | 58 ++++++++++++++++++++++++++++++++-------- 5 files changed, 117 insertions(+), 17 deletions(-) diff --git a/core/src/sys/mem.zig b/core/src/sys/mem.zig index 985298d..c39541e 100644 --- a/core/src/sys/mem.zig +++ b/core/src/sys/mem.zig @@ -40,7 +40,7 @@ pub fn lockFrame(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerr pub fn setAddressSpace(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void { const core = cpu.thisCore(); - if (!sys.checkToken(core, system.kernel.Token.VirtualMemory)) return error.NotAuthorized; + if (!sys.checkToken(core, system.kernel.Token.CreateProcess)) return error.NotAuthorized; const target = thread.lookupThreadById(args.arg0) orelse return error.NoSuchThread; diff --git a/core/src/sys/sched.zig b/core/src/sys/sched.zig index 244874c..e1b9f19 100644 --- a/core/src/sys/sched.zig +++ b/core/src/sys/sched.zig @@ -41,7 +41,7 @@ pub fn sleep(regs: *platform.Registers, args: *sys.Arguments, _: *isize) anyerro pub fn setEventQueue(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void { const core = cpu.thisCore(); - if (!sys.checkToken(core, system.kernel.Token.EventQueue)) return error.NotAuthorized; + if (!sys.checkToken(core, system.kernel.Token.CreateProcess)) return error.NotAuthorized; const target = thread.lookupThreadById(args.arg0) orelse return error.NoSuchThread; if (target.event_queue) |_| return error.ThreadQueueAlreadySet; @@ -54,3 +54,55 @@ pub fn setEventQueue(_: *platform.Registers, args: *sys.Arguments, _: *isize) an target.event_queue = RingBuffer.init(data, platform.PAGE_SIZE, true); } + +pub fn createThread(_: *platform.Registers, _: *sys.Arguments, result: *isize) anyerror!void { + const core = cpu.thisCore(); + if (!sys.checkToken(core, system.kernel.Token.CreateProcess)) return error.NotAuthorized; + + const allocator = pmm.lockGlobalAllocator(); + defer pmm.unlockGlobalAllocator(); + + const child = try thread.createThreadControlBlock(allocator); + thread.arch.initUserRegisters(&child.regs); + + result.* = @bitCast(child.id); +} + +pub fn setThreadEntry(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void { + const core = cpu.thisCore(); + if (!sys.checkToken(core, system.kernel.Token.CreateProcess)) return error.NotAuthorized; + const target = thread.lookupThreadById(args.arg0) orelse return error.NoSuchThread; + + thread.arch.setAddress(&target.regs, args.arg1); +} + +pub fn setThreadArguments(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void { + const core = cpu.thisCore(); + if (!sys.checkToken(core, system.kernel.Token.CreateProcess)) return error.NotAuthorized; + const target = thread.lookupThreadById(args.arg0) orelse return error.NoSuchThread; + + thread.arch.setArguments(&target.regs, args.arg1, args.arg2); +} + +pub fn setThreadStack(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void { + const core = cpu.thisCore(); + if (!sys.checkToken(core, system.kernel.Token.CreateProcess)) return error.NotAuthorized; + const target = thread.lookupThreadById(args.arg0) orelse return error.NoSuchThread; + + thread.arch.setStack(&target.regs, args.arg1); +} + +pub fn startThread(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void { + const core = cpu.thisCore(); + if (!sys.checkToken(core, system.kernel.Token.CreateProcess)) return error.NotAuthorized; + const target = thread.lookupThreadById(args.arg0) orelse return error.NoSuchThread; + + if (target.state != .Inactive) return; + + thread.reviveThread(core, target); +} + +pub fn getThreadId(_: *platform.Registers, _: *sys.Arguments, result: *isize) anyerror!void { + const core = cpu.thisCore(); + result.* = @bitCast(core.current_thread.id); +} diff --git a/core/src/sys/syscall.zig b/core/src/sys/syscall.zig index 4616530..2c309cf 100644 --- a/core/src/sys/syscall.zig +++ b/core/src/sys/syscall.zig @@ -29,6 +29,13 @@ const syscalls = [_]SystemCall{ sched.sleep, sched.setEventQueue, tokens.setTokens, + mem.setAddressSpace, + sched.createThread, + sched.setThreadEntry, + sched.setThreadArguments, + sched.setThreadStack, + sched.startThread, + sched.getThreadId, }; pub fn invokeSyscall(number: usize, frame: *platform.Registers, args: *Arguments, retval: *isize) void { diff --git a/system/lib/kernel.zig b/system/lib/kernel.zig index 42d478c..6f9ad0c 100644 --- a/system/lib/kernel.zig +++ b/system/lib/kernel.zig @@ -7,17 +7,22 @@ pub const SystemCall = enum(u64) { SetPriority, // requires Token.ThreadPriority GetPriority, Sleep, - SetEventQueue, // requires Token.EventQueue + SetEventQueue, // requires Token.CreateProcess SetTokens, // requires Token.Root - SetAddressSpace, // requires Token.VirtualMemory + SetAddressSpace, // requires Token.CreateProcess + CreateThread, // requires Token.CreateProcess + SetThreadEntry, // requires Token.CreateProcess + SetThreadArguments, // requires Token.CreateProcess + SetThreadStack, // requires Token.CreateProcess + StartThread, // requires Token.CreateProcess + GetThreadId, }; pub const Token = enum(u64) { Root = 1 << 0, PhysicalMemory = 1 << 1, ThreadPriority = 1 << 2, - EventQueue = 1 << 3, - VirtualMemory = 1 << 4, + CreateProcess = 1 << 3, }; pub const SystemError = error{ diff --git a/system/lib/syscalls.zig b/system/lib/syscalls.zig index 6cc57d4..be5cf59 100644 --- a/system/lib/syscalls.zig +++ b/system/lib/syscalls.zig @@ -1,58 +1,94 @@ const kernel = @import("kernel.zig"); const target = @import("builtin").target; -fn syscall(num: kernel.SystemCall, arg0: u64, arg1: u64) i64 { +fn syscall(num: kernel.SystemCall, arg0: u64, arg1: u64, arg2: u64) i64 { return switch (target.cpu.arch) { .x86_64 => asm volatile ("int $66" : [result] "={rax}" (-> i64), : [num] "{rax}" (@intFromEnum(num)), [arg0] "{rdi}" (arg0), [arg1] "{rsi}" (arg1), + [arg2] "{rdx}" (arg2), ), else => @compileError("unsupported architecture"), }; } pub fn print(arg: u64) void { - _ = syscall(.Print, arg, 0); + _ = syscall(.Print, arg, 0, 0); } pub fn allocFrame() !usize { - const retval = syscall(.AllocFrame, 0, 0); + const retval = syscall(.AllocFrame, 0, 0, 0); if (retval < 0) return error.OutOfMemory; return @bitCast(retval); } pub fn lockFrame(address: u64) void { - _ = syscall(.LockFrame, address, 0); + _ = syscall(.LockFrame, address, 0, 0); } pub fn freeFrame(address: u64) void { - _ = syscall(.FreeFrame, address, 0); + _ = syscall(.FreeFrame, address, 0, 0); } pub fn yield() void { - _ = syscall(.Yield, 0, 0); + _ = syscall(.Yield, 0, 0, 0); } pub fn setPriority(priority: u8) void { - _ = syscall(.SetPriority, priority, 0); + _ = syscall(.SetPriority, priority, 0, 0); } pub fn getPriority() u8 { - return @truncate(@as(u64, @bitCast(syscall(.GetPriority, 0, 0)))); + return @truncate(@as(u64, @bitCast(syscall(.GetPriority, 0, 0, 0)))); } pub fn sleep(ms: u64) void { - _ = syscall(.Sleep, ms, 0); + _ = syscall(.Sleep, ms, 0, 0); } pub fn setEventQueue(pid: u64, address: u64) !void { - const retval = syscall(.SetEventQueue, pid, address); + const retval = syscall(.SetEventQueue, pid, address, 0); if (retval < 0) return error.NoSuchThread; } pub fn setTokens(pid: u64, tokens: u64) !void { - const retval = syscall(.SetTokens, pid, tokens); + const retval = syscall(.SetTokens, pid, tokens, 0); if (retval < 0) return error.NoSuchThread; } + +pub fn setAddressSpace(pid: u64, address: u64) !void { + const retval = syscall(.SetAddressSpace, pid, address, 0); + if (retval < 0) return error.NoSuchThread; +} + +pub fn createThread() !u64 { + const retval = syscall(.CreateThread, 0, 0, 0); + if (retval < 0) return error.NoSuchThread; + return @bitCast(retval); +} + +pub fn setThreadEntry(pid: u64, entry: u64) !void { + const retval = syscall(.SetThreadEntry, pid, entry, 0); + if (retval < 0) return error.NoSuchThread; +} + +pub fn setThreadArguments(pid: u64, arg0: u64, arg1: u64) !void { + const retval = syscall(.SetThreadArguments, pid, arg0, arg1); + if (retval < 0) return error.NoSuchThread; +} + +pub fn setThreadStack(pid: u64, stack: u64) !void { + const retval = syscall(.SetThreadStack, pid, stack, 0); + if (retval < 0) return error.NoSuchThread; +} + +pub fn startThread(pid: u64) !void { + const retval = syscall(.StartThread, pid, 0, 0); + if (retval < 0) return error.NoSuchThread; +} + +pub fn getThreadId() u64 { + return @bitCast(syscall(.GetThreadId, 0, 0, 0)); +}