diff options
Diffstat (limited to 'src/kernel.zig')
-rw-r--r-- | src/kernel.zig | 198 |
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"); + } +} |