aboutsummaryrefslogtreecommitdiff
path: root/src/kernel.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel.zig')
-rw-r--r--src/kernel.zig198
1 files changed, 198 insertions, 0 deletions
diff --git a/src/kernel.zig b/src/kernel.zig
new file mode 100644
index 0000000..3f71c01
--- /dev/null
+++ b/src/kernel.zig
@@ -0,0 +1,198 @@
+// SPDX-FileCopyrightText: 2024 Himbeer <himbeer@disroot.org>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+const std = @import("std");
+
+const Console = @import("lib/Console.zig");
+const hwinfo = @import("lib/hwinfo.zig");
+const instructions = @import("lib/instructions.zig");
+const interrupts = @import("lib/interrupts.zig");
+const mem = @import("lib/mem.zig");
+const paging = @import("lib/paging.zig");
+const pci = @import("lib/pci.zig");
+const plic = @import("lib/plic.zig");
+const process = @import("lib/process.zig");
+
+const Error = error{
+ HartIdOutOfRange,
+};
+
+const HartData = packed struct(usize) {
+ hart_id: u16,
+ reserved: u48,
+
+ pub inline fn loadSScratch() HartData {
+ return asm volatile (
+ \\ csrr %[hart_data], sscratch
+ : [hart_data] "=r" (-> HartData),
+ );
+ }
+
+ pub inline fn storeSScratch(self: HartData) void {
+ asm volatile (
+ \\ csrw sscratch, %[hart_data]
+ :
+ : [hart_data] "r" (self),
+ );
+ }
+};
+
+pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, ret_addr: ?usize) noreturn {
+ _ = &error_return_trace;
+ _ = &ret_addr;
+
+ @setCold(true);
+
+ const console = Console.autoChoose() orelse while (true) asm volatile ("wfi");
+ const w = console.writer();
+
+ w.print("\r\n", .{}) catch while (true) asm volatile ("wfi");
+ w.print("= !! ========== !! =\r\n", .{}) catch while (true) asm volatile ("wfi");
+ w.print("!!! KERNEL PANIC !!!\r\n", .{}) catch while (true) asm volatile ("wfi");
+ w.print("{s}\r\n", .{msg}) catch while (true) asm volatile ("wfi");
+ w.print("= !! ========== !! =\r\n", .{}) catch while (true) asm volatile ("wfi");
+
+ while (true) {
+ asm volatile ("wfi");
+ }
+}
+
+export fn _start() callconv(.Naked) noreturn {
+ // Stack grows down, use (exclusive) end instead of start.
+ asm volatile (
+ \\ .option push
+ \\ .option norelax
+ \\ la gp, _global_pointer
+ \\ .option pop
+ \\
+ \\ la sp, _stack_end
+ \\ j %[function]
+ :
+ : [function] "s" (&kmain),
+ );
+}
+
+fn kmain(hart_id: usize, _: usize) noreturn {
+ run(hart_id) catch |err| std.debug.panic("Hart {d}: {any}", .{ hart_id, err });
+}
+
+fn run(hart_id: usize) !noreturn {
+ if (hart_id > ~@as(u16, 0)) return Error.HartIdOutOfRange;
+
+ const hart_data = HartData{
+ .hart_id = @intCast(hart_id),
+ .reserved = 0,
+ };
+ hart_data.storeSScratch();
+
+ paging.init();
+
+ const kmem: *paging.Table = @alignCast(@ptrCast(try paging.zeroedAlloc(1)));
+
+ try kmem.mapKernel();
+
+ instructions.setSatp(kmem.satp(0));
+
+ asm volatile (
+ \\ la sp, _stack_end
+ \\ j %[function]
+ :
+ : [function] "s" (&pagedStart),
+ );
+
+ unreachable;
+}
+
+fn pagedStart() callconv(.Naked) noreturn {
+ asm volatile (
+ \\ la sp, _stack_end
+ \\ j %[function]
+ :
+ : [function] "s" (&pagedMain),
+ );
+}
+
+fn pagedMain() noreturn {
+ pagedRun() catch |err| std.debug.panic("Paged: {any}", .{err});
+}
+
+fn pagedRun() !noreturn {
+ const console = Console.autoChoose() orelse while (true) asm volatile ("wfi");
+ const w = console.writer();
+
+ try w.print("\r\n", .{});
+ try w.print("Console init\r\n", .{});
+ try w.print("\r\n", .{});
+
+ const hart_data = HartData.loadSScratch();
+
+ try w.print("Hart : {d}\r\n", .{hart_data.hart_id});
+
+ try w.print("Paging : Sv39\r\n", .{});
+
+ interrupts.init();
+ interrupts.setEnabled(interrupts.Enable.all);
+ try w.print("Interrupts : All\r\n", .{});
+
+ try w.print("\r\n", .{});
+
+ var chunk_allocator = try mem.ChunkAllocator(.{ .auto_merge_free = true }).init(128);
+ const allocator = chunk_allocator.allocator();
+
+ try w.print("\r\n", .{});
+ try w.print("===================== Kernel Page Table =====================\r\n", .{});
+ try w.print(".text: 0x{x:0>8} - 0x{x:0>8} -> identity mapped (r-x)\r\n", .{ @intFromPtr(paging.text_start), @intFromPtr(paging.text_end) });
+ try w.print(".rodata: 0x{x:0>8} - 0x{x:0>8} -> identity mapped (r--)\r\n", .{ @intFromPtr(paging.rodata_start), @intFromPtr(paging.rodata_end) });
+ try w.print(".data: 0x{x:0>8} - 0x{x:0>8} -> identity mapped (rw-)\r\n", .{ @intFromPtr(paging.data_start), @intFromPtr(paging.data_end) });
+ try w.print(".sdata: 0x{x:0>8} - 0x{x:0>8} -> identity mapped (rw-)\r\n", .{ @intFromPtr(paging.sdata_start), @intFromPtr(paging.sdata_end) });
+ try w.print(".bss: 0x{x:0>8} - 0x{x:0>8} -> identity mapped (rw-)\r\n", .{ @intFromPtr(paging.bss_start), @intFromPtr(paging.bss_end) });
+ try w.print(".sbss: 0x{x:0>8} - 0x{x:0>8} -> identity mapped (rw-)\r\n", .{ @intFromPtr(paging.sbss_start), @intFromPtr(paging.sbss_end) });
+ try w.print("Stack: 0x{x:0>8} - 0x{x:0>8} -> identity mapped (rw-)\r\n", .{ @intFromPtr(paging.stack_start), @intFromPtr(paging.stack_end) });
+ try w.print("Trap Stack: 0x{x:0>8} - 0x{x:0>8} -> identity mapped (rw-)\r\n", .{ @intFromPtr(paging.stvec_stack_start), @intFromPtr(paging.stvec_stack_end) });
+ try w.print("\r\n", .{});
+ try w.print("Heap: 0x{x:0>8} - 0x{x:0>8} -> identity mapped (rw-)\r\n", .{ @intFromPtr(paging.heap_start), @intFromPtr(paging.heap_end) });
+ try w.print("=============================================================\r\n", .{});
+ try w.print("\r\n", .{});
+
+ try w.print("Timer : {d} Hz\r\n", .{1 / (@as(f64, process.schedule_interval_millis) / 1000)});
+
+ var plic_dev = hwinfo.byKind(.plic);
+ if (try plic_dev.next()) |plic_handle| {
+ _ = &plic_handle;
+ try w.print("PLIC : Disabled\r\n", .{});
+ } else {
+ try w.print("PLIC : Not present\r\n", .{});
+ }
+
+ try w.print("\r\n", .{});
+
+ if (pci.controllerFromHwInfo()) |pci_controller| {
+ try w.print("\r\n", .{});
+
+ for (0..256) |bus| {
+ for (0..32) |device| {
+ const cfg_space = pci_controller.cfgSpace(@intCast(bus), @intCast(device), 0);
+ const vendor_id = cfg_space.getVendorId();
+ const device_id = cfg_space.getDeviceId();
+ const class = cfg_space.getClass();
+ const subclass = cfg_space.getSubclass();
+
+ if (vendor_id != 0xffff) {
+ try w.print("PCI {:0>3}.{:0>3}: Vendor = 0x{x:0>4}, Device = 0x{x:0>4}, Class = 0x{x:0>4}, Subclass = 0x{x:0>4}\r\n", .{ bus, device, vendor_id, device_id, class, subclass });
+ }
+ }
+ }
+
+ try w.print("\r\n", .{});
+ } else {
+ try w.print("PCI not present\r\n", .{});
+ }
+
+ try w.print("Enter process demo\r\n", .{});
+ try process.demo(allocator);
+
+ while (true) {
+ asm volatile ("wfi");
+ }
+}