diff --git a/core/src/sys/sched.zig b/core/src/sys/sched.zig index 613eb50..a4d74bc 100644 --- a/core/src/sys/sched.zig +++ b/core/src/sys/sched.zig @@ -1,7 +1,18 @@ +const std = @import("std"); +const system = @import("system"); const platform = @import("../arch/platform.zig").arch; const sys = @import("syscall.zig"); const thread = @import("../thread.zig"); const cpu = @import("../arch/cpu.zig"); +const pmm = @import("../pmm.zig"); +const vmm = @import("../arch/vmm.zig").arch; + +const RingBuffer = system.ring_buffer.RingBuffer; + +const SyscallError = error{ + NoSuchThread, + ThreadQueueAlreadySet, +}; pub fn yield(regs: *platform.Registers, _: *sys.Arguments, _: *isize) anyerror!void { const core = cpu.thisCore(); @@ -23,3 +34,17 @@ pub fn getPriority(_: *platform.Registers, _: *sys.Arguments, retval: *isize) an pub fn sleep(regs: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void { _ = thread.startSleep(regs, args.arg0); } + +pub fn setEventQueue(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void { + const target = thread.lookupThreadById(args.arg0) orelse return error.NoSuchThread; + + if (target.event_queue) |_| return error.ThreadQueueAlreadySet; + + const phys = pmm.PhysFrame{ .address = args.arg1 }; + + const virt = phys.virtualAddress(vmm.PHYSICAL_MAPPING_BASE); + + const data: [*]u8 = @ptrFromInt(virt); + + target.event_queue = RingBuffer.init(data, platform.PAGE_SIZE, true); +} diff --git a/core/src/sys/syscall.zig b/core/src/sys/syscall.zig index fe628b9..f60d418 100644 --- a/core/src/sys/syscall.zig +++ b/core/src/sys/syscall.zig @@ -15,7 +15,7 @@ pub const Arguments = struct { const SystemCall = *const fn (frame: *platform.Registers, args: *Arguments, retval: *isize) anyerror!void; -const syscalls = [_]SystemCall{ print, mem.allocFrame, mem.lockFrame, mem.freeFrame, sched.yield, sched.setPriority, sched.getPriority, sched.sleep }; +const syscalls = [_]SystemCall{ print, mem.allocFrame, mem.lockFrame, mem.freeFrame, sched.yield, sched.setPriority, sched.getPriority, sched.sleep, sched.setEventQueue }; pub fn invokeSyscall(number: usize, frame: *platform.Registers, args: *Arguments, retval: *isize) void { if (number >= syscalls.len) { diff --git a/system/init/arch/x86_64/vm.zig b/system/init/arch/x86_64/vm.zig index fdd9d46..8db0547 100644 --- a/system/init/arch/x86_64/vm.zig +++ b/system/init/arch/x86_64/vm.zig @@ -1,5 +1,7 @@ const std = @import("std"); -const kernel = @import("../../kernel.zig"); +const system = @import("system"); + +const syscalls = system.syscalls; const MapError = error{ MemoryAlreadyInUse, @@ -7,7 +9,7 @@ const MapError = error{ OutOfMemory, }; -const PhysFrame = struct { +pub const PhysFrame = struct { address: u64, pub fn virtualAddress(self: *const PhysFrame, base: usize) usize { @@ -105,7 +107,7 @@ fn updatePageTableEntry(entry: *PageTableEntry, phys: PhysFrame, flags: u32) voi fn setUpParentPageTableEntry(mapper: *const MemoryMapper, pte: *PageTableEntry, flags: u32) !void { if (pte.present == 0) { pte.clear(); - const frame = PhysFrame{ .address = try kernel.allocFrame() }; + const frame = PhysFrame{ .address = try syscalls.allocFrame() }; pte.present = 1; pte.setAddress(frame.address); getTable(mapper, pte).* = std.mem.zeroes(PageDirectory); diff --git a/system/init/kernel.zig b/system/init/kernel.zig deleted file mode 100644 index 200518b..0000000 --- a/system/init/kernel.zig +++ /dev/null @@ -1,56 +0,0 @@ -const SystemCall = enum(u64) { - Print, - AllocFrame, - LockFrame, - FreeFrame, - Yield, - SetPriority, - GetPriority, - Sleep, -}; - -const SystemError = error{ - OutOfMemory, -}; - -fn syscall(num: SystemCall, arg: u64) i64 { - return asm volatile ("int $66" - : [result] "=r" (-> i64), - : [num] "{rax}" (@intFromEnum(num)), - [arg] "{rdi}" (arg), - ); -} - -pub fn print(arg: u64) void { - _ = syscall(.Print, arg); -} - -pub fn allocFrame() !usize { - const retval = syscall(.AllocFrame, 0); - if (retval < 0) return error.OutOfMemory; - return @bitCast(retval); -} - -pub fn lockFrame(address: u64) void { - _ = syscall(.LockFrame, address); -} - -pub fn freeFrame(address: u64) void { - _ = syscall(.FreeFrame, address); -} - -pub fn yield() void { - _ = syscall(.Yield, 0); -} - -pub fn setPriority(priority: u8) void { - _ = syscall(.SetPriority, priority); -} - -pub fn getPriority() u8 { - return @truncate(@as(u64, @bitCast(syscall(.GetPriority, 0)))); -} - -pub fn sleep(ms: u64) void { - _ = syscall(.Sleep, ms); -} diff --git a/system/init/main.zig b/system/init/main.zig index b402c07..f4c808d 100644 --- a/system/init/main.zig +++ b/system/init/main.zig @@ -1,14 +1,30 @@ -const kernel = @import("kernel.zig"); +const system = @import("system"); const vm = @import("arch/vm.zig").arch; +const syscalls = system.syscalls; +const buffer = system.ring_buffer; + +// FIXME: Make arch-specific. +const PAGE_SIZE = 4096; + +fn setupKernelRingBuffer(base: u64) !buffer.RingBuffer { + const phys = vm.PhysFrame{ .address = try syscalls.allocFrame() }; + + const data: [*]u8 = @ptrCast(phys.virtualPointer(u8, base)); + + try syscalls.setEventQueue(1, phys.address); + + return buffer.RingBuffer.init(data, PAGE_SIZE, true); +} + export fn _start(base: u64, address: u64) callconv(.C) noreturn { const mapper = vm.MemoryMapper.create(.{ .address = address }, base); - kernel.print(base); - kernel.print(address); - kernel.print(@intFromPtr(mapper.directory)); + syscalls.print(base); + syscalls.print(address); + syscalls.print(@intFromPtr(mapper.directory)); - const phys = kernel.allocFrame() catch { + const phys = syscalls.allocFrame() catch { while (true) {} }; @@ -16,10 +32,17 @@ export fn _start(base: u64, address: u64) callconv(.C) noreturn { while (true) {} }; + var event_queue = setupKernelRingBuffer(base) catch { + while (true) {} + }; + var counter: u64 = 0; while (true) : (counter += 4) { - kernel.sleep(1000); - kernel.print(counter); + syscalls.sleep(1000); + + // Reading a random number from the ring buffer we share with the kernel :D + var data: [1]u8 = .{0}; + if (event_queue.read(@ptrCast(&data), 1)) syscalls.print(data[0]); } } diff --git a/system/lib/kernel.zig b/system/lib/kernel.zig new file mode 100644 index 0000000..44abc67 --- /dev/null +++ b/system/lib/kernel.zig @@ -0,0 +1,16 @@ +pub const SystemCall = enum(u64) { + Print, + AllocFrame, + LockFrame, + FreeFrame, + Yield, + SetPriority, + GetPriority, + Sleep, + SetEventQueue, +}; + +pub const SystemError = error{ + OutOfMemory, + NoSuchThread, +}; diff --git a/system/lib/syscalls.zig b/system/lib/syscalls.zig new file mode 100644 index 0000000..cb16857 --- /dev/null +++ b/system/lib/syscalls.zig @@ -0,0 +1,53 @@ +const kernel = @import("kernel.zig"); +const target = @import("builtin").target; + +fn syscall(num: kernel.SystemCall, arg0: u64, arg1: u64) i64 { + return switch (target.cpu.arch) { + .x86_64 => asm volatile ("int $66" + : [result] "=r" (-> i64), + : [num] "{rax}" (@intFromEnum(num)), + [arg0] "{rdi}" (arg0), + [arg1] "{rsi}" (arg1), + ), + else => @compileError("unsupported architecture"), + }; +} + +pub fn print(arg: u64) void { + _ = syscall(.Print, arg, 0); +} + +pub fn allocFrame() !usize { + const retval = syscall(.AllocFrame, 0, 0); + if (retval < 0) return error.OutOfMemory; + return @bitCast(retval); +} + +pub fn lockFrame(address: u64) void { + _ = syscall(.LockFrame, address, 0); +} + +pub fn freeFrame(address: u64) void { + _ = syscall(.FreeFrame, address, 0); +} + +pub fn yield() void { + _ = syscall(.Yield, 0, 0); +} + +pub fn setPriority(priority: u8) void { + _ = syscall(.SetPriority, priority, 0); +} + +pub fn getPriority() u8 { + return @truncate(@as(u64, @bitCast(syscall(.GetPriority, 0, 0)))); +} + +pub fn sleep(ms: u64) void { + _ = syscall(.Sleep, ms, 0); +} + +pub fn setEventQueue(pid: u64, address: u64) !void { + const retval = syscall(.SetEventQueue, pid, address); + if (retval < 0) return error.NoSuchThread; +} diff --git a/system/lib/system.zig b/system/lib/system.zig index 0a7ccf8..2bc0c1e 100644 --- a/system/lib/system.zig +++ b/system/lib/system.zig @@ -1 +1,3 @@ +pub const kernel = @import("kernel.zig"); pub const ring_buffer = @import("ring_buffer.zig"); +pub const syscalls = @import("syscalls.zig");