diff --git a/build.zig b/build.zig index a9ee659..16ed875 100644 --- a/build.zig +++ b/build.zig @@ -19,7 +19,7 @@ pub fn build(b: *std.Build) void { return; }; - // Get the target platform (might be linux or freestanding) + // Get the target platform const plat = config.getPlatform(cfg) catch { b.default_step.dependOn( &b.addFail("Invalid platform (this should not happen!)").step, @@ -48,10 +48,10 @@ pub fn build(b: *std.Build) void { rtl_module.addImport("rtl", rtl_module); - const arch = if (plat.os == .freestanding) switch (plat.arch) { + const arch = switch (plat.arch) { .x86_64 => "amd64", else => @tagName(plat.arch), - } else "um"; + }; const arch_module = b.createModule(.{ .root_source_file = b.path(b.fmt("src/arch/{s}/root.zig", .{arch})), @@ -132,24 +132,22 @@ fn targetQueryForPlatform(plat: config.Platform) std.Target.Query { var q: std.Target.Query = .{ .cpu_arch = plat.arch, .os_tag = plat.os, - .abi = if (plat.os == .freestanding) .none else .gnu, + .abi = .none, .cpu_model = .baseline, }; - if (plat.os == .freestanding) { - switch (plat.arch) { - .x86_64 => { - const f = std.Target.Cpu.Feature.FeatureSetFns(std.Target.x86.Feature); - q.cpu_features_add = f.featureSet(&.{.soft_float}); - q.cpu_features_sub = f.featureSet(&.{ .x87, .mmx, .sse, .sse2 }); - }, - .aarch64 => { - const f = std.Target.Cpu.Feature.FeatureSetFns(std.Target.aarch64.Feature); - q.cpu_features_sub = f.featureSet(&.{ .fp_armv8, .neon }); - }, - .riscv64 => {}, - else => {}, - } + switch (plat.arch) { + .x86_64 => { + const f = std.Target.Cpu.Feature.FeatureSetFns(std.Target.x86.Feature); + q.cpu_features_add = f.featureSet(&.{.soft_float}); + q.cpu_features_sub = f.featureSet(&.{ .x87, .mmx, .sse, .sse2 }); + }, + .aarch64 => { + const f = std.Target.Cpu.Feature.FeatureSetFns(std.Target.aarch64.Feature); + q.cpu_features_sub = f.featureSet(&.{ .fp_armv8, .neon }); + }, + .riscv64 => {}, + else => {}, } return q; @@ -181,59 +179,42 @@ fn addKernel(b: *std.Build, plat: config.Platform, optimize: std.builtin.Optimiz const modules: []const *std.Build.Module = &.{ config_module, ksyms_module, rtl, arch, kernel.root_module }; - if (plat.os == .freestanding) { - kernel.linkage = .static; - kernel.pie = false; + kernel.linkage = .static; + kernel.pie = false; - for (modules) |m| { - m.pic = false; - m.strip = false; - m.stack_check = false; - m.stack_protector = false; - m.unwind_tables = .none; - m.omit_frame_pointer = false; + for (modules) |m| { + m.pic = false; + m.strip = false; + m.stack_check = false; + m.stack_protector = false; + m.unwind_tables = .none; + m.omit_frame_pointer = false; - m.code_model = switch (plat.arch) { - .x86_64 => .kernel, - .riscv64 => .medium, - else => .large, - }; - - switch (plat.arch) { - .x86_64 => { - m.red_zone = false; - }, - else => {}, - } - } - - kernel.entry = .{ .symbol_name = "kmain" }; + m.code_model = switch (plat.arch) { + .x86_64 => .kernel, + .riscv64 => .medium, + else => .large, + }; switch (plat.arch) { .x86_64 => { - kernel.root_module.addAssemblyFile(b.path("src/kern/amd64/locore.s")); - kernel.root_module.addAssemblyFile(b.path("src/platform/pc/ap.s")); + m.red_zone = false; }, else => {}, } - - kernel.linker_script = b.path(b.fmt("build/linker-scripts/{s}.lds", .{@tagName(plat.arch)})); - } else { - const translate_c = b.addTranslateC(.{ - .root_source_file = b.path("src/platform/um/c.h"), - .target = target, - .optimize = optimize, - }); - - translate_c.addIncludePath(.{ .cwd_relative = "/usr/include" }); - - kernel.root_module.addImport("c", translate_c.createModule()); - kernel.linker_script = b.path("build/linker-scripts/uml.lds"); - kernel.root_module.link_libc = true; - kernel.linker_allow_shlib_undefined = true; - kernel.root_module.linkSystemLibrary("sdl2-compat", .{ .use_pkg_config = .force }); - kernel.root_module.addLibraryPath(.{ .cwd_relative = "/usr/lib64" }); } + kernel.entry = .{ .symbol_name = "kmain" }; + + switch (plat.arch) { + .x86_64 => { + kernel.root_module.addAssemblyFile(b.path("src/kern/amd64/locore.s")); + kernel.root_module.addAssemblyFile(b.path("src/platform/pc/ap.s")); + }, + else => {}, + } + + kernel.linker_script = b.path(b.fmt("build/linker-scripts/{s}.lds", .{@tagName(plat.arch)})); + return kernel; } diff --git a/build/config.zig b/build/config.zig index 98dce4a..a6db091 100644 --- a/build/config.zig +++ b/build/config.zig @@ -16,7 +16,6 @@ pub const Platform = struct { const ArchEnum = enum { amd64, aarch64, - um, }; const BootloaderEnum = enum { @@ -38,9 +37,8 @@ pub fn getPlatform(config: Config) !Platform { .arch = switch (config.arch) { .amd64 => .x86_64, .aarch64 => .aarch64, - .um => builtin.cpu.arch, }, - .os = if (config.arch == .um) .linux else .freestanding, + .os = .freestanding, }; if (ret.os == .freestanding and (ret.arch == .x86_64 or ret.arch == .aarch64)) { diff --git a/build/run.zig b/build/run.zig index ca9cef3..c82706f 100644 --- a/build/run.zig +++ b/build/run.zig @@ -47,6 +47,8 @@ pub fn addRun(b: *std.Build, kernel: *std.Build.Step.Compile, plat: config.Platf qemu.addArgs(&.{ "-d", "int", + "-s", + "-S", "-D", "qemu.log", "-no-reboot", @@ -56,7 +58,7 @@ pub fn addRun(b: *std.Build, kernel: *std.Build.Step.Compile, plat: config.Platf switch (plat.arch) { .x86_64 => { - qemu.addArgs(&.{ "-serial", "stdio", "-m", "1G", "-smp", "4" }); + qemu.addArgs(&.{ "-serial", "stdio", "-m", "32M", "-smp", "4" }); if (!debug and builtin.target.os.tag == .linux and builtin.cpu.arch == .x86_64) qemu.addArgs(&.{ "-enable-kvm", "-cpu", "host,+invtsc" }); }, @@ -66,7 +68,5 @@ pub fn addRun(b: *std.Build, kernel: *std.Build.Step.Compile, plat: config.Platf } run_step.dependOn(&qemu.step); - } else { - run_step.dependOn(&b.addRunArtifact(kernel).step); } } diff --git a/config.zig.zon b/config.zig.zon index 162a4ac..24aa38f 100644 --- a/config.zig.zon +++ b/config.zig.zon @@ -9,7 +9,6 @@ .options = .{ .{ .value = "amd64" }, .{ .value = "aarch64" }, - .{ .value = "um", .label = "Usermode (Linux)" }, }, }, .{ @@ -20,11 +19,6 @@ .options = .{ .{ .value = "limine", .label = "Limine" }, }, - .depends_on = .{ - .not = .{ - .key_eq = .{ .key = "arch", .value = "um" }, - }, - }, }, .{ .kind = .menu, @@ -37,7 +31,6 @@ .default = .{ .int = 10 }, .help = "This option sets the default time slice (in milliseconds) used by the scheduler.", }, - .{ .kind = .int, .key = "sched_balance_interval", @@ -45,7 +38,6 @@ .default = .{ .int = 1000 }, .help = "This option sets the rate (in milliseconds) at which thread load balancing is performed.", }, - .{ .kind = .int, .key = "ncpus", @@ -54,7 +46,6 @@ .range = .{ .min = 1, .max = 16384 }, .help = "This option sets the maximum number of CPUs the kernel can support.", }, - .{ .kind = .int, .key = "log_buffer_shift", @@ -62,11 +53,9 @@ .default = .{ .int = 14 }, .help = "This option sets the size of the kernel log buffer as a power of two. The actual size is calculated as 2 raised to the power of this value (i.e., 2^LOG_BUFFER_SHIFT bytes).", }, - .{ .kind = .menu, .label = "Memory Management Options", - .entries = .{ .{ .kind = .menu, diff --git a/src/arch/um/root.zig b/src/arch/um/root.zig deleted file mode 100644 index 98c31d3..0000000 --- a/src/arch/um/root.zig +++ /dev/null @@ -1 +0,0 @@ -pub const name = "um"; diff --git a/src/kern/panic.zig b/src/kern/panic.zig index d52050d..b26526d 100644 --- a/src/kern/panic.zig +++ b/src/kern/panic.zig @@ -87,11 +87,8 @@ pub fn panic_with_frame( pub fn panic( msg: []const u8, - first_trace_addr: ?usize, + _: ?usize, ) noreturn { - if (config.arch == .um) { - std.debug.defaultPanic(msg, first_trace_addr); - } panic_lock.acquire_no_ipl(); panic_with_frame(msg, @frameAddress()); } diff --git a/src/kern/private.zig b/src/kern/private.zig index ffbb087..663ed25 100644 --- a/src/kern/private.zig +++ b/src/kern/private.zig @@ -5,7 +5,6 @@ const rtl = @import("rtl"); pub const impl = switch (config.arch) { .amd64 => @import("amd64/impl.zig"), - .um => @import("um/impl.zig"), else => @compileError("unsupported architecture"), }; diff --git a/src/kern/um/impl.zig b/src/kern/um/impl.zig deleted file mode 100644 index 22cb227..0000000 --- a/src/kern/um/impl.zig +++ /dev/null @@ -1,135 +0,0 @@ -const r = @import("root"); - -const c = r.pl.impl.c; -const ke = r.ke; -const ki = ke.private; - -fn set_signals(enabled: bool) bool { - var newmask: c.sigset_t = undefined; - var oldmask: c.sigset_t = undefined; - - _ = c.sigemptyset(&newmask); - _ = c.sigaddset(&newmask, c.SIGUSR1); - _ = c.sigaddset(&newmask, c.SIGUSR2); - _ = c.sigaddset(&newmask, c.SIGALRM); - - const how = if (enabled) c.SIG_UNBLOCK else c.SIG_BLOCK; - - if (c.pthread_sigmask(how, &newmask, &oldmask) != 0) { - @panic("pthread_sigmask failed"); - } - - return c.sigismember(&oldmask, c.SIGUSR1) == 0; -} - -threadlocal var hardware_ipl: ke.Ipl = .Passive; -threadlocal var interrupts_enabled: bool = true; - -pub fn set_hardware_ipl(ipl: ke.Ipl) void { - hardware_ipl = ipl; - update_signals(); -} - -pub fn disable_interrupts() bool { - const old = interrupts_enabled; - interrupts_enabled = false; - update_signals(); - return old; -} - -pub fn enable_interrupts() bool { - const old = interrupts_enabled; - interrupts_enabled = true; - update_signals(); - return old; -} - -pub fn restore_interrupts(val: bool) void { - interrupts_enabled = val; - update_signals(); -} - -fn update_signals() void { - const should_enable = interrupts_enabled and - @intFromEnum(hardware_ipl) <= @intFromEnum(ke.Ipl.get_max_software()); - _ = set_signals(should_enable); -} - -pub fn send_resched_ipi(cpu: u32) void { - _ = c.pthread_kill(r.pl.impl.percpu.remote(cpu).pthread, c.SIGUSR1); -} - -pub const ThreadContext = struct { - ucontext: c.ucontext_t, - old_lock: ?*ke.SpinLock, - - fn real_entry(entry_int: c_ulong, arg_int: c_ulong) callconv(.c) void { - if (ki.sched.percpu.local().current_thread.?.context.old_lock) |lock| { - lock.release_no_ipl(); - ki.sched.percpu.local().current_thread.?.context.old_lock = null; - } - const entry: *const fn (?*anyopaque) void = @ptrFromInt(entry_int); - const arg: ?*anyopaque = @ptrFromInt(arg_int); - ke.ipl.lower(.Passive); - entry(arg); - } - - pub fn init(stack: r.VAddr, stack_size: usize, entry: *const fn (?*anyopaque) void, arg: ?*anyopaque) ThreadContext { - var new: ThreadContext = .{ .ucontext = undefined, .old_lock = null }; - - if (c.getcontext(&new.ucontext) == -1) { - @panic("getcontext() failed"); - } - - new.ucontext.uc_stack.ss_sp = @ptrFromInt(stack); - new.ucontext.uc_stack.ss_size = stack_size; - - // No successor - new.ucontext.uc_link = null; - - const entry_int: usize = @intFromPtr(entry); - const arg_int: usize = @intFromPtr(arg); - - c.makecontext( - &new.ucontext, - @ptrCast(&real_entry), - 2, - @as(c_ulong, entry_int), - @as(c_ulong, arg_int), - ); - return new; - } - - pub fn load(self: *ThreadContext) void { - _ = c.setcontext(&self.ucontext); - } - - pub fn switch_to(self: *ThreadContext, new: *ThreadContext) void { - const thread: *ke.Thread = @fieldParentPtr("context", self); - new.old_lock = &thread.lock; - - if (c.swapcontext(&self.ucontext, &new.ucontext) == -1) { - @panic("swapcontext() failed"); - } - - if (self.old_lock) |lock| { - self.old_lock = null; - lock.release_no_ipl(); - } - } -}; - -const bootstrap_offsets = [1]usize{0}; - -pub fn early_init() void { - // Ensure we can use per-cpu data. - r.pl.impl.cpu_offsets = @constCast(&bootstrap_offsets); -} - -pub inline fn percpu_ptr_other(variable: anytype, cpu_id: usize) @TypeOf(variable) { - return @ptrFromInt(@intFromPtr(variable) +% r.pl.impl.cpu_offsets[cpu_id]); -} - -pub inline fn percpu_ptr(variable: anytype) @TypeOf(variable) { - return @ptrFromInt(@intFromPtr(variable) +% r.pl.impl.cpu_offsets[r.pl.impl.my_cpu_id]); -} diff --git a/src/mm/init.zig b/src/mm/init.zig index f745242..8c5e805 100644 --- a/src/mm/init.zig +++ b/src/mm/init.zig @@ -103,9 +103,7 @@ fn map_kernel(boot_info: *pl.BootInfo) void { pub fn init(boot_info: *pl.BootInfo) linksection(r.init) void { mi.phys.init(boot_info); - if (config.arch != .um) { - map_kernel(boot_info); - } + map_kernel(boot_info); mi.kernel_space.pmap.activate(); mi.phys.init_pfndb(); mi.zone.early_init(); diff --git a/src/mm/private.zig b/src/mm/private.zig index be42d76..5d6f5f7 100644 --- a/src/mm/private.zig +++ b/src/mm/private.zig @@ -29,7 +29,6 @@ pub const PMapLevel = struct { pub const impl = switch (config.arch) { .amd64 => @import("amd64/impl.zig"), - .um => @import("um/impl.zig"), else => @compileError("unsupported architecture"), }; diff --git a/src/mm/um/impl.zig b/src/mm/um/impl.zig deleted file mode 100644 index 62e4bd5..0000000 --- a/src/mm/um/impl.zig +++ /dev/null @@ -1,80 +0,0 @@ -const r = @import("root"); -const std = @import("std"); -const linux = std.os.linux; - -pub var kernel_heap_base: usize = 0; -pub var pfndb_base: usize = 0; -pub const hhdm_minimum_max_address: usize = 0; - -var page_table: std.AutoHashMap(usize, usize) = .init(std.heap.page_allocator); - -pub fn init_kernel() void { - kernel_heap_base = linux.mmap( - null, - r.gib(8), - .{ .READ = true, .WRITE = true }, - .{ .ANONYMOUS = true, .TYPE = .PRIVATE }, - -1, - 0, - ); - - r.pl.impl.check_function("mmap", kernel_heap_base); - - pfndb_base = linux.mmap( - null, - r.gib(1), - .{ .READ = true, .WRITE = true }, - .{ .ANONYMOUS = true, .TYPE = .PRIVATE }, - -1, - 0, - ); - - r.pl.impl.check_function("mmap", pfndb_base); -} - -pub fn phys_to_virt(pa: usize) usize { - return r.pl.impl.global_state.phys_base + pa; -} - -pub fn virt_to_phys(va: usize) usize { - return va - r.pl.impl.global_state.phys_base; -} - -pub const PMap = struct { - const Self = @This(); - - pub fn map_from(_: *Self, va: r.VAddr, size: usize, source: anytype) void { - var remain = size; - - while (remain > 0) { - const item = source.next(va); - - var posix_flags: std.c.PROT = .{}; - - posix_flags.READ = item.flags.read; - posix_flags.WRITE = item.flags.write; - posix_flags.EXEC = item.flags.execute; - - _ = std.c.mmap( - @ptrFromInt(va), - size, - posix_flags, - .{ .FIXED = true, .TYPE = .PRIVATE }, - r.pl.impl.global_state.phys_memory_memfd, - @bitCast(item.pa), - ); - - page_table.put(va & ~@as(usize, 0xFFF), item.pa) catch unreachable; - - remain -|= item.len; - } - } - - pub fn query(_: *Self, va: r.VAddr) ?r.PAddr { - const page = va & ~@as(usize, 0xFFF); - const pa = page_table.get(page) orelse return null; - return pa; - } - - pub fn activate(_: *Self) void {} -}; diff --git a/src/platform/root.zig b/src/platform/root.zig index 7f20079..0ad0817 100644 --- a/src/platform/root.zig +++ b/src/platform/root.zig @@ -5,7 +5,6 @@ const config = @import("config"); pub const impl = switch (config.arch) { .amd64 => @import("pc/impl.zig"), - .um => @import("um/impl.zig"), else => @compileError("unsupported architecture"), }; diff --git a/src/platform/um/c.h b/src/platform/um/c.h deleted file mode 100644 index 87fa695..0000000 --- a/src/platform/um/c.h +++ /dev/null @@ -1,9 +0,0 @@ -#define _GNU_SOURCE 1 -#include -#include -#include -#include -#include -#include -#include -#include diff --git a/src/platform/um/entry.zig b/src/platform/um/entry.zig deleted file mode 100644 index cf07693..0000000 --- a/src/platform/um/entry.zig +++ /dev/null @@ -1,186 +0,0 @@ -const r = @import("root"); - -pub const std_options = r.std_options; -pub const panic = r.panic; - -const c = @import("c"); -const std = @import("std"); -const ke = r.ke; -const pl = r.pl; - -const default_mem_size = r.gib(1); - -fn parse_mem_size(str: []const u8) !usize { - if (str.len == 0) return default_mem_size; - - const last = str[str.len - 1]; - - const mul: usize = switch (std.ascii.toLower(last)) { - 'k' => r.kib(1), - 'm' => r.mib(1), - 'g' => r.gib(1), - else => 1, - }; - - const digits = if (mul == 1) str else str[0 .. str.len - 1]; - const size = try std.fmt.parseInt(usize, digits, 10); - return size * mul; -} - -var gui_started = std.atomic.Value(bool).init(false); - -fn gui_thread() void { - if (c.SDL_Init(c.SDL_INIT_VIDEO) != 0) { - std.debug.panic("Failed to initialize SDL: {s}\n", .{c.SDL_GetError()}); - } - - const window = c.SDL_CreateWindow( - "Zag (UM)", - c.SDL_WINDOWPOS_UNDEFINED, - c.SDL_WINDOWPOS_UNDEFINED, - 800, - 600, - c.SDL_WINDOW_SHOWN, - ); - - if (window == null) { - std.debug.panic("Failed to create window: {s}\n", .{c.SDL_GetError()}); - } - - const renderer = c.SDL_CreateRenderer(window.?, -1, c.SDL_RENDERER_ACCELERATED); - if (renderer == null) { - std.debug.panic("Failed to create renderer: {s}\n", .{c.SDL_GetError()}); - } - - const fb_surface: ?*c.SDL_Surface = c.SDL_CreateRGBSurface(0, 800, 600, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0); - if (fb_surface == null) { - std.debug.panic("Failed to create surface: {s}\n", .{c - .SDL_GetError()}); - } - - const surface = fb_surface.?; - - const texture = c.SDL_CreateTexture( - renderer.?, - c.SDL_PIXELFORMAT_RGB888, - c.SDL_TEXTUREACCESS_STREAMING, - 800, - 600, - ); - - pl.impl.global_state.boot_info.framebuffer = .{ - .address = @intFromPtr(surface.pixels), - .width = 800, - .height = 600, - .pitch = @intCast(surface.pitch), - .bpp = 32, - }; - - gui_started.store(true, .release); - - // Mask all signals. - var sigset: c.sigset_t = undefined; - _ = c.sigfillset(&sigset); - _ = c.pthread_sigmask(c.SIG_BLOCK, &sigset, null); - - var event: c.SDL_Event = undefined; - var quit = false; - - while (!quit) { - const frame_start = c.SDL_GetTicks(); - - while (c.SDL_PollEvent(&event) != 0) { - if (event.type == c.SDL_QUIT) { - quit = true; - } - } - - // Copy the framebuffer (surface) to a texture and render it. - _ = c.SDL_UpdateTexture(texture, null, surface.pixels, surface.pitch); - _ = c.SDL_RenderClear(renderer.?); - _ = c.SDL_RenderCopy(renderer.?, texture, null, null); - _ = c.SDL_RenderPresent(renderer.?); - - const frame_time = c.SDL_GetTicks() - frame_start; - - if (frame_time < 16) { - c.SDL_Delay(16 - frame_time); - } - } - - _ = c.SDL_DestroyTexture(texture); - - // Exit. - c.SDL_Quit(); - std.process.exit(0); -} - -fn start_gui() void { - _ = std.Thread.spawn(.{ .allocator = std.heap.page_allocator }, gui_thread, .{}) catch unreachable; -} - -pub fn main(init: std.process.Init) !void { - var args = try init.minimal.args.iterateAllocator(init.gpa); - defer args.deinit(); - - const exe = args.next().?; - - var mem_size: usize = default_mem_size; - var cmdline: ?[]const u8 = null; - var ncpus: usize = 1; - var gui = false; - - while (args.next()) |arg| { - if (std.mem.eql(u8, arg, "-m") or std.mem.eql(u8, arg, "--mem-size")) { - const val = args.next() orelse fatal("--mem-size requires a value", .{}); - mem_size = parse_mem_size(val) catch fatal("invalid mem-size", .{}); - } else if (std.mem.eql(u8, arg, "-c") or std.mem.eql(u8, arg, "--cmdline")) { - cmdline = args.next() orelse fatal("--cmdline requires a value", .{}); - } else if (std.mem.eql(u8, arg, "-t") or std.mem.eql(u8, arg, "--threads")) { - const val = args.next() orelse fatal("--threads requires a value", .{}); - ncpus = std.fmt.parseInt(usize, val, 10) catch fatal("invalid thread count", .{}); - } else if (std.mem.eql(u8, arg, "-g") or std.mem.eql(u8, arg, "--gui")) { - gui = true; - } else if (std.mem.eql(u8, arg, "--help") or std.mem.eql(u8, arg, "-h")) { - var stderr = std.Io.File.stderr().writerStreaming(init.io, &.{}); - var w = &stderr.interface; - - try w.print( - \\Usage: {s} [options] - \\ -m, --mem-size SIZE Set the memory size - \\ -c, --cmdline STR Set the kernel cmdline - \\ -t, --threads COUNT Set the number of threads - \\ -g, --gui, Enable graphics mode using SDL2 - \\ - , .{exe}); - std.process.exit(0); - } else { - fatal("unknown argument: {s}", .{arg}); - } - } - - pl.impl.global_state.params = - .{ .ncpus = ncpus, .cmdline = cmdline, .mem_size = mem_size }; - - pl.impl.global_state.boot_info.kernel_address.physical_base = 0; - pl.impl.global_state.boot_info.kernel_address.virtual_base = 0; - - pl.impl.global_state.boot_info.rsdp = 0; - pl.impl.global_state.boot_info.cmdline = cmdline; - - if (gui) { - start_gui(); - while (gui_started.load(.monotonic) != true) { - std.atomic.spinLoopHint(); - } - } - - ke.ncpus = ncpus; - - ke.private.init(&pl.impl.global_state.boot_info); -} - -fn fatal(comptime fmt: []const u8, args: anytype) noreturn { - std.debug.print(fmt ++ "\n", args); - std.process.exit(1); -} diff --git a/src/platform/um/impl.zig b/src/platform/um/impl.zig deleted file mode 100644 index e0aee58..0000000 --- a/src/platform/um/impl.zig +++ /dev/null @@ -1,206 +0,0 @@ -const std = @import("std"); -const linux = std.os.linux; -const r = @import("root"); -const pl = r.pl; -const ke = r.ke; -const ki = r.ke.private; -const posix = std.posix; - -pub const entry = @import("entry.zig"); - -const timer = @import("timer.zig"); - -pub const c = @import("c"); - -pub const name = "User-Mode"; - -pub const GlobalState = struct { - const Params = struct { - mem_size: usize, - cmdline: ?[]const u8, - ncpus: usize, - }; - - params: Params, - boot_info: pl.BootInfo, - phys_memory_memfd: i32, - phys_base: usize, -}; - -pub const CpuState = struct { - pthread: c.pthread_t, - td: *ke.Thread, -}; - -pub var global_state: GlobalState = undefined; -pub threadlocal var my_cpu_id: usize = 0; -pub const percpu = ke.CpuLocal(CpuState, undefined); - -pub fn debug_write(char: u8) void { - _ = linux.write(linux.STDERR_FILENO, @ptrCast(&char), 1); -} - -pub const arm_timer = timer.arm_timer; - -pub fn check_function(fn_name: []const u8, ret: usize) void { - const real_ret: isize = @bitCast(ret); - - if (real_ret < 0) { - const errno_val = linux.errno(ret); - - std.debug.print("error: {s}: {s}\n", .{ fn_name, @tagName(errno_val) }); - std.process.exit(1); - } -} - -pub var cpu_offsets: []usize = undefined; - -pub fn early_init(_: *pl.BootInfo) linksection(r.init) void { - percpu.local().pthread = c.pthread_self(); - my_cpu_id = 0; - - const memfd: i32 = @intCast(linux.memfd_create("phys_memory", 0)); - - check_function("ftruncate", linux.ftruncate(memfd, @intCast(global_state.params.mem_size))); - - const phys_base = linux.mmap(null, global_state.params.mem_size, .{ .READ = true, .WRITE = true }, .{ .TYPE = .SHARED }, memfd, 0); - - check_function("mmap", phys_base); - - // Build memory map - global_state.boot_info.memory_map.entry_count = 1; - global_state.boot_info.memory_map.entries[0].base = 0; - global_state.boot_info.memory_map.entries[0].size = global_state.params.mem_size; - global_state.boot_info.memory_map.entries[0].type = .Free; - - global_state.phys_memory_memfd = memfd; - global_state.phys_base = phys_base; - - const pfndb_base = linux.mmap(null, r.tib(1), .{}, .{ .ANONYMOUS = true, .TYPE = .PRIVATE }, -1, 0); - - check_function("mmap", pfndb_base); - - const heap_base = linux.mmap(null, r.gib(8), .{}, .{ .ANONYMOUS = true, .TYPE = .PRIVATE }, -1, 0); - - check_function("mmap", heap_base); - - r.kernel_pfndb_base = pfndb_base; - r.kernel_heap_base = heap_base; - - std.log.info("um: kernel heap lives at {X}", .{heap_base}); -} - -fn sigusr1_handler(_: posix.SIG, _: *const posix.siginfo_t, _: ?*anyopaque) callconv(.c) void { - if (@intFromEnum(ki.ipl.current()) < @intFromEnum(ke.Ipl.Dispatch) and ki.ipl.is_softint_pending(.Dispatch)) { - ki.dpc.dispatch(ke.cpu.current()); - } -} - -fn make_thread(entrypoint: *const fn (?*anyopaque) void, td: *ke.Thread) void { - const stack = std.heap.page_allocator.alloc(u8, 16384) catch @panic("wtf"); - - td.init(@intFromPtr(stack.ptr), 16384, entrypoint, null); - - td.base_priority = ke.Thread.Priority.idle; - td.priority = td.base_priority; - td.pinned = true; -} - -var cpus_up = std.atomic.Value(usize).init(0); - -fn other_cpu_entry(_: ?*anyopaque) callconv(.c) ?*anyopaque { - my_cpu_id = cpus_up.fetchAdd(1, .monotonic) + 1; - - percpu.local().pthread = c.pthread_self(); - - ki.cpu.init_cpu(@intCast(my_cpu_id)); - - ki.sched.percpu.local().current_thread = percpu.local().td; - ki.sched.percpu.local().idle_thread = percpu.local().td; - - timer.init_cpu(); - - while (true) {} - - return null; -} - -var cpu: ke.Cpu linksection(r.percpu) = undefined; - -fn idle(_: ?*anyopaque) void { - while (true) { - std.atomic.spinLoopHint(); - } -} - -extern var __percpu_start: u8; -extern var __percpu_end: u8; - -pub fn late_init(_: *pl.BootInfo) linksection(r.init) void { - timer.init(); - timer.init_cpu(); - - var sa: posix.Sigaction = std.mem.zeroes(posix.Sigaction); - sa.handler = .{ - .sigaction = sigusr1_handler, - }; - - sa.flags = posix.SA.SIGINFO; - - sa.mask = posix.sigemptyset(); - - _ = posix.sigaction(posix.SIG.USR1, &sa, null); - - std.log.info("um: starting {} thread{s}", .{ - ke.ncpus - 1, - if ((ke.ncpus - 1) > 1) "s" else "", - }); - - const other_count = ke.ncpus - 1; - - const allocator = std.heap.page_allocator; - - var other_threads = - allocator.alloc(c.pthread_t, other_count) catch @panic("oom"); - - cpu_offsets = allocator.alloc(usize, ke.ncpus) catch @panic("oom"); - cpu_offsets[0] = 0; - - const size = @intFromPtr(&__percpu_end) - @intFromPtr(&__percpu_start); - - for (1..ke.ncpus) |i| { - const block = allocator.alloc(u8, size) catch @panic("oom"); - cpu_offsets[i] = @intFromPtr(block.ptr) -% @intFromPtr(&__percpu_start); - - @memcpy(block, @as([*]u8, @ptrCast(&__percpu_start))[0..size]); - - const td = allocator.create(ke.Thread) catch @panic("oom"); - make_thread(idle, td); - percpu.remote(@intCast(i)).td = td; - - var attr: c.pthread_attr_t = undefined; - - _ = c.pthread_attr_init(&attr); - - var cpuset: c.cpu_set_t = std.mem.zeroes(c.cpu_set_t); - cpuset.__bits[i / 64] |= @as(c_ulong, 1) << @intCast(i % 64); - _ = c.pthread_attr_setaffinity_np(&attr, @sizeOf(c.cpu_set_t), &cpuset); - - const ret = c.pthread_create( - &other_threads[i - 1], - &attr, - other_cpu_entry, - null, - ); - - if (ret != 0) { - @panic("pthread_create() failed"); - } - } - - if (ke.ncpus > 1) { - while (cpus_up.load(.monotonic) < @as(u32, @intCast(ke.ncpus - 1))) { - std.atomic.spinLoopHint(); - } - } -} diff --git a/src/platform/um/timer.zig b/src/platform/um/timer.zig deleted file mode 100644 index 8d4d1b7..0000000 --- a/src/platform/um/timer.zig +++ /dev/null @@ -1,75 +0,0 @@ -const r = @import("root"); -const std = @import("std"); -const posix = std.posix; -const linux = std.os.linux; -const c = r.pl.impl.c; -const ke = r.ke; -const ki = ke.private; - -threadlocal var timerid: c.timer_t = undefined; - -fn timer_handler(_: posix.SIG, _: *const posix.siginfo_t, _: ?*anyopaque) callconv(.c) void { - const old_ipl = ke.ipl.set_hardware(.Device); - - ki.timer.clock(); - - _ = ke.ipl.set_hardware(old_ipl); - - if (@intFromEnum(old_ipl) < @intFromEnum(ke.Ipl.Dispatch) and ki.ipl.is_softint_pending(.Dispatch)) { - ki.dpc.dispatch(ke.cpu.current()); - } -} - -pub fn arm_timer(ns: r.Nanoseconds) void { - const value: c.struct_itimerspec = .{ .it_value = .{ - .tv_sec = @intCast(ns / std.time.ns_per_s), - .tv_nsec = @intCast(ns % std.time.ns_per_s), - }, .it_interval = .{ .tv_sec = 0, .tv_nsec = 0 } }; - - if (c.timer_settime(timerid, 0, &value, null) == -1) { - @panic("timer_settime failed"); - } -} - -fn tc_read() u64 { - var ts: std.c.timespec = undefined; - - _ = linux.clock_gettime(linux.CLOCK.MONOTONIC, &ts); - - return @intCast(ts.sec * std.time.ns_per_s + ts.nsec); -} - -var tc: ke.TimeCounter = .{ - .read_count = tc_read, - .frequency = std.time.ns_per_s, - .name = "CLOCK_MONOTONIC", - .quality = 1000, - .mask = std.math.maxInt(u64), - .p = 0, - .n = 0, -}; - -pub fn init() void { - var act = std.mem.zeroes(posix.Sigaction); - - act.handler.sigaction = timer_handler; - act.flags = posix.SA.RESTART | posix.SA.SIGINFO; - - act.mask = posix.sigfillset(); - - posix.sigaction(posix.SIG.ALRM, &act, null); - - ke.time.register_source(&tc); -} - -pub fn init_cpu() void { - var sev: c.sigevent = std.mem.zeroes(c.sigevent); - - sev.sigev_notify = c.SIGEV_THREAD_ID; - sev.sigev_signo = c.SIGALRM; - sev._sigev_un._tid = linux.gettid(); - - if (c.timer_create(c.CLOCK_MONOTONIC, &sev, &timerid) == -1) { - @panic("timer_create failed"); - } -} diff --git a/src/root.zig b/src/root.zig index 56a2b55..39fe227 100644 --- a/src/root.zig +++ b/src/root.zig @@ -56,8 +56,6 @@ pub const std_options = std.Options{ pub const panic = std.debug.FullPanic(ke.panic); -pub const main = if (config.arch == .um) pl.impl.entry.main else undefined; - comptime { // Ensure the entry point is linked in. _ = @import("boot/limine/entry.zig");