Page fault loop

Fixed up the virtual memory mapping

Removed un-used parameters in arch.init
Some doc comments
Name changes
This commit is contained in:
DrDeano 2020-07-24 23:51:27 +01:00
parent fde6894bf2
commit 1030633d1d
No known key found for this signature in database
GPG key ID: 96188600582B9ED7
12 changed files with 348 additions and 263 deletions

View file

@ -339,11 +339,10 @@ pub fn initMem(mb_info: BootPayload) Allocator.Error!MemProfile {
mem.ADDR_OFFSET = @ptrToInt(&KERNEL_ADDR_OFFSET);
const mmap_addr = mb_info.mmap_addr;
const num_mmap_entries = mb_info.mmap_length / @sizeOf(multiboot.multiboot_memory_map_t);
const vaddr_end = @ptrCast([*]u8, &KERNEL_VADDR_END);
var allocator = std.heap.FixedBufferAllocator.init(vaddr_end[0..mem.FIXED_ALLOC_SIZE]);
var reserved_physical_mem = std.ArrayList(mem.Range).init(&allocator.allocator);
var reserved_virtual_mem = std.ArrayList(mem.Map).init(&allocator.allocator);
const allocator = &mem.fixed_buffer_allocator.allocator;
var reserved_physical_mem = std.ArrayList(mem.Range).init(allocator);
var reserved_virtual_mem = std.ArrayList(mem.Map).init(allocator);
const mem_map = @intToPtr([*]multiboot.multiboot_memory_map_t, mmap_addr)[0..num_mmap_entries];
// Reserve the unavailable sections from the multiboot memory map
@ -351,7 +350,10 @@ pub fn initMem(mb_info: BootPayload) Allocator.Error!MemProfile {
if (entry.@"type" != multiboot.MULTIBOOT_MEMORY_AVAILABLE) {
// If addr + len is greater than maxInt(usize) just ignore whatever comes after maxInt(usize) since it can't be addressed anyway
const end: usize = if (entry.addr > std.math.maxInt(usize) - entry.len) std.math.maxInt(usize) else @intCast(usize, entry.addr + entry.len);
try reserved_physical_mem.append(.{ .start = @intCast(usize, entry.addr), .end = end });
try reserved_physical_mem.append(.{
.start = @intCast(usize, entry.addr),
.end = end,
});
}
}
@ -360,8 +362,14 @@ pub fn initMem(mb_info: BootPayload) Allocator.Error!MemProfile {
.start = @ptrToInt(mb_info),
.end = @ptrToInt(mb_info) + @sizeOf(multiboot.multiboot_info_t),
};
const mb_physical = mem.Range{ .start = mem.virtToPhys(mb_region.start), .end = mem.virtToPhys(mb_region.end) };
try reserved_virtual_mem.append(.{ .virtual = mb_region, .physical = mb_physical });
const mb_physical = mem.Range{
.start = mem.virtToPhys(mb_region.start),
.end = mem.virtToPhys(mb_region.end),
};
try reserved_virtual_mem.append(.{
.virtual = mb_region,
.physical = mb_physical,
});
// Map the tty buffer
const tty_addr = mem.virtToPhys(tty.getVideoBufferAddress());
@ -379,16 +387,56 @@ pub fn initMem(mb_info: BootPayload) Allocator.Error!MemProfile {
// Map the boot modules
const boot_modules = @intToPtr([*]multiboot.multiboot_mod_list, mem.physToVirt(mb_info.mods_addr))[0..mods_count];
var modules = std.ArrayList(mem.Module).init(&allocator.allocator);
var modules = std.ArrayList(mem.Module).init(allocator);
for (boot_modules) |module| {
const virtual = mem.Range{ .start = mem.physToVirt(module.mod_start), .end = mem.physToVirt(module.mod_end) };
const physical = mem.Range{ .start = module.mod_start, .end = module.mod_end };
try modules.append(.{ .region = virtual, .name = std.mem.span(mem.physToVirt(@intToPtr([*:0]u8, module.cmdline))) });
try reserved_virtual_mem.append(.{ .physical = physical, .virtual = virtual });
const virtual = mem.Range{
.start = mem.physToVirt(module.mod_start),
.end = mem.physToVirt(module.mod_end),
};
const physical = mem.Range{
.start = module.mod_start,
.end = module.mod_end,
};
try modules.append(.{
.region = virtual,
.name = std.mem.span(mem.physToVirt(@intToPtr([*:0]u8, module.cmdline))),
});
try reserved_virtual_mem.append(.{
.physical = physical,
.virtual = virtual,
});
}
// Map the kernel stack
const kernel_stack_virt = mem.Range{
.start = @ptrToInt(&KERNEL_STACK_START),
.end = @ptrToInt(&KERNEL_STACK_END),
};
const kernel_stack_phy = mem.Range{
.start = mem.virtToPhys(kernel_stack_virt.start),
.end = mem.virtToPhys(kernel_stack_virt.end),
};
try reserved_virtual_mem.append(.{
.virtual = kernel_stack_virt,
.physical = kernel_stack_phy,
});
// Map the rest of the kernel
const kernel_virt = mem.Range{
.start = @ptrToInt(&KERNEL_VADDR_START),
.end = @ptrToInt(&KERNEL_STACK_START),
};
const kernel_phy = mem.Range{
.start = mem.virtToPhys(kernel_virt.start),
.end = mem.virtToPhys(kernel_virt.end),
};
try reserved_virtual_mem.append(.{
.virtual = kernel_virt,
.physical = kernel_phy,
});
return MemProfile{
.vaddr_end = vaddr_end,
.vaddr_end = @ptrCast([*]u8, &KERNEL_VADDR_END),
.vaddr_start = @ptrCast([*]u8, &KERNEL_VADDR_START),
.physaddr_end = @ptrCast([*]u8, &KERNEL_PHYSADDR_END),
.physaddr_start = @ptrCast([*]u8, &KERNEL_PHYSADDR_START),
@ -397,7 +445,7 @@ pub fn initMem(mb_info: BootPayload) Allocator.Error!MemProfile {
.modules = modules.items,
.physical_reserved = reserved_physical_mem.items,
.virtual_reserved = reserved_virtual_mem.items,
.fixed_allocator = allocator,
.fixed_allocator = mem.fixed_buffer_allocator,
};
}
@ -452,12 +500,10 @@ pub fn initTaskStack(entry_point: usize, allocator: *Allocator) Allocator.Error!
/// Initialise the architecture
///
/// Arguments:
/// IN boot_payload: BootPayload - The multiboot information from the GRUB bootloader.
/// IN mem_profile: *const MemProfile - The memory profile of the computer. Used to set up
/// paging.
/// IN allocator: *Allocator - The allocator use to handle memory.
///
pub fn init(boot_payload: BootPayload, mem_profile: *const MemProfile, allocator: *Allocator) void {
pub fn init(mem_profile: *const MemProfile) void {
gdt.init();
idt.init();
@ -465,7 +511,7 @@ pub fn init(boot_payload: BootPayload, mem_profile: *const MemProfile, allocator
isr.init();
irq.init();
paging.init(boot_payload, mem_profile, allocator);
paging.init(mem_profile);
pit.init();
rtc.init();

View file

@ -101,6 +101,7 @@ export fn start_higher_half() callconv(.Naked) noreturn {
asm volatile (
\\.extern KERNEL_STACK_END
\\mov $KERNEL_STACK_END, %%esp
\\sub $32, %%esp
\\mov %%esp, %%ebp
);

View file

@ -387,9 +387,8 @@ fn pageFault(state: *arch.CpuState) u32 {
///
/// Arguments:
/// IN mem_profile: *const MemProfile - The memory profile of the system and kernel
/// IN allocator: *std.mem.Allocator - The allocator to use
///
pub fn init(mb_info: *multiboot.multiboot_info_t, mem_profile: *const MemProfile, allocator: *std.mem.Allocator) void {
pub fn init(mem_profile: *const MemProfile) void {
std.log.info(.paging, "Init\n", .{});
defer std.log.info(.paging, "Done\n", .{});
@ -401,7 +400,7 @@ pub fn init(mb_info: *multiboot.multiboot_info_t, mem_profile: *const MemProfile
:
: [addr] "{eax}" (dir_physaddr)
);
const v_end = std.mem.alignForward(@ptrToInt(mem_profile.vaddr_end) + mem.FIXED_ALLOC_SIZE, PAGE_SIZE_4KB);
const v_end = std.mem.alignForward(@ptrToInt(mem_profile.vaddr_end), PAGE_SIZE_4KB);
switch (build_options.test_mode) {
.Initialisation => runtimeTests(v_end),
else => {},

View file

@ -414,6 +414,8 @@ const FreeListAllocator = struct {
var free_list = &(try FreeListAllocator.init(start, size));
var allocator = &free_list.allocator;
std.debug.warn("", .{});
const alloc0 = try alloc(allocator, 64, 0, 0);
const alloc0_addr = @ptrToInt(alloc0.ptr);
// Should be at the start of the heap
@ -424,6 +426,8 @@ const FreeListAllocator = struct {
testing.expectEqual(header.next_free, null);
testing.expectEqual(free_list.first_free, header);
std.debug.warn("", .{});
// 64 bytes aligned to 4 bytes
const alloc1 = try alloc(allocator, 64, 4, 0);
const alloc1_addr = @ptrToInt(alloc1.ptr);

View file

@ -61,7 +61,9 @@ export fn kmain(boot_payload: arch.BootPayload) void {
log_root.init(serial_stream);
const mem_profile = arch.initMem(boot_payload) catch |e| panic_root.panic(@errorReturnTrace(), "Failed to initialise memory profile: {}", .{e});
const mem_profile = arch.initMem(boot_payload) catch |e| {
panic_root.panic(@errorReturnTrace(), "Failed to initialise memory profile: {}", .{e});
};
var fixed_allocator = mem_profile.fixed_allocator;
panic_root.init(&mem_profile, &fixed_allocator.allocator) catch |e| {
@ -69,10 +71,12 @@ export fn kmain(boot_payload: arch.BootPayload) void {
};
pmm.init(&mem_profile, &fixed_allocator.allocator);
kernel_vmm = vmm.init(&mem_profile, &fixed_allocator.allocator) catch |e| panic_root.panic(@errorReturnTrace(), "Failed to initialise kernel VMM: {}", .{e});
kernel_vmm = vmm.init(&mem_profile, &fixed_allocator.allocator) catch |e| {
panic_root.panic(@errorReturnTrace(), "Failed to initialise kernel VMM: {}", .{e});
};
std.log.info(.kmain, "Init arch " ++ @tagName(builtin.arch) ++ "\n", .{});
arch.init(boot_payload, &mem_profile, &fixed_allocator.allocator);
arch.init(&mem_profile);
std.log.info(.kmain, "Arch init done\n", .{});
// Give the kernel heap 10% of the available memory. This can be fine-tuned as time goes on.

View file

@ -53,7 +53,10 @@ pub const MemProfile = struct {
};
/// The size of the fixed allocator used before the heap is set up. Set to 1MiB.
pub const FIXED_ALLOC_SIZE: usize = 1024 * 1024;
pub var fixed_buffer: [1024 * 1024]u8 = undefined;
/// The fixed allocator used before the heap is set up.
pub var fixed_buffer_allocator: std.heap.FixedBufferAllocator = std.heap.FixedBufferAllocator.init(fixed_buffer[0..]);
/// 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

View file

@ -6,6 +6,7 @@ const multiboot = @import("multiboot.zig");
const mem = @import("mem.zig");
const build_options = @import("build_options");
const ArrayList = std.ArrayList;
const Allocator = std.mem.Allocator;
const testing = std.testing;
/// The possible errors from panic code
@ -31,12 +32,12 @@ const SymbolMap = struct {
/// Initialise an empty symbol map.
///
/// Arguments:
/// IN allocator: *std.mem.Allocator - The allocator to use to initialise the array list.
/// IN allocator: *Allocator - The allocator to use to initialise the array list.
///
/// Return: SymbolMap
/// The symbol map.
///
pub fn init(allocator: *std.mem.Allocator) SymbolMap {
pub fn init(allocator: *Allocator) SymbolMap {
return SymbolMap{
.symbols = ArrayList(MapEntry).init(allocator),
};
@ -56,14 +57,23 @@ const SymbolMap = struct {
/// IN name: []const u8 - The name of the entry.
/// IN addr: usize - The address for the entry.
///
/// Error: std.mem.Allocator.Error
/// * - See ArrayList.append
/// Error: Allocator.Error
/// error.OutOfMemory - If there isn't enough memory to append a map entry.
///
pub fn add(self: *SymbolMap, name: []const u8, addr: usize) !void {
pub fn add(self: *SymbolMap, name: []const u8, addr: usize) Allocator.Error!void {
try self.addEntry(MapEntry{ .addr = addr, .func_name = name });
}
pub fn addEntry(self: *SymbolMap, entry: MapEntry) !void {
///
/// Add a symbol map entry.
///
/// Arguments:
/// IN entry: MapEntry - The entry.
///
/// Error: Allocator.Error
/// error.OutOfMemory - If there isn't enough memory to append a map entry.
///
pub fn addEntry(self: *SymbolMap, entry: MapEntry) Allocator.Error!void {
try self.symbols.append(entry);
}
@ -104,6 +114,168 @@ fn logTraceAddress(addr: usize) void {
std.log.emerg(.panic, "{x}: {}\n", .{ addr, str });
}
///
/// Parse a hexadecimal address from the pointer up until the end pointer. Must be terminated by a
/// whitespace character.
///
/// Arguments:
/// IN/OUT ptr: *[*]const u8 - The address at which to start looking, updated after all
/// characters have been consumed.
/// IN end: *const u8 - The end address at which to start looking. A whitespace character must
/// be found before this.
///
/// Return: usize
/// The address parsed.
///
/// Error: PanicError || std.fmt.ParseIntError
/// PanicError.InvalidSymbolFile - A terminating whitespace wasn't found before the end address.
/// std.fmt.ParseIntError - See std.fmt.parseInt
///
fn parseAddr(ptr: *[*]const u8, end: *const u8) (PanicError || std.fmt.ParseIntError)!usize {
const addr_start = ptr.*;
ptr.* = try parseNonWhitespace(ptr.*, end);
const len = @ptrToInt(ptr.*) - @ptrToInt(addr_start);
const addr_str = addr_start[0..len];
return std.fmt.parseInt(usize, addr_str, 16);
}
///
/// Parse a single character. The address given cannot be greater than or equal to the end address
/// given.
///
/// Arguments:
/// IN ptr: [*]const u8 - The address at which to get the character from.
/// IN end: *const u8 - The end address at which to start looking. ptr cannot be greater than or
/// equal to this.
///
/// Return: u8
/// The character parsed.
///
/// Error: PanicError
/// PanicError.InvalidSymbolFile - The address given is greater than or equal to the end address.
///
fn parseChar(ptr: [*]const u8, end: *const u8) PanicError!u8 {
if (@ptrToInt(ptr) >= @ptrToInt(end)) {
return PanicError.InvalidSymbolFile;
}
return ptr[0];
}
///
/// Parse until a non-whitespace character. Must be terminated by a non-whitespace character before
/// the end address.
///
/// Arguments:
/// IN ptr: [*]const u8 - The address at which to start looking.
/// IN end: *const u8 - The end address at which to start looking. A non-whitespace character
/// must be found before this.
///
/// Return: [*]const u8
/// ptr plus the number of whitespace characters consumed.
///
/// Error: PanicError
/// PanicError.InvalidSymbolFile - A terminating non-whitespace character wasn't found before
/// the end address.
///
fn parseWhitespace(ptr: [*]const u8, end: *const u8) PanicError![*]const u8 {
var i: u32 = 0;
while (std.fmt.isWhiteSpace(try parseChar(ptr + i, end))) : (i += 1) {}
return ptr + i;
}
///
/// Parse until a whitespace character. Must be terminated by a whitespace character before the end
/// address.
///
/// Arguments:
/// IN ptr: [*]const u8 - The address at which to start looking.
/// IN end: *const u8 - The end address at which to start looking. A whitespace character must
/// be found before this.
///
/// Return: [*]const u8
/// ptr plus the number of non-whitespace characters consumed.
///
/// Error: PanicError
/// PanicError.InvalidSymbolFile - A terminating whitespace character wasn't found before the
/// end address.
///
fn parseNonWhitespace(ptr: [*]const u8, end: *const u8) PanicError![*]const u8 {
var i: u32 = 0;
while (!std.fmt.isWhiteSpace(try parseChar(ptr + i, end))) : (i += 1) {}
return ptr + i;
}
///
/// Parse until a newline character. Must be terminated by a newline character before the end
/// address.
///
/// Arguments:
/// IN ptr: [*]const u8 - The address at which to start looking.
/// IN end: *const u8 - The end address at which to start looking. A newline character must
/// be found before this.
///
/// Return: [*]const u8
/// ptr plus the number of non-newline characters consumed.
///
/// Error: PanicError
/// PanicError.InvalidSymbolFile - A terminating newline character wasn't found before the
/// end address.
///
fn parseNonNewLine(ptr: [*]const u8, end: *const u8) PanicError![*]const u8 {
var i: u32 = 0;
while ((try parseChar(ptr + i, end)) != '\n') : (i += 1) {}
return ptr + i;
}
///
/// Parse a name from the pointer up until the end pointer. Must be terminated by a whitespace
/// character.
///
/// Arguments:
/// IN/OUT ptr: *[*]const u8 - The address at which to start looking, updated after all
/// characters have been consumed.
/// IN end: *const u8 - The end address at which to start looking. A whitespace character must
/// be found before this.
///
/// Return: []const u8
/// The name parsed.
///
/// Error: PanicError
/// PanicError.InvalidSymbolFile - A terminating whitespace wasn't found before the end address.
///
fn parseName(ptr: *[*]const u8, end: *const u8) PanicError![]const u8 {
const name_start = ptr.*;
ptr.* = try parseNonNewLine(ptr.*, end);
const len = @ptrToInt(ptr.*) - @ptrToInt(name_start);
return name_start[0..len];
}
///
/// Parse a symbol map entry from the pointer up until the end pointer,
/// in the format of '\d+\w+[a-zA-Z0-9]+'. Must be terminated by a whitespace character.
///
/// Arguments:
/// IN/OUT ptr: *[*]const u8 - The address at which to start looking, updated once after the
/// address has been consumed and once again after the name has been consumed.
/// IN end: *const u8 - The end address at which to start looking. A whitespace character must
/// be found before this.
///
/// Return: MapEntry
/// The entry parsed.
///
/// Error: PanicError || std.fmt.ParseIntError
/// PanicError.InvalidSymbolFile - A terminating whitespace wasn't found before the end address.
/// std.fmt.ParseIntError - See parseAddr.
///
fn parseMapEntry(start: *[*]const u8, end: *const u8) (PanicError || std.fmt.ParseIntError)!MapEntry {
var ptr = try parseWhitespace(start.*, end);
defer start.* = ptr;
const addr = try parseAddr(&ptr, end);
ptr = try parseWhitespace(ptr, end);
const name = try parseName(&ptr, end);
return MapEntry{ .addr = addr, .func_name = name };
}
pub fn panic(trace: ?*builtin.StackTrace, comptime format: []const u8, args: anytype) noreturn {
@setCold(true);
std.log.emerg(.panic, "Kernel panic: " ++ format ++ "\n", args);
@ -125,168 +297,6 @@ pub fn panic(trace: ?*builtin.StackTrace, comptime format: []const u8, args: any
arch.haltNoInterrupts();
}
///
/// Parse a hexadecimal address from the pointer up until the end pointer. Must be terminated by a
/// whitespace character.
///
/// Arguments:
/// IN/OUT ptr: *[*]const u8 - The address at which to start looking, updated after all
/// characters have been consumed.
/// IN end: *const u8 - The end address at which to start looking. A whitespace character must
/// be found before this.
///
/// Return: usize
/// The address parsed.
///
/// Error: PanicError || std.fmt.ParseUnsignedError
/// PanicError.InvalidSymbolFile: A terminating whitespace wasn't found before the end address.
/// std.fmt.ParseUnsignedError: See std.fmt.parseInt
///
fn parseAddr(ptr: *[*]const u8, end: *const u8) !usize {
const addr_start = ptr.*;
ptr.* = try parseNonWhitespace(ptr.*, end);
const len = @ptrToInt(ptr.*) - @ptrToInt(addr_start);
const addr_str = addr_start[0..len];
return try std.fmt.parseInt(usize, addr_str, 16);
}
///
/// Parse a single character. The address given cannot be greater than or equal to the end address
/// given.
///
/// Arguments:
/// IN ptr: [*]const u8 - The address at which to get the character from.
/// IN end: *const u8 - The end address at which to start looking. ptr cannot be greater than or
/// equal to this.
///
/// Return: u8
/// The character parsed.
///
/// Error: PanicError
/// PanicError.InvalidSymbolFile: The address given is greater than or equal to the end address.
///
fn parseChar(ptr: [*]const u8, end: *const u8) PanicError!u8 {
if (@ptrToInt(ptr) >= @ptrToInt(end)) {
return PanicError.InvalidSymbolFile;
}
return ptr[0];
}
///
/// Parse until a non-whitespace character. Must be terminated by a non-whitespace character before
/// the end address.
///
/// Arguments:
/// IN ptr: [*]const u8 - The address at which to start looking.
/// IN end: *const u8 - The end address at which to start looking. A non-whitespace character
/// must be found before this.
///
/// Return: [*]const u8
/// ptr plus the number of whitespace characters consumed.
///
/// Error: PanicError
/// PanicError.InvalidSymbolFile: A terminating non-whitespace character wasn't found before the
/// end address.
///
fn parseWhitespace(ptr: [*]const u8, end: *const u8) PanicError![*]const u8 {
var i: u32 = 0;
while (std.fmt.isWhiteSpace(try parseChar(ptr + i, end))) : (i += 1) {}
return ptr + i;
}
///
/// Parse until a whitespace character. Must be terminated by a whitespace character before the end
/// address.
///
/// Arguments:
/// IN ptr: [*]const u8 - The address at which to start looking.
/// IN end: *const u8 - The end address at which to start looking. A whitespace character must
/// be found before this.
///
/// Return: [*]const u8
/// ptr plus the number of non-whitespace characters consumed.
///
/// Error: PanicError
/// PanicError.InvalidSymbolFile: A terminating whitespace character wasn't found before the end
/// address.
///
fn parseNonWhitespace(ptr: [*]const u8, end: *const u8) PanicError![*]const u8 {
var i: u32 = 0;
while (!std.fmt.isWhiteSpace(try parseChar(ptr + i, end))) : (i += 1) {}
return ptr + i;
}
///
/// Parse until a newline character. Must be terminated by a newline character before the end
/// address.
///
/// Arguments:
/// IN ptr: [*]const u8 - The address at which to start looking.
/// IN end: *const u8 - The end address at which to start looking. A newline character must
/// be found before this.
///
/// Return: [*]const u8
/// ptr plus the number of non-newline characters consumed.
///
/// Error: PanicError
/// PanicError.InvalidSymbolFile: A terminating newline character wasn't found before the end
/// address.
///
fn parseNonNewLine(ptr: [*]const u8, end: *const u8) PanicError![*]const u8 {
var i: u32 = 0;
while ((try parseChar(ptr + i, end)) != '\n') : (i += 1) {}
return ptr + i;
}
///
/// Parse a name from the pointer up until the end pointer. Must be terminated by a whitespace
/// character.
///
/// Arguments:
/// IN/OUT ptr: *[*]const u8 - The address at which to start looking, updated after all
/// characters have been consumed.
/// IN end: *const u8 - The end address at which to start looking. A whitespace character must
/// be found before this.
///
/// Return: []const u8
/// The name parsed.
///
/// Error: PanicError
/// PanicError.InvalidSymbolFile: A terminating whitespace wasn't found before the end address.
///
fn parseName(ptr: *[*]const u8, end: *const u8) PanicError![]const u8 {
const name_start = ptr.*;
ptr.* = try parseNonNewLine(ptr.*, end);
const len = @ptrToInt(ptr.*) - @ptrToInt(name_start);
return name_start[0..len];
}
///
/// Parse a symbol map entry from the pointer up until the end pointer,
/// in the format of '\d+\w+[a-zA-Z0-9]+'. Must be terminated by a whitespace character.
///
/// Arguments:
/// IN/OUT ptr: *[*]const u8 - The address at which to start looking, updated once after the
/// address has been consumed and once again after the name has been consumed.
/// IN end: *const u8 - The end address at which to start looking. A whitespace character must
/// be found before this.
///
/// Return: MapEntry
/// The entry parsed.
///
/// Error: PanicError || std.fmt.ParseUnsignedError
/// PanicError.InvalidSymbolFile: A terminating whitespace wasn't found before the end address.
/// std.fmt.ParseUnsignedError: See parseAddr.
///
fn parseMapEntry(start: *[*]const u8, end: *const u8) !MapEntry {
var ptr = try parseWhitespace(start.*, end);
defer start.* = ptr;
const addr = try parseAddr(&ptr, end);
ptr = try parseWhitespace(ptr, end);
const name = try parseName(&ptr, end);
return MapEntry{ .addr = addr, .func_name = name };
}
///
/// Initialise the panic subsystem by looking for a boot module called "kernel.map" and loading the
/// symbols from it. Exits early if no such module was found.
@ -294,13 +304,14 @@ fn parseMapEntry(start: *[*]const u8, end: *const u8) !MapEntry {
/// Arguments:
/// IN mem_profile: *const mem.MemProfile - The memory profile from which to get the loaded boot
/// modules.
/// IN allocator: *std.mem.Allocator - The allocator to use to store the symbol map.
/// IN allocator: *Allocator - The allocator to use to store the symbol map.
///
/// Error: PanicError || std.fmt.ParseUnsignedError
/// PanicError.InvalidSymbolFile: A terminating whitespace wasn't found before the end address.
/// std.fmt.ParseUnsignedError: See parseMapEntry.
/// Error: PanicError || Allocator.Error || std.fmt.ParseIntError
/// PanicError.InvalidSymbolFile - A terminating whitespace wasn't found before the end address.
/// Allocator.Error.OutOfMemory - If there wasn't enough memory.
/// std.fmt.ParseIntError - See parseMapEntry.
///
pub fn init(mem_profile: *const mem.MemProfile, allocator: *std.mem.Allocator) !void {
pub fn init(mem_profile: *const mem.MemProfile, allocator: *Allocator) (PanicError || Allocator.Error || std.fmt.ParseIntError)!void {
std.log.info(.panic, "Init\n", .{});
defer std.log.info(.panic, "Done\n", .{});

View file

@ -7,6 +7,7 @@ const MemProfile = (if (is_test) @import(mock_path ++ "mem_mock.zig") else @impo
const testing = std.testing;
const panic = @import("panic.zig").panic;
const Bitmap = @import("bitmap.zig").Bitmap;
const Allocator = std.mem.Allocator;
const PmmBitmap = Bitmap(u32);
@ -94,16 +95,18 @@ pub fn blocksFree() usize {
///
/// Arguments:
/// IN mem: *const MemProfile - The system's memory profile.
/// IN allocator: *std.mem.Allocator - The allocator to use to allocate the bitmaps.
/// IN allocator: *Allocator - The allocator to use to allocate the bitmaps.
///
pub fn init(mem: *const MemProfile, allocator: *std.mem.Allocator) void {
pub fn init(mem_profile: *const MemProfile, allocator: *Allocator) void {
std.log.info(.pmm, "Init\n", .{});
defer std.log.info(.pmm, "Done\n", .{});
bitmap = PmmBitmap.init(mem.mem_kb * 1024 / BLOCK_SIZE, allocator) catch @panic("Bitmap allocation failed");
bitmap = PmmBitmap.init(mem_profile.mem_kb * 1024 / BLOCK_SIZE, allocator) catch |e| {
panic(@errorReturnTrace(), "Bitmap allocation failed: {}\n", .{e});
};
// Occupy the regions of memory that the memory map describes as reserved
for (mem.physical_reserved) |entry| {
for (mem_profile.physical_reserved) |entry| {
var addr = std.mem.alignBackward(entry.start, BLOCK_SIZE);
var end = entry.end - 1;
// If the end address can be aligned without overflowing then align it
@ -120,7 +123,7 @@ pub fn init(mem: *const MemProfile, allocator: *std.mem.Allocator) void {
}
switch (build_options.test_mode) {
.Initialisation => runtimeTests(mem, allocator),
.Initialisation => runtimeTests(mem_profile, allocator),
else => {},
}
}
@ -200,10 +203,10 @@ test "setAddr and isSet" {
/// Allocate all blocks and make sure they don't overlap with any reserved addresses.
///
/// Arguments:
/// IN mem: *const MemProfile - The memory profile to check for reserved memory regions.
/// IN/OUT allocator: *std.mem.Allocator - The allocator to use when needing to create intermediate structures used for testing
/// IN mem_profile: *const MemProfile - The memory profile to check for reserved memory regions.
/// IN/OUT allocator: *Allocator - The allocator to use when needing to create intermediate structures used for testing
///
fn runtimeTests(mem: *const MemProfile, allocator: *std.mem.Allocator) void {
fn runtimeTests(mem_profile: *const MemProfile, allocator: *Allocator) void {
// Make sure that occupied memory can't be allocated
var prev_alloc: usize = std.math.maxInt(usize);
var alloc_list = std.ArrayList(usize).init(allocator);
@ -213,17 +216,21 @@ fn runtimeTests(mem: *const MemProfile, allocator: *std.mem.Allocator) void {
panic(null, "FAILURE: PMM allocated the same address twice: 0x{x}", .{alloced});
}
prev_alloc = alloced;
for (mem.physical_reserved) |entry| {
for (mem_profile.physical_reserved) |entry| {
var addr = std.mem.alignBackward(@intCast(usize, entry.start), BLOCK_SIZE);
if (addr == alloced) {
panic(null, "FAILURE: PMM allocated an address that should be reserved by the memory map: 0x{x}", .{addr});
}
}
alloc_list.append(alloced) catch |e| panic(@errorReturnTrace(), "FAILURE: Failed to add PMM allocation to list: {}", .{e});
alloc_list.append(alloced) catch |e| {
panic(@errorReturnTrace(), "FAILURE: Failed to add PMM allocation to list: {}", .{e});
};
}
// Clean up
for (alloc_list.items) |alloced| {
free(alloced) catch |e| panic(@errorReturnTrace(), "FAILURE: Failed freeing allocation in PMM rt test: {}", .{e});
free(alloced) catch |e| {
panic(@errorReturnTrace(), "FAILURE: Failed freeing allocation in PMM rt test: {}", .{e});
};
}
std.log.info(.pmm, "Tested allocation\n", .{});
}

View file

@ -9,6 +9,7 @@ const mem = if (is_test) @import(mock_path ++ "mem_mock.zig") else @import("mem.
const tty = @import("tty.zig");
const panic = @import("panic.zig").panic;
const arch = @import("arch.zig").internals;
const Allocator = std.mem.Allocator;
/// Attributes for a virtual memory allocation
pub const Attributes = struct {
@ -63,13 +64,13 @@ pub fn Mapper(comptime Payload: type) type {
/// IN physical_start: usize - The start of the physical memory to map to
/// IN physical_end: usize - The end of the physical memory to map to
/// IN attrs: Attributes - The attributes to apply to this region of memory
/// IN/OUT allocator: std.mem.Allocator - The allocator to use when mapping, if required
/// IN/OUT allocator: Allocator - The allocator to use when mapping, if required
/// IN spec: Payload - The payload to pass to the mapper
///
/// Error: std.mem.AllocatorError || MapperError
/// Error: AllocatorError || MapperError
/// The causes depend on the mapper used
///
mapFn: fn (virtual_start: usize, virtual_end: usize, physical_start: usize, physical_end: usize, attrs: Attributes, allocator: *std.mem.Allocator, spec: Payload) (std.mem.Allocator.Error || MapperError)!void,
mapFn: fn (virtual_start: usize, virtual_end: usize, physical_start: usize, physical_end: usize, attrs: Attributes, allocator: *Allocator, spec: Payload) (Allocator.Error || MapperError)!void,
///
/// Unmap a region (can span more than one block) of virtual memory from its physical memory. After a call to this function, the memory should not be accessible without error.
@ -79,10 +80,10 @@ pub fn Mapper(comptime Payload: type) type {
/// IN virtual_end: usize - The end of the virtual region to unmap
/// IN spec: Payload - The payload to pass to the mapper
///
/// Error: std.mem.AllocatorError || MapperError
/// Error: AllocatorError || MapperError
/// The causes depend on the mapper used
///
unmapFn: fn (virtual_start: usize, virtual_end: usize, spec: Payload) (std.mem.Allocator.Error || MapperError)!void,
unmapFn: fn (virtual_start: usize, virtual_end: usize, spec: Payload) (Allocator.Error || MapperError)!void,
};
}
@ -132,7 +133,7 @@ pub fn VirtualMemoryManager(comptime Payload: type) type {
end: usize,
/// The allocator to use when allocating and freeing regions
allocator: *std.mem.Allocator,
allocator: *Allocator,
/// All allocations that have been made with this manager
allocations: std.hash_map.AutoHashMap(usize, Allocation),
@ -151,17 +152,17 @@ pub fn VirtualMemoryManager(comptime Payload: type) type {
/// Arguments:
/// IN start: usize - The start of the memory region to manage
/// IN end: usize - The end of the memory region to manage. Must be greater than the start
/// IN/OUT allocator: *std.mem.Allocator - The allocator to use when allocating and freeing regions
/// IN/OUT allocator: *Allocator - The allocator to use when allocating and freeing regions
/// IN mapper: Mapper - The mapper to use when allocating and freeing regions
/// IN payload: Payload - The payload data to be passed to the mapper
///
/// Return: Self
/// The manager constructed
///
/// Error: std.mem.Allocator.Error
/// std.mem.Allocator.Error.OutOfMemory - The allocator cannot allocate the memory required
/// Error: Allocator.Error
/// error.OutOfMemory - The allocator cannot allocate the memory required
///
pub fn init(start: usize, end: usize, allocator: *std.mem.Allocator, mapper: Mapper(Payload), payload: Payload) std.mem.Allocator.Error!Self {
pub fn init(start: usize, end: usize, allocator: *Allocator, mapper: Mapper(Payload), payload: Payload) Allocator.Error!Self {
const size = end - start;
var bmp = try bitmap.Bitmap(usize).init(std.mem.alignForward(size, pmm.BLOCK_SIZE) / pmm.BLOCK_SIZE, allocator);
return Self{
@ -189,7 +190,7 @@ pub fn VirtualMemoryManager(comptime Payload: type) type {
/// Bitmap(u32).Error.OutOfBounds - The address given is outside of the memory managed
///
pub fn isSet(self: *const Self, virt: usize) bitmap.Bitmap(u32).BitmapError!bool {
return try self.bmp.isSet((virt - self.start) / BLOCK_SIZE);
return self.bmp.isSet((virt - self.start) / BLOCK_SIZE);
}
///
@ -201,21 +202,22 @@ pub fn VirtualMemoryManager(comptime Payload: type) type {
/// IN physical: ?mem.Range - The physical region to map to or null if only the virtual region is to be set
/// IN attrs: Attributes - The attributes to apply to the memory regions
///
/// Error: VmmError || Bitmap(u32).BitmapError || std.mem.Allocator.Error || MapperError
/// Error: VmmError || Bitmap(u32).BitmapError || Allocator.Error || MapperError
/// VmmError.AlreadyAllocated - The virtual address has already been allocated
/// VmmError.PhysicalAlreadyAllocated - The physical address has already been allocated
/// VmmError.PhysicalVirtualMismatch - The physical region and virtual region are of different sizes
/// VmmError.InvalidVirtAddresses - The start virtual address is greater than the end address
/// VmmError.InvalidPhysicalAddresses - The start physical address is greater than the end address
/// Bitmap.BitmapError.OutOfBounds - The physical or virtual addresses are out of bounds
/// std.mem.Allocator.Error.OutOfMemory - Allocating the required memory failed
/// Allocator.Error.OutOfMemory - Allocating the required memory failed
/// MapperError.* - The causes depend on the mapper used
///
pub fn set(self: *Self, virtual: mem.Range, physical: ?mem.Range, attrs: Attributes) (VmmError || bitmap.Bitmap(u32).BitmapError || std.mem.Allocator.Error || MapperError)!void {
pub fn set(self: *Self, virtual: mem.Range, physical: ?mem.Range, attrs: Attributes) (VmmError || bitmap.Bitmap(u32).BitmapError || Allocator.Error || MapperError)!void {
var virt = virtual.start;
while (virt < virtual.end) : (virt += BLOCK_SIZE) {
if (try self.isSet(virt))
if (try self.isSet(virt)) {
return VmmError.AlreadyAllocated;
}
}
if (virtual.start > virtual.end) {
return VmmError.InvalidVirtAddresses;
@ -266,12 +268,13 @@ pub fn VirtualMemoryManager(comptime Payload: type) type {
/// Return: ?usize
/// The address at the start of the allocated region, or null if no region could be allocated due to a lack of contiguous blocks.
///
/// Error: std.mem.Allocator.Error
/// std.mem.AllocatorError.OutOfMemory: The required amount of memory couldn't be allocated
/// Error: Allocator.Error
/// error.OutOfMemory: The required amount of memory couldn't be allocated
///
pub fn alloc(self: *Self, num: usize, attrs: Attributes) std.mem.Allocator.Error!?usize {
if (num == 0)
pub fn alloc(self: *Self, num: usize, attrs: Attributes) Allocator.Error!?usize {
if (num == 0) {
return null;
}
// Ensure that there is both enough physical and virtual address space free
if (pmm.blocksFree() >= num and self.bmp.num_free_entries >= num) {
// The virtual address space must be contiguous
@ -312,19 +315,23 @@ pub fn VirtualMemoryManager(comptime Payload: type) type {
const entry = (vaddr - self.start) / BLOCK_SIZE;
if (try self.bmp.isSet(entry)) {
// There will be an allocation associated with this virtual address
const allocation = self.allocations.get(vaddr) orelse unreachable;
const allocation = self.allocations.get(vaddr).?;
const physical = allocation.physical;
defer physical.deinit();
const num_physical_allocations = physical.items.len;
for (physical.items) |block, i| {
// Clear the address space entry and free the physical memory
try self.bmp.clearEntry(entry + i);
pmm.free(block) catch |e| panic(@errorReturnTrace(), "Failed to free PMM reserved memory at 0x{X}: {}\n", .{ block * BLOCK_SIZE, e });
pmm.free(block) catch |e| {
panic(@errorReturnTrace(), "Failed to free PMM reserved memory at 0x{X}: {}\n", .{ block * BLOCK_SIZE, e });
};
}
// Unmap the entire range
const region_start = entry * BLOCK_SIZE;
const region_end = (entry + num_physical_allocations) * BLOCK_SIZE;
self.mapper.unmapFn(region_start, region_end, self.payload) catch |e| panic(@errorReturnTrace(), "Failed to unmap VMM reserved memory from 0x{X} to 0x{X}: {}\n", .{ region_start, region_end, e });
self.mapper.unmapFn(region_start, region_end, self.payload) catch |e| {
panic(@errorReturnTrace(), "Failed to unmap VMM reserved memory from 0x{X} to 0x{X}: {}\n", .{ region_start, region_end, e });
};
// The allocation is freed so remove from the map
self.allocations.removeAssertDiscard(vaddr);
} else {
@ -339,31 +346,33 @@ pub fn VirtualMemoryManager(comptime Payload: type) type {
///
/// Arguments:
/// IN mem_profile: *const mem.MemProfile - The system's memory profile. This is used to find the kernel code region and boot modules
/// IN/OUT allocator: *std.mem.Allocator - The allocator to use when needing to allocate memory
/// IN/OUT allocator: *Allocator - The allocator to use when needing to allocate memory
///
/// Return: VirtualMemoryManager
/// The virtual memory manager created with all reserved virtual regions allocated
///
/// Error: std.mem.Allocator.Error
/// std.mem.Allocator.Error.OutOfMemory - The allocator cannot allocate the memory required
/// Error: Allocator.Error
/// error.OutOfMemory - The allocator cannot allocate the memory required
///
pub fn init(mem_profile: *const mem.MemProfile, allocator: *std.mem.Allocator) std.mem.Allocator.Error!VirtualMemoryManager(arch.VmmPayload) {
std.log.info(.tty, "Init\n", .{});
defer std.log.info(.tty, "Done\n", .{});
pub fn init(mem_profile: *const mem.MemProfile, allocator: *Allocator) Allocator.Error!VirtualMemoryManager(arch.VmmPayload) {
std.log.info(.vmm, "Init\n", .{});
defer std.log.info(.vmm, "Done\n", .{});
var vmm = try VirtualMemoryManager(arch.VmmPayload).init(@ptrToInt(&KERNEL_ADDR_OFFSET), 0xFFFFFFFF, allocator, arch.VMM_MAPPER, arch.KERNEL_VMM_PAYLOAD);
// Map in kernel
// Calculate start and end of mapping
const v_start = std.mem.alignBackward(@ptrToInt(mem_profile.vaddr_start), BLOCK_SIZE);
const v_end = std.mem.alignForward(@ptrToInt(mem_profile.vaddr_end) + mem.FIXED_ALLOC_SIZE, BLOCK_SIZE);
const p_start = std.mem.alignBackward(@ptrToInt(mem_profile.physaddr_start), BLOCK_SIZE);
const p_end = std.mem.alignForward(@ptrToInt(mem_profile.physaddr_end) + mem.FIXED_ALLOC_SIZE, BLOCK_SIZE);
vmm.set(.{ .start = v_start, .end = v_end }, mem.Range{ .start = p_start, .end = p_end }, .{ .kernel = true, .writable = false, .cachable = true }) catch |e| panic(@errorReturnTrace(), "Failed mapping kernel code in VMM: {}", .{e});
// Map all the reserved virtual addresses.
for (mem_profile.virtual_reserved) |entry| {
const virtual = mem.Range{ .start = std.mem.alignBackward(entry.virtual.start, BLOCK_SIZE), .end = std.mem.alignForward(entry.virtual.end, BLOCK_SIZE) };
const physical: ?mem.Range = if (entry.physical) |phys| mem.Range{ .start = std.mem.alignBackward(phys.start, BLOCK_SIZE), .end = std.mem.alignForward(phys.end, BLOCK_SIZE) } else null;
const virtual = mem.Range{
.start = std.mem.alignBackward(entry.virtual.start, BLOCK_SIZE),
.end = std.mem.alignForward(entry.virtual.end, BLOCK_SIZE),
};
const physical: ?mem.Range = if (entry.physical) |phys|
mem.Range{
.start = std.mem.alignBackward(phys.start, BLOCK_SIZE),
.end = std.mem.alignForward(phys.end, BLOCK_SIZE),
}
else
null;
vmm.set(virtual, physical, .{ .kernel = true, .writable = true, .cachable = true }) catch |e| switch (e) {
VmmError.AlreadyAllocated => {},
else => panic(@errorReturnTrace(), "Failed mapping region in VMM {}: {}\n", .{ entry, e }),
@ -380,7 +389,7 @@ pub fn init(mem_profile: *const mem.MemProfile, allocator: *std.mem.Allocator) s
test "alloc and free" {
const num_entries = 512;
var vmm = try testInit(num_entries);
var allocations = test_allocations orelse unreachable;
var allocations = test_allocations.?;
var virtual_allocations = std.ArrayList(usize).init(std.testing.allocator);
defer virtual_allocations.deinit();
@ -399,7 +408,7 @@ test "alloc and free" {
} else {
// Else it should have succeeded and allocated the correct address
std.testing.expectEqual(@as(?usize, vmm.start + entry * BLOCK_SIZE), result);
try virtual_allocations.append(result orelse unreachable);
try virtual_allocations.append(result.?);
}
// Make sure that the entries are set or not depending on the allocation success
@ -471,7 +480,7 @@ test "set" {
// Make sure it put the correct address in the map
std.testing.expect(vmm.allocations.get(vstart) != null);
var allocations = test_allocations orelse unreachable;
var allocations = test_allocations.?;
// The entries before the virtual start shouldn't be set
var vaddr = vmm.start;
while (vaddr < vstart) : (vaddr += BLOCK_SIZE) {
@ -499,10 +508,10 @@ var test_mapper = Mapper(u8){ .mapFn = testMap, .unmapFn = testUnmap };
/// Return: VirtualMemoryManager(u8)
/// The VMM constructed
///
/// Error: std.mem.Allocator.Error
/// Error: Allocator.Error
/// OutOfMemory: The allocator couldn't allocate the structures needed
///
fn testInit(num_entries: u32) std.mem.Allocator.Error!VirtualMemoryManager(u8) {
fn testInit(num_entries: u32) Allocator.Error!VirtualMemoryManager(u8) {
if (test_allocations == null) {
test_allocations = try bitmap.Bitmap(u64).init(num_entries, std.heap.page_allocator);
} else |allocations| {
@ -524,7 +533,7 @@ fn testInit(num_entries: u32) std.mem.Allocator.Error!VirtualMemoryManager(u8) {
.modules = &[_]mem.Module{},
};
pmm.init(&mem_profile, std.heap.page_allocator);
return try VirtualMemoryManager(u8).init(0, num_entries * BLOCK_SIZE, std.heap.page_allocator, test_mapper, 39);
return VirtualMemoryManager(u8).init(0, num_entries * BLOCK_SIZE, std.heap.page_allocator, test_mapper, 39);
}
///
@ -536,14 +545,14 @@ fn testInit(num_entries: u32) std.mem.Allocator.Error!VirtualMemoryManager(u8) {
/// IN pstart: usize - The start of the physical region to map
/// IN pend: usize - The end of the physical region to map
/// IN attrs: Attributes - The attributes to map with
/// IN/OUT allocator: *std.mem.Allocator - The allocator to use. Ignored
/// IN/OUT allocator: *Allocator - The allocator to use. Ignored
/// IN payload: u8 - The payload value. Expected to be 39
///
fn testMap(vstart: usize, vend: usize, pstart: usize, pend: usize, attrs: Attributes, allocator: *std.mem.Allocator, payload: u8) (std.mem.Allocator.Error || MapperError)!void {
fn testMap(vstart: usize, vend: usize, pstart: usize, pend: usize, attrs: Attributes, allocator: *Allocator, payload: u8) (Allocator.Error || MapperError)!void {
std.testing.expectEqual(@as(u8, 39), payload);
var vaddr = vstart;
while (vaddr < vend) : (vaddr += BLOCK_SIZE) {
(test_allocations orelse unreachable).setEntry(vaddr / BLOCK_SIZE) catch unreachable;
(test_allocations.?).setEntry(vaddr / BLOCK_SIZE) catch unreachable;
}
}
@ -555,11 +564,11 @@ fn testMap(vstart: usize, vend: usize, pstart: usize, pend: usize, attrs: Attrib
/// IN vend: usize - The end of the virtual region to unmap
/// IN payload: u8 - The payload value. Expected to be 39
///
fn testUnmap(vstart: usize, vend: usize, payload: u8) (std.mem.Allocator.Error || MapperError)!void {
fn testUnmap(vstart: usize, vend: usize, payload: u8) (Allocator.Error || MapperError)!void {
std.testing.expectEqual(@as(u8, 39), payload);
var vaddr = vstart;
while (vaddr < vend) : (vaddr += BLOCK_SIZE) {
(test_allocations orelse unreachable).clearEntry(vaddr / BLOCK_SIZE) catch unreachable;
(test_allocations.?).clearEntry(vaddr / BLOCK_SIZE) catch unreachable;
}
}
@ -574,7 +583,7 @@ fn testUnmap(vstart: usize, vend: usize, payload: u8) (std.mem.Allocator.Error |
///
fn runtimeTests(comptime Payload: type, vmm: VirtualMemoryManager(Payload), mem_profile: *const mem.MemProfile) void {
const v_start = std.mem.alignBackward(@ptrToInt(mem_profile.vaddr_start), BLOCK_SIZE);
const v_end = std.mem.alignForward(@ptrToInt(mem_profile.vaddr_end) + mem.FIXED_ALLOC_SIZE, BLOCK_SIZE);
const v_end = std.mem.alignForward(@ptrToInt(mem_profile.vaddr_end), BLOCK_SIZE);
var vaddr = vmm.start;
while (vaddr < vmm.end - BLOCK_SIZE) : (vaddr += BLOCK_SIZE) {
@ -597,5 +606,5 @@ fn runtimeTests(comptime Payload: type, vmm: VirtualMemoryManager(Payload), mem_
}
}
std.log.info(.tty, "Tested allocations\n", .{});
std.log.info(.vmm, "Tested allocations\n", .{});
}

View file

@ -122,7 +122,7 @@ pub fn initTTY(boot_payload: BootPayload) TTY {
};
}
pub fn initMem(payload: BootPayload) std.mem.Allocator.Error!mem.MemProfile {
pub fn initMem(payload: BootPayload) Allocator.Error!mem.MemProfile {
return MemProfile{
.vaddr_end = @ptrCast([*]u8, &KERNEL_VADDR_END),
.vaddr_start = @ptrCast([*]u8, &KERNEL_VADDR_START),
@ -142,7 +142,7 @@ pub fn initTaskStack(entry_point: usize, allocator: *Allocator) Allocator.Error!
return ret;
}
pub fn init(payload: BootPayload, mem_profile: *const MemProfile, allocator: *Allocator) void {
pub fn init(mem_profile: *const MemProfile) void {
// I'll get back to this as this doesn't effect the current testing.
// When I come on to the mem.zig testing, I'll fix :)
//return mock_framework.performAction("init", void, mem_profile, allocator);

View file

@ -28,7 +28,6 @@ pub const MemProfile = struct {
fixed_allocator: std.heap.FixedBufferAllocator,
};
// The size of the fixed allocator used before the heap is set up. Set to 1MiB.
const FIXED_ALLOC_SIZE = 1024 * 1024;
pub fn virtToPhys(virt: anytype) @TypeOf(virt) {

View file

@ -120,6 +120,8 @@ pub const RuntimeStep = struct {
std.debug.warn("{}\n", .{msg});
if (std.mem.indexOf(u8, msg, "FAILURE")) |_| {
return false;
} else if (std.mem.indexOf(u8, msg, "Kernel panic")) |_| {
return false;
} else if (std.mem.eql(u8, msg, "[info] (kmain): SUCCESS")) {
return true;
}