feat(um): implement mm for um

This commit is contained in:
Loïc Grégoire
2026-04-15 22:20:23 -04:00
parent 8ea47b72f8
commit deab6561b9
6 changed files with 160 additions and 79 deletions
+73 -66
View File
@@ -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);
+2
View File
@@ -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");
+70
View File
@@ -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 {}
};