// SPDX-FileCopyrightText: 2024 Himbeer // // SPDX-License-Identifier: AGPL-3.0-or-later const std = @import("std"); const debug_console = @import("sbi/debug_console.zig"); const fdt = @import("fdt.zig"); const instructions = @import("instructions.zig"); const interrupts = @import("interrupts.zig"); const mem = @import("mem.zig"); const paging = @import("paging.zig"); const pci = @import("pci.zig"); export fn start() callconv(.Naked) noreturn { // Stack grows down, use (exclusive) end instead of start. asm volatile ( \\ la sp, _stack_end \\ call %[function] : : [function] "s" (&kmain), ); } fn kmain(hart_id: usize, fdt_blob: *fdt.RawHeader) noreturn { const w = debug_console.writer() catch while (true) {}; w.print("Kernel init\r\n", .{}) catch while (true) {}; run(hart_id, fdt_blob, w) catch |err| { w.print("Fatal error: {any}\r\n", .{err}) catch while (true) {}; while (true) {} }; } fn run(hart_id: usize, fdt_blob: *fdt.RawHeader, w: debug_console.Writer) !noreturn { try w.print("\r\n", .{}); try w.print("Hart : {d}\r\n", .{hart_id}); try w.print("FDT address : 0x{x:0>8}\r\n", .{@intFromPtr(fdt_blob)}); const dt_header = try fdt.Header.parse(fdt_blob); paging.init(); const kmem: *paging.Table = @alignCast(@ptrCast(try paging.zeroedAlloc(1))); try w.print("\r\n", .{}); try w.print("===================== Kernel Page Table =====================\r\n", .{}); try w.print("MMIO: 0x{x:0>8} - 0x{x:0>8} -> identity mapped (rw-)\r\n", .{ paging.mmio_start, paging.mmio_end }); try w.print("\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(".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("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("\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("FDT: 0x{x:0>8} - 0x{x:0>8} -> identity mapped (r--)\r\n", .{ @intFromPtr(fdt_blob), @intFromPtr(fdt_blob) + dt_header.total_size }); try w.print("=============================================================\r\n", .{}); try w.print("\r\n", .{}); try kmem.identityMapRange(paging.mmio_start, paging.mmio_end, paging.EntryFlags.readWrite); try kmem.identityMapRange(@intFromPtr(paging.text_start), @intFromPtr(paging.text_end), paging.EntryFlags.readExec); try kmem.identityMapRange(@intFromPtr(paging.rodata_start), @intFromPtr(paging.rodata_end), paging.EntryFlags.readOnly); try kmem.identityMapRange(@intFromPtr(paging.data_start), @intFromPtr(paging.data_end), paging.EntryFlags.readWrite); try kmem.identityMapRange(@intFromPtr(paging.bss_start), @intFromPtr(paging.bss_end), paging.EntryFlags.readWrite); try kmem.identityMapRange(@intFromPtr(paging.stack_start), @intFromPtr(paging.stack_end), paging.EntryFlags.readWrite); try kmem.identityMapRange(@intFromPtr(paging.heap_start), @intFromPtr(paging.heap_end), paging.EntryFlags.readWrite); try kmem.identityMapRange(@intFromPtr(fdt_blob), @intFromPtr(fdt_blob) + dt_header.total_size, paging.EntryFlags.readOnly); instructions.setSatp(kmem.satp(0)); 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(64); const allocator = chunk_allocator.allocator(); try w.print("Parse FDT\r\n", .{}); const dt = try dt_header.parseTree(allocator); try w.print("Locate PCI MMIO\r\n", .{}); const pci_controller = try pci.controllerFromFdt(&dt); 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", .{}); try w.print("Deref 0x1\r\n", .{}); @as(*volatile u8, @ptrFromInt(0x1)).* = 0; try w.print("Segfault successful\r\n", .{}); while (true) { asm volatile ("wfi"); } }