From f41ad7e747c6fb17e7a1cfc30d92290a1d48f779 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Fri, 7 Mar 2025 18:00:00 +0100 Subject: [PATCH] system+init+memory: Add basic IPC code --- system/init/main.zig | 54 +++++++++++++++++++++++++++++++++++++++--- system/lib/ipc.zig | 38 +++++++++++++++++++++++++++++ system/lib/system.zig | 1 + system/memory/main.zig | 9 ++++++- 4 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 system/lib/ipc.zig diff --git a/system/init/main.zig b/system/init/main.zig index 05121c3..a59c8fe 100644 --- a/system/init/main.zig +++ b/system/init/main.zig @@ -3,9 +3,9 @@ const system = @import("system"); const vm = system.vm; const syscalls = system.syscalls; const buffer = system.ring_buffer; +const heap = system.heap; -// FIXME: Make arch-specific. -const PAGE_SIZE = 4096; +const PAGE_SIZE = vm.PAGE_SIZE; fn setupKernelRingBuffer(base: u64) !buffer.RingBuffer { const phys = vm.PhysFrame{ .address = try syscalls.allocFrame() }; @@ -33,6 +33,44 @@ fn discoverThreadLimit() u64 { } } +fn setupKernelRingBufferForThread(mapper: *const vm.MemoryMapper, pid: u64, virt: u64) !void { + const phys = vm.PhysFrame{ .address = try syscalls.allocFrame() }; + + try vm.map(mapper, virt, phys, @intFromEnum(vm.Flags.User) | @intFromEnum(vm.Flags.ReadWrite) | @intFromEnum(vm.Flags.NoExecute)); + + try syscalls.setEventQueue(pid, phys.address); +} + +fn setupRingBufferForThread(mapper: *const vm.MemoryMapper, base: u64, virt: u64) !buffer.RingBuffer { + const phys = vm.PhysFrame{ .address = try syscalls.allocFrame() }; + + try vm.map(mapper, virt, phys, @intFromEnum(vm.Flags.User) | @intFromEnum(vm.Flags.ReadWrite) | @intFromEnum(vm.Flags.NoExecute)); + + const data: [*]u8 = @ptrCast(phys.virtualPointer(u8, base)); + + return buffer.RingBuffer.init(data, PAGE_SIZE, true); +} + +fn setupThread(pid: u64, base: u64) !system.ipc.Connection { + const space = try syscalls.getAddressSpace(pid); + const mapper = vm.MemoryMapper.create(.{ .address = space }, base); + + const ipc_base = 0x1000; // FIXME: Find a good place in the address space and guarantee this is free. + + try setupKernelRingBufferForThread(&mapper, pid, ipc_base + system.ipc.KERNEL_BUFFER_ADDRESS_OFFSET); + // INIT_WRITE and INIT_READ are inverted here because when the process writes, init reads. + const read_buffer = try setupRingBufferForThread(&mapper, base, ipc_base + system.ipc.INIT_WRITE_BUFFER_ADDRESS_OFFSET); + const write_buffer = try setupRingBufferForThread(&mapper, base, ipc_base + system.ipc.INIT_READ_BUFFER_ADDRESS_OFFSET); + + const connection: system.ipc.Connection = .{ .pid = pid, .read_buffer = read_buffer, .write_buffer = write_buffer }; + + try syscalls.setThreadArguments(pid, base, ipc_base); + + try syscalls.startThread(pid); + + return connection; +} + export fn _start(base: u64, address: u64) callconv(.C) noreturn { setTokens(); @@ -42,15 +80,25 @@ export fn _start(base: u64, address: u64) callconv(.C) noreturn { const threads = discoverThreadLimit(); syscalls.print(threads); + const pid: u64 = 2; + var connection = setupThread(pid, base) catch { + while (true) {} + }; + const event_queue = setupKernelRingBuffer(base) catch { while (true) {} }; - _ = event_queue; + system.ipc.setKernelBuffer(event_queue); var counter: u64 = 0; while (true) : (counter += 4) { + var data: u8 = undefined; + if (connection.read_buffer.read(@ptrCast(&data), 1)) { + syscalls.print(data); + } + syscalls.sleep(1000); syscalls.print(counter); } diff --git a/system/lib/ipc.zig b/system/lib/ipc.zig new file mode 100644 index 0000000..eca8a85 --- /dev/null +++ b/system/lib/ipc.zig @@ -0,0 +1,38 @@ +const buffer = @import("ring_buffer.zig"); +const vm = @import("arch/vm.zig"); + +pub const Connection = struct { + pid: u64, + read_buffer: buffer.RingBuffer, + write_buffer: buffer.RingBuffer, +}; + +pub const KERNEL_BUFFER_ADDRESS_OFFSET = 0x0000; +pub const INIT_WRITE_BUFFER_ADDRESS_OFFSET = 0x1000; +pub const INIT_READ_BUFFER_ADDRESS_OFFSET = 0x2000; + +var kernel_buffer: ?buffer.RingBuffer = null; + +pub fn setKernelBuffer(buf: buffer.RingBuffer) void { + kernel_buffer = buf; +} + +pub fn getKernelBuffer() ?buffer.RingBuffer { + return kernel_buffer; +} + +const PAGE_SIZE = vm.PAGE_SIZE; + +fn createPageBufferFromAddress(address: u64) buffer.RingBuffer { + const data: [*]u8 = @ptrFromInt(address); + + return buffer.RingBuffer.init(data, PAGE_SIZE, false); +} + +pub fn readInitBuffers(base_address: u64) Connection { + kernel_buffer = createPageBufferFromAddress(base_address + KERNEL_BUFFER_ADDRESS_OFFSET); + const read_buffer = createPageBufferFromAddress(base_address + INIT_READ_BUFFER_ADDRESS_OFFSET); + const write_buffer = createPageBufferFromAddress(base_address + INIT_WRITE_BUFFER_ADDRESS_OFFSET); + + return .{ .pid = 0, .read_buffer = read_buffer, .write_buffer = write_buffer }; +} diff --git a/system/lib/system.zig b/system/lib/system.zig index e1305a6..24e2d73 100644 --- a/system/lib/system.zig +++ b/system/lib/system.zig @@ -2,4 +2,5 @@ pub const kernel = @import("kernel.zig"); pub const ring_buffer = @import("ring_buffer.zig"); pub const syscalls = @import("syscalls.zig"); pub const vm = @import("arch/vm.zig"); +pub const ipc = @import("ipc.zig"); pub const heap = @import("heap.zig"); diff --git a/system/memory/main.zig b/system/memory/main.zig index 32bee9e..7b16ba4 100644 --- a/system/memory/main.zig +++ b/system/memory/main.zig @@ -9,8 +9,15 @@ fn setTokens() void { syscalls.setTokens(syscalls.getThreadId(), tokens) catch {}; } -export fn _start(_: u64, _: u64) callconv(.C) noreturn { +export fn _start(_: u64, ipc_base: u64) callconv(.C) noreturn { setTokens(); + var connection = system.ipc.readInitBuffers(ipc_base); + + const byte: u8 = 127; + + _ = connection.write_buffer.write(@ptrCast(&byte), 1); + syscalls.yield(); + while (true) {} }