mirror of
https://github.com/rdmsr/zag.git
synced 2026-11-01 23:58:21 +00:00
feat(um): implement mm for um
This commit is contained in:
+1
-1
@@ -10,8 +10,8 @@ var thread0: ke.Thread = undefined;
|
|||||||
var stack: [8192]u8 align(16) = undefined;
|
var stack: [8192]u8 align(16) = undefined;
|
||||||
|
|
||||||
pub fn init(boot_info: *pl.BootInfo) linksection(b.init) void {
|
pub fn init(boot_info: *pl.BootInfo) linksection(b.init) void {
|
||||||
std.log.info("hello, world", .{});
|
|
||||||
ki.impl.early_init();
|
ki.impl.early_init();
|
||||||
|
std.log.info("hello, world", .{});
|
||||||
pl.early_init(boot_info);
|
pl.early_init(boot_info);
|
||||||
ki.cpu.init_cpu(0);
|
ki.cpu.init_cpu(0);
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
pub inline fn percpu_ptr_other(variable: anytype, cpu_id: usize) @TypeOf(variable) {
|
||||||
return @ptrFromInt(@intFromPtr(variable) +% b.pl.impl.cpu_offsets[cpu_id]);
|
return @ptrFromInt(@intFromPtr(variable) +% b.pl.impl.cpu_offsets[cpu_id]);
|
||||||
}
|
}
|
||||||
|
|||||||
+73
-66
@@ -2,83 +2,90 @@ const b = @import("base");
|
|||||||
const pl = b.pl;
|
const pl = b.pl;
|
||||||
const mm = b.mm;
|
const mm = b.mm;
|
||||||
const mi = mm.private;
|
const mi = mm.private;
|
||||||
|
const config = @import("config");
|
||||||
|
|
||||||
extern var text_start_addr: u8;
|
const is_um = @hasDecl(config, "CONFIG_ARCH_UM");
|
||||||
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;
|
|
||||||
|
|
||||||
fn map_kernel(boot_info: *pl.BootInfo) void {
|
pub const map_kernel = if (!is_um)
|
||||||
const kaddr = boot_info.kernel_address;
|
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_start = @intFromPtr(&text_start_addr);
|
||||||
const text_end = @intFromPtr(&text_end_addr);
|
const text_end = @intFromPtr(&text_end_addr);
|
||||||
const rodata_start = @intFromPtr(&rodata_start_addr);
|
const rodata_start = @intFromPtr(&rodata_start_addr);
|
||||||
const rodata_end = @intFromPtr(&rodata_end_addr);
|
const rodata_end = @intFromPtr(&rodata_end_addr);
|
||||||
const data_start = @intFromPtr(&data_start_addr);
|
const data_start = @intFromPtr(&data_start_addr);
|
||||||
const data_end = @intFromPtr(&data_end_addr);
|
const data_end = @intFromPtr(&data_end_addr);
|
||||||
|
|
||||||
const text_size = text_end - text_start;
|
const text_size = text_end - text_start;
|
||||||
const rodata_size = rodata_end - rodata_start;
|
const rodata_size = rodata_end - rodata_start;
|
||||||
const data_size = data_end - data_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, .{
|
mi.kernel_pmap.map_contiguous_range(text_start, kaddr.physical_base + (text_start - kaddr.virtual_base), text_size, .{
|
||||||
.read = true,
|
.read = true,
|
||||||
.execute = true,
|
.execute = true,
|
||||||
.global = true,
|
.global = true,
|
||||||
});
|
});
|
||||||
|
|
||||||
mi.kernel_pmap.map_contiguous_range(rodata_start, kaddr.physical_base + (rodata_start - kaddr.virtual_base), rodata_size, .{
|
mi.kernel_pmap.map_contiguous_range(rodata_start, kaddr.physical_base + (rodata_start - kaddr.virtual_base), rodata_size, .{
|
||||||
.read = true,
|
.read = true,
|
||||||
.global = true,
|
.global = true,
|
||||||
});
|
});
|
||||||
|
|
||||||
mi.kernel_pmap.map_contiguous_range(data_start, kaddr.physical_base + (data_start - kaddr.virtual_base), data_size, .{
|
mi.kernel_pmap.map_contiguous_range(data_start, kaddr.physical_base + (data_start - kaddr.virtual_base), data_size, .{
|
||||||
.read = true,
|
.read = true,
|
||||||
.write = true,
|
.write = true,
|
||||||
.global = true,
|
.global = true,
|
||||||
});
|
});
|
||||||
|
|
||||||
mi.kernel_pmap.map_contiguous_range(mm.p2v(0), 0, mi.impl.hhdm_minimum_max_address, .{
|
mi.kernel_pmap.map_contiguous_range(mm.p2v(0), 0, mi.impl.hhdm_minimum_max_address, .{
|
||||||
.read = true,
|
.read = true,
|
||||||
.write = true,
|
.write = true,
|
||||||
.global = 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).
|
// 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.
|
// 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
|
// See https://github.com/torvalds/linux/commit/66520ebc2df3fe52eb4792f8101fac573b766baf
|
||||||
for (0..boot_info.memory_map.entry_count) |i| {
|
for (0..boot_info.memory_map.entry_count) |i| {
|
||||||
const entry = boot_info.memory_map.entries[i];
|
const entry = boot_info.memory_map.entries[i];
|
||||||
|
|
||||||
if ((entry.type != .Free and entry.type != .LoaderReclaimable) or entry.size < mm.page_size) {
|
if ((entry.type != .Free and entry.type != .LoaderReclaimable) or entry.size < mm.page_size) {
|
||||||
continue;
|
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,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}.call
|
||||||
if (entry.base + entry.size <= mi.impl.hhdm_minimum_max_address) {
|
else
|
||||||
continue;
|
struct {
|
||||||
}
|
pub fn call(_: *pl.BootInfo) void {}
|
||||||
|
}.call;
|
||||||
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");
|
|
||||||
|
|
||||||
pub fn init(boot_info: *pl.BootInfo) linksection(b.init) void {
|
pub fn init(boot_info: *pl.BootInfo) linksection(b.init) void {
|
||||||
mi.phys.init(boot_info);
|
mi.phys.init(boot_info);
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ pub const PMap = pmap.PMap;
|
|||||||
|
|
||||||
pub const impl = if (@hasDecl(config, "CONFIG_ARCH_AMD64"))
|
pub const impl = if (@hasDecl(config, "CONFIG_ARCH_AMD64"))
|
||||||
@import("amd64/impl.zig")
|
@import("amd64/impl.zig")
|
||||||
|
else if (@hasDecl(config, "CONFIG_ARCH_UM"))
|
||||||
|
@import("um/impl.zig")
|
||||||
else
|
else
|
||||||
@compileError("unsupported architecture");
|
@compileError("unsupported architecture");
|
||||||
|
|
||||||
|
|||||||
@@ -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 {}
|
||||||
|
};
|
||||||
@@ -48,8 +48,8 @@ pub fn debug_write(char: u8) void {
|
|||||||
|
|
||||||
pub const arm_timer = timer.arm_timer;
|
pub const arm_timer = timer.arm_timer;
|
||||||
|
|
||||||
fn check_function(fn_name: []const u8, ret: usize) void {
|
pub fn check_function(fn_name: []const u8, ret: usize) void {
|
||||||
const real_ret: i64 = @intCast(ret);
|
const real_ret: isize = @bitCast(ret);
|
||||||
|
|
||||||
if (real_ret < 0) {
|
if (real_ret < 0) {
|
||||||
const errno_val = linux.errno(ret);
|
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 var cpu_offsets: []usize = undefined;
|
||||||
|
|
||||||
pub fn early_init() linksection(b.init) void {
|
pub fn early_init(_: *pl.BootInfo) linksection(b.init) void {
|
||||||
// Ensure we can use per-cpu data.
|
|
||||||
cpu_offsets = @constCast(&bootstrap_offsets);
|
|
||||||
|
|
||||||
percpu.local().pthread = c.pthread_self();
|
percpu.local().pthread = c.pthread_self();
|
||||||
my_cpu_id = 0;
|
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)));
|
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);
|
check_function("mmap", phys_base);
|
||||||
|
|
||||||
// Build memory map
|
// Build memory map
|
||||||
global_state.boot_info.memory_map.entry_count = 1;
|
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].size = global_state.params.mem_size;
|
||||||
global_state.boot_info.memory_map.entries[0].type = .Free;
|
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();
|
percpu.local().pthread = c.pthread_self();
|
||||||
|
|
||||||
ki.cpu.init_cpu();
|
ki.cpu.init_cpu(@intCast(my_cpu_id));
|
||||||
|
|
||||||
timer.init_cpu();
|
timer.init_cpu();
|
||||||
|
|
||||||
@@ -139,7 +134,7 @@ fn idle(_: ?*anyopaque) void {}
|
|||||||
extern var __percpu_start: u8;
|
extern var __percpu_start: u8;
|
||||||
extern var __percpu_end: 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();
|
||||||
timer.init_cpu();
|
timer.init_cpu();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user