114 lines
3.7 KiB
Zig
114 lines
3.7 KiB
Zig
const std = @import("std");
|
|
const expectEqual = std.testing.expectEqual;
|
|
const log = @import("log.zig");
|
|
|
|
pub const Module = struct {
|
|
/// The region of memory occupied by the module
|
|
region: Range,
|
|
/// The module's name
|
|
name: []const u8,
|
|
};
|
|
|
|
pub const Map = struct {
|
|
/// The virtual range to reserve
|
|
virtual: Range,
|
|
/// The physical range to map to, if any
|
|
physical: ?Range,
|
|
};
|
|
|
|
/// A range of memory
|
|
pub const Range = struct {
|
|
/// The start of the range, inclusive
|
|
start: usize,
|
|
/// The end of the range, exclusive
|
|
end: usize,
|
|
};
|
|
|
|
pub const MemProfile = struct {
|
|
/// The virtual end address of the kernel code.
|
|
vaddr_end: [*]u8,
|
|
|
|
/// The virtual end address of the kernel code.
|
|
vaddr_start: [*]u8,
|
|
|
|
/// The physical end address of the kernel code.
|
|
physaddr_end: [*]u8,
|
|
|
|
/// The physical start address of the kernel code.
|
|
physaddr_start: [*]u8,
|
|
|
|
/// The amount of memory in the system, in kilobytes.
|
|
mem_kb: usize,
|
|
|
|
/// The modules loaded into memory at boot.
|
|
modules: []Module,
|
|
|
|
/// The virtual regions of reserved memory. Should not include what is tracked by the vaddr_* fields but should include the regions occupied by the modules. These are reserved and mapped by the VMM
|
|
virtual_reserved: []Map,
|
|
|
|
/// The phsyical regions of reserved memory. Should not include what is tracked by the physaddr_* fields but should include the regions occupied by the modules. These are reserved by the PMM
|
|
physical_reserved: []Range,
|
|
|
|
/// The allocator to use before a heap can be set up.
|
|
fixed_allocator: std.heap.FixedBufferAllocator,
|
|
};
|
|
|
|
/// The size of the fixed allocator used before the heap is set up. Set to 1MiB.
|
|
pub const FIXED_ALLOC_SIZE: usize = 1024 * 1024;
|
|
|
|
/// The kernel's virtual address offset. It's assigned in the init function and this file's tests.
|
|
/// We can't just use KERNEL_ADDR_OFFSET since using externs in the virtToPhys test is broken in
|
|
/// release-safe. This is a workaround until that is fixed.
|
|
pub var ADDR_OFFSET: usize = undefined;
|
|
|
|
///
|
|
/// Convert a virtual address to its physical counterpart by subtracting the kernel virtual offset from the virtual address.
|
|
///
|
|
/// Arguments:
|
|
/// IN virt: var - The virtual address to covert. Either an integer or pointer.
|
|
///
|
|
/// Return: @TypeOf(virt)
|
|
/// The physical address.
|
|
///
|
|
pub fn virtToPhys(virt: var) @TypeOf(virt) {
|
|
const T = @TypeOf(virt);
|
|
return switch (@typeInfo(T)) {
|
|
.Pointer => @intToPtr(T, @ptrToInt(virt) - ADDR_OFFSET),
|
|
.Int => virt - ADDR_OFFSET,
|
|
else => @compileError("Only pointers and integers are supported"),
|
|
};
|
|
}
|
|
|
|
///
|
|
/// Convert a physical address to its virtual counterpart by adding the kernel virtual offset to the physical address.
|
|
///
|
|
/// Arguments:
|
|
/// IN phys: var - The physical address to covert. Either an integer or pointer.
|
|
///
|
|
/// Return: @TypeOf(virt)
|
|
/// The virtual address.
|
|
///
|
|
pub fn physToVirt(phys: var) @TypeOf(phys) {
|
|
const T = @TypeOf(phys);
|
|
return switch (@typeInfo(T)) {
|
|
.Pointer => @intToPtr(T, @ptrToInt(phys) + ADDR_OFFSET),
|
|
.Int => phys + ADDR_OFFSET,
|
|
else => @compileError("Only pointers and integers are supported"),
|
|
};
|
|
}
|
|
|
|
test "physToVirt" {
|
|
ADDR_OFFSET = 0xC0000000;
|
|
const offset: usize = ADDR_OFFSET;
|
|
expectEqual(physToVirt(@as(usize, 0)), offset + 0);
|
|
expectEqual(physToVirt(@as(usize, 123)), offset + 123);
|
|
expectEqual(@ptrToInt(physToVirt(@intToPtr(*align(1) usize, 123))), offset + 123);
|
|
}
|
|
|
|
test "virtToPhys" {
|
|
ADDR_OFFSET = 0xC0000000;
|
|
const offset: usize = ADDR_OFFSET;
|
|
expectEqual(virtToPhys(offset + 0), 0);
|
|
expectEqual(virtToPhys(offset + 123), 123);
|
|
expectEqual(@ptrToInt(virtToPhys(@intToPtr(*align(1) usize, offset + 123))), 123);
|
|
}
|