diff --git a/src/kern/init.zig b/src/kern/init.zig index c41dc81..6ca5a11 100644 --- a/src/kern/init.zig +++ b/src/kern/init.zig @@ -10,8 +10,8 @@ var thread0: ke.Thread = undefined; var stack: [8192]u8 align(16) = undefined; pub fn init(boot_info: *pl.BootInfo) linksection(b.init) void { - std.log.info("hello, world", .{}); ki.impl.early_init(); + std.log.info("hello, world", .{}); pl.early_init(boot_info); ki.cpu.init_cpu(0); diff --git a/src/kern/um/impl.zig b/src/kern/um/impl.zig index cb73c77..8f3a411 100644 --- a/src/kern/um/impl.zig +++ b/src/kern/um/impl.zig @@ -99,6 +99,13 @@ pub const ThreadContext = struct { } }; +const bootstrap_offsets = [1]usize{0}; + +pub fn early_init() void { + // Ensure we can use per-cpu data. + b.pl.impl.cpu_offsets = @constCast(&bootstrap_offsets); +} + pub inline fn percpu_ptr_other(variable: anytype, cpu_id: usize) @TypeOf(variable) { return @ptrFromInt(@intFromPtr(variable) +% b.pl.impl.cpu_offsets[cpu_id]); } diff --git a/src/mm/init.zig b/src/mm/init.zig index cb05b0d..05b2b71 100644 --- a/src/mm/init.zig +++ b/src/mm/init.zig @@ -2,83 +2,90 @@ const b = @import("base"); const pl = b.pl; const mm = b.mm; const mi = mm.private; +const config = @import("config"); -extern var text_start_addr: u8; -extern var text_end_addr: u8; -extern var rodata_start_addr: u8; -extern var rodata_end_addr: u8; -extern var data_start_addr: u8; -extern var data_end_addr: u8; +const is_um = @hasDecl(config, "CONFIG_ARCH_UM"); -fn map_kernel(boot_info: *pl.BootInfo) void { - const kaddr = boot_info.kernel_address; +pub const map_kernel = if (!is_um) + struct { + extern var text_start_addr: u8; + extern var text_end_addr: u8; + extern var rodata_start_addr: u8; + extern var rodata_end_addr: u8; + extern var data_start_addr: u8; + extern var data_end_addr: u8; + pub fn call(boot_info: *pl.BootInfo) void { + const kaddr = boot_info.kernel_address; - const text_start = @intFromPtr(&text_start_addr); - const text_end = @intFromPtr(&text_end_addr); - const rodata_start = @intFromPtr(&rodata_start_addr); - const rodata_end = @intFromPtr(&rodata_end_addr); - const data_start = @intFromPtr(&data_start_addr); - const data_end = @intFromPtr(&data_end_addr); + const text_start = @intFromPtr(&text_start_addr); + const text_end = @intFromPtr(&text_end_addr); + const rodata_start = @intFromPtr(&rodata_start_addr); + const rodata_end = @intFromPtr(&rodata_end_addr); + const data_start = @intFromPtr(&data_start_addr); + const data_end = @intFromPtr(&data_end_addr); - const text_size = text_end - text_start; - const rodata_size = rodata_end - rodata_start; - const data_size = data_end - data_start; + const text_size = text_end - text_start; + const rodata_size = rodata_end - rodata_start; + const data_size = data_end - data_start; - mi.kernel_pmap.map_contiguous_range(text_start, kaddr.physical_base + (text_start - kaddr.virtual_base), text_size, .{ - .read = true, - .execute = true, - .global = true, - }); + mi.kernel_pmap.map_contiguous_range(text_start, kaddr.physical_base + (text_start - kaddr.virtual_base), text_size, .{ + .read = true, + .execute = true, + .global = true, + }); - mi.kernel_pmap.map_contiguous_range(rodata_start, kaddr.physical_base + (rodata_start - kaddr.virtual_base), rodata_size, .{ - .read = true, - .global = true, - }); + mi.kernel_pmap.map_contiguous_range(rodata_start, kaddr.physical_base + (rodata_start - kaddr.virtual_base), rodata_size, .{ + .read = true, + .global = true, + }); - mi.kernel_pmap.map_contiguous_range(data_start, kaddr.physical_base + (data_start - kaddr.virtual_base), data_size, .{ - .read = true, - .write = true, - .global = true, - }); + mi.kernel_pmap.map_contiguous_range(data_start, kaddr.physical_base + (data_start - kaddr.virtual_base), data_size, .{ + .read = true, + .write = true, + .global = true, + }); - mi.kernel_pmap.map_contiguous_range(mm.p2v(0), 0, mi.impl.hhdm_minimum_max_address, .{ - .read = true, - .write = true, - .global = true, - }); + mi.kernel_pmap.map_contiguous_range(mm.p2v(0), 0, mi.impl.hhdm_minimum_max_address, .{ + .read = true, + .write = true, + .global = true, + }); - // Now go through every usable entry and map to the HHDM every part that isnt covered by [0, hhdm_minimum_max_address). - // We can't blindly map until the maximum usable physical address because on some CPUs this might cause MCEs. - // See https://github.com/torvalds/linux/commit/66520ebc2df3fe52eb4792f8101fac573b766baf - for (0..boot_info.memory_map.entry_count) |i| { - const entry = boot_info.memory_map.entries[i]; + // Now go through every usable entry and map to the HHDM every part that isnt covered by [0, hhdm_minimum_max_address). + // We can't blindly map until the maximum usable physical address because on some CPUs this might cause MCEs. + // See https://github.com/torvalds/linux/commit/66520ebc2df3fe52eb4792f8101fac573b766baf + for (0..boot_info.memory_map.entry_count) |i| { + const entry = boot_info.memory_map.entries[i]; - if ((entry.type != .Free and entry.type != .LoaderReclaimable) or entry.size < mm.page_size) { - continue; + if ((entry.type != .Free and entry.type != .LoaderReclaimable) or entry.size < mm.page_size) { + continue; + } + + if (entry.base + entry.size <= mi.impl.hhdm_minimum_max_address) { + continue; + } + + var entry_start = entry.base; + var entry_size = entry.size; + + if (entry.base < mi.impl.hhdm_minimum_max_address) { + const adjust = mi.impl.hhdm_minimum_max_address - entry.base; + entry_start += adjust; + entry_size -= adjust; + } + + mi.kernel_pmap.map_contiguous_range(mm.p2v(entry_start), entry_start, entry_size, .{ + .read = true, + .write = true, + .global = true, + }); + } } - - if (entry.base + entry.size <= mi.impl.hhdm_minimum_max_address) { - continue; - } - - var entry_start = entry.base; - var entry_size = entry.size; - - if (entry.base < mi.impl.hhdm_minimum_max_address) { - const adjust = mi.impl.hhdm_minimum_max_address - entry.base; - entry_start += adjust; - entry_size -= adjust; - } - - mi.kernel_pmap.map_contiguous_range(mm.p2v(entry_start), entry_start, entry_size, .{ - .read = true, - .write = true, - .global = true, - }); - } -} - -const std = @import("std"); + }.call +else + struct { + pub fn call(_: *pl.BootInfo) void {} + }.call; pub fn init(boot_info: *pl.BootInfo) linksection(b.init) void { mi.phys.init(boot_info); diff --git a/src/mm/private.zig b/src/mm/private.zig index 7c90960..a11741d 100644 --- a/src/mm/private.zig +++ b/src/mm/private.zig @@ -10,6 +10,8 @@ pub const PMap = pmap.PMap; pub const impl = if (@hasDecl(config, "CONFIG_ARCH_AMD64")) @import("amd64/impl.zig") +else if (@hasDecl(config, "CONFIG_ARCH_UM")) + @import("um/impl.zig") else @compileError("unsupported architecture"); diff --git a/src/mm/um/impl.zig b/src/mm/um/impl.zig new file mode 100644 index 0000000..1fb88ee --- /dev/null +++ b/src/mm/um/impl.zig @@ -0,0 +1,70 @@ +const b = @import("base"); +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; + +pub fn init_kernel() void { + kernel_heap_base = linux.mmap( + null, + b.gib(8), + .{ .READ = true, .WRITE = true }, + .{ .ANONYMOUS = true, .TYPE = .PRIVATE }, + -1, + 0, + ); + + b.pl.impl.check_function("mmap", kernel_heap_base); + + pfndb_base = linux.mmap( + null, + b.gib(1), + .{ .READ = true, .WRITE = true }, + .{ .ANONYMOUS = true, .TYPE = .PRIVATE }, + -1, + 0, + ); + + b.pl.impl.check_function("mmap", pfndb_base); +} + +pub fn phys_to_virt(pa: usize) usize { + return b.pl.impl.global_state.phys_base + pa; +} + +pub fn virt_to_phys(va: usize) usize { + return va - b.pl.impl.global_state.phys_base; +} + +pub const PMap = struct { + const Self = @This(); + + pub fn map_from(_: *Self, va: b.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 }, + b.pl.impl.global_state.phys_memory_memfd, + @bitCast(item.pa), + ); + + remain -|= item.len; + } + } + + pub fn activate(_: *Self) void {} +}; diff --git a/src/platform/um/impl.zig b/src/platform/um/impl.zig index 3d7c260..4507b69 100644 --- a/src/platform/um/impl.zig +++ b/src/platform/um/impl.zig @@ -48,8 +48,8 @@ pub fn debug_write(char: u8) void { pub const arm_timer = timer.arm_timer; -fn check_function(fn_name: []const u8, ret: usize) void { - const real_ret: i64 = @intCast(ret); +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); @@ -59,14 +59,9 @@ fn check_function(fn_name: []const u8, ret: usize) void { } } -const bootstrap_offsets = [1]usize{0}; - pub var cpu_offsets: []usize = undefined; -pub fn early_init() linksection(b.init) void { - // Ensure we can use per-cpu data. - cpu_offsets = @constCast(&bootstrap_offsets); - +pub fn early_init(_: *pl.BootInfo) linksection(b.init) void { percpu.local().pthread = c.pthread_self(); my_cpu_id = 0; @@ -74,13 +69,13 @@ pub fn early_init() linksection(b.init) void { 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 }, .{ .ANONYMOUS = true, .TYPE = .SHARED }, memfd, 0); + 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 = phys_base; + 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; @@ -123,7 +118,7 @@ fn other_cpu_entry(_: ?*anyopaque) callconv(.c) ?*anyopaque { percpu.local().pthread = c.pthread_self(); - ki.cpu.init_cpu(); + ki.cpu.init_cpu(@intCast(my_cpu_id)); timer.init_cpu(); @@ -139,7 +134,7 @@ fn idle(_: ?*anyopaque) void {} extern var __percpu_start: u8; extern var __percpu_end: u8; -pub fn late_init() linksection(b.init) void { +pub fn late_init(_: *pl.BootInfo) linksection(b.init) void { timer.init(); timer.init_cpu();