Microkernel thing OS experiment (Zig ⚡)
1pub const aux = @import("aux.zig");
2pub const mm = @import("mm/root.zig");
3pub const scheduler = @import("scheduler.zig");
4pub const loadElf = loader.loadElf;
5const arch = @import("arch");
6const std = @import("std");
7const loader = @import("loader.zig");
8
9// Arch init must set up appropriate fields!
10pub var init_data: aux.InitState = .{};
11
12// Generic bsp init
13pub fn generic_init() callconv(.c) noreturn {
14 const log = std.log.scoped(.generic_init);
15 // First, do early arch init
16 arch.boot.early_init();
17
18 // Now, set up the bootmem and console
19 mm.bootmem.init();
20
21 // Now, do the rest of the arch init
22 arch.boot.bsp_init();
23
24 // Next, set up the console
25 aux.initConsole();
26
27 // Now, set up interrupts
28 arch.interrupts.init();
29 arch.interrupts.init_syscalls();
30
31 log.info("Loading attached tasks...", .{});
32 arch.boot.loadTasks();
33
34 log.info("Dropping to userspace!", .{});
35
36 arch.interrupts.startScheduling();
37}
38
39pub fn loadTask(scratch: *arch.structures.Task, task_slice: []align(4096) u8) void {
40 // 1. Create a user address space
41 var user_ctx = arch.mm.paging.Context.make_user() catch |err| {
42 std.log.err("Failed to make user context! {}", .{err});
43 @panic("make_user_ctx");
44 };
45
46 // 2. Allocate a user stack
47 mm.paging.map(.{
48 .vaddr = 0x7ffe_0000_0000,
49 .size = 65536,
50 .memory_type = .MemoryWriteBack,
51 .perms = .{
52 .x = false,
53 .u = true,
54 .w = true,
55 },
56 .context = &user_ctx,
57 }) catch @panic("couldn't map user stack");
58
59 // 3. Map ELF into address space
60 const entry = loadElf(&user_ctx, task_slice) catch |err| {
61 std.log.err("Couldn't load the root task! {}", .{err});
62 @panic("ggz");
63 };
64 // 4. Add task to scheduler
65 scratch.* = .{
66 .cr3_val = user_ctx.cr3_val,
67 .regs = .default,
68 .rip = entry,
69 .rsp = 0x7ffe_0001_0000,
70 };
71 scheduler.pushTask(scratch);
72}
73
74// std options etc.
75pub const panic = std.debug.FullPanic(aux.panic);
76pub const std_options: std.Options = .{
77 .logFn = aux.logFn,
78 .page_size_min = arch.page_size.min,
79 .page_size_max = arch.page_size.max,
80 .queryPageSize = arch.page_size.get,
81};
82
83comptime {
84 // Entry point (_start)
85 @export(&generic_init, .{ .name = "_start", .linkage = .strong });
86}