Merge pull request #130 from SamTebbs33/feature/update_zig_version
Update Pluto to Zig master
This commit is contained in:
commit
638ad81e82
21 changed files with 157 additions and 135 deletions
38
build.zig
38
build.zig
|
@ -3,30 +3,19 @@ const builtin = @import("builtin");
|
|||
const Builder = std.build.Builder;
|
||||
const LibExeObjStep = std.build.LibExeObjStep;
|
||||
const Step = std.build.Step;
|
||||
const Target = std.build.Target;
|
||||
const Target = std.Target;
|
||||
const CrossTarget = std.zig.CrossTarget;
|
||||
const fs = std.fs;
|
||||
const Mode = builtin.Mode;
|
||||
|
||||
pub fn build(b: *Builder) !void {
|
||||
const target = Target{
|
||||
.Cross = Target.Cross{
|
||||
.arch = .i386,
|
||||
.os = .freestanding,
|
||||
.abi = .gnu,
|
||||
.cpu_features = Target.CpuFeatures.initFromCpu(.i386, &builtin.Target.x86.cpu._i686),
|
||||
},
|
||||
const target = CrossTarget{
|
||||
.cpu_arch = .i386,
|
||||
.os_tag = .freestanding,
|
||||
.cpu_model = .{ .explicit = &Target.x86.cpu._i686 },
|
||||
};
|
||||
|
||||
const test_target = Target{
|
||||
.Cross = Target.Cross{
|
||||
.arch = .i386,
|
||||
.os = .linux,
|
||||
.abi = .gnu,
|
||||
.cpu_features = Target.CpuFeatures.initFromCpu(.i386, &builtin.Target.x86.cpu._i686),
|
||||
},
|
||||
};
|
||||
|
||||
const target_str = switch (target.getArch()) {
|
||||
const target_str = switch (target.getCpuArch()) {
|
||||
.i386 => "x86",
|
||||
else => unreachable,
|
||||
};
|
||||
|
@ -50,7 +39,7 @@ pub fn build(b: *Builder) !void {
|
|||
exec.addBuildOption(bool, "rt_test", rt_test);
|
||||
exec.setBuildMode(build_mode);
|
||||
exec.setLinkerScriptPath("link.ld");
|
||||
exec.setTheTarget(target);
|
||||
exec.setTarget(target);
|
||||
|
||||
const output_iso = try fs.path.join(b.allocator, &[_][]const u8{ b.exe_dir, "pluto.iso" });
|
||||
const iso_dir_path = try fs.path.join(b.allocator, &[_][]const u8{ b.exe_dir, "iso" });
|
||||
|
@ -77,14 +66,9 @@ pub fn build(b: *Builder) !void {
|
|||
unit_tests.addBuildOption([]const u8, "mock_path", mock_path);
|
||||
unit_tests.addBuildOption([]const u8, "arch_mock_path", arch_mock_path);
|
||||
|
||||
const qemu_bin = switch (test_target.getArch()) {
|
||||
.i386 => "qemu-i386",
|
||||
else => unreachable,
|
||||
};
|
||||
if (builtin.os.tag != .windows) unit_tests.enable_qemu = true;
|
||||
|
||||
// We need this as the build as the make() doesn't handle it properly
|
||||
unit_tests.setExecCmd(&[_]?[]const u8{ qemu_bin, null });
|
||||
unit_tests.setTheTarget(test_target);
|
||||
unit_tests.setTarget(.{ .cpu_arch = .i386 });
|
||||
|
||||
test_step.dependOn(&unit_tests.step);
|
||||
}
|
||||
|
@ -92,7 +76,7 @@ pub fn build(b: *Builder) !void {
|
|||
const run_step = b.step("run", "Run with qemu");
|
||||
const run_debug_step = b.step("debug-run", "Run with qemu and wait for a gdb connection");
|
||||
|
||||
const qemu_bin = switch (target.getArch()) {
|
||||
const qemu_bin = switch (target.getCpuArch()) {
|
||||
.i386 => "qemu-system-i386",
|
||||
else => unreachable,
|
||||
};
|
||||
|
|
|
@ -425,6 +425,7 @@ pub fn setTssStack(esp0: u32) void {
|
|||
///
|
||||
pub fn init() void {
|
||||
log.logInfo("Init gdt\n", .{});
|
||||
defer log.logInfo("Done gdt\n", .{});
|
||||
// Initiate TSS
|
||||
gdt_entries[TSS_INDEX] = makeEntry(@ptrToInt(&tss), @sizeOf(TtsEntry) - 1, TSS_SEGMENT, NULL_FLAGS);
|
||||
|
||||
|
@ -437,8 +438,6 @@ pub fn init() void {
|
|||
// Load the TSS
|
||||
arch.ltr(TSS_OFFSET);
|
||||
|
||||
log.logInfo("Done\n", .{});
|
||||
|
||||
if (build_options.rt_test) runtimeTests();
|
||||
}
|
||||
|
||||
|
|
|
@ -180,11 +180,11 @@ pub fn openInterruptGate(index: u8, handler: InterruptHandler) IdtError!void {
|
|||
///
|
||||
pub fn init() void {
|
||||
log.logInfo("Init idt\n", .{});
|
||||
defer log.logInfo("Done idt\n", .{});
|
||||
|
||||
idt_ptr.base = @ptrToInt(&idt_entries);
|
||||
|
||||
arch.lidt(&idt_ptr);
|
||||
log.logInfo("Done\n", .{});
|
||||
|
||||
if (build_options.rt_test) runtimeTests();
|
||||
}
|
||||
|
|
|
@ -129,14 +129,13 @@ pub fn registerIrq(irq_num: u8, handler: IrqHandler) IrqError!void {
|
|||
///
|
||||
pub fn init() void {
|
||||
log.logInfo("Init irq\n", .{});
|
||||
defer log.logInfo("Done irq\n", .{});
|
||||
|
||||
comptime var i = IRQ_OFFSET;
|
||||
inline while (i < IRQ_OFFSET + 16) : (i += 1) {
|
||||
openIrq(i, interrupts.getInterruptStub(i));
|
||||
}
|
||||
|
||||
log.logInfo("Done\n", .{});
|
||||
|
||||
if (build_options.rt_test) runtimeTests();
|
||||
}
|
||||
|
||||
|
|
|
@ -235,6 +235,7 @@ pub fn registerIsr(isr_num: u16, handler: IsrHandler) IsrError!void {
|
|||
///
|
||||
pub fn init() void {
|
||||
log.logInfo("Init isr\n", .{});
|
||||
defer log.logInfo("Done isr\n", .{});
|
||||
|
||||
comptime var i = 0;
|
||||
inline while (i < 32) : (i += 1) {
|
||||
|
@ -243,8 +244,6 @@ pub fn init() void {
|
|||
|
||||
openIsr(syscalls.INTERRUPT, interrupts.getInterruptStub(syscalls.INTERRUPT));
|
||||
|
||||
log.logInfo("Done\n", .{});
|
||||
|
||||
if (build_options.rt_test) runtimeTests();
|
||||
}
|
||||
|
||||
|
|
|
@ -293,6 +293,8 @@ fn pageFault(state: *arch.InterruptContext) void {
|
|||
///
|
||||
pub fn init(mb_info: *multiboot.multiboot_info_t, mem_profile: *const MemProfile, allocator: *std.mem.Allocator) void {
|
||||
log.logInfo("Init paging\n", .{});
|
||||
defer log.logInfo("Done paging\n", .{});
|
||||
|
||||
// Calculate start and end of mapping
|
||||
const v_start = std.mem.alignBackward(@ptrToInt(mem_profile.vaddr_start), PAGE_SIZE_4KB);
|
||||
const v_end = std.mem.alignForward(@ptrToInt(mem_profile.vaddr_end) + mem_profile.fixed_alloc_size, PAGE_SIZE_4KB);
|
||||
|
@ -351,7 +353,6 @@ pub fn init(mb_info: *multiboot.multiboot_info_t, mem_profile: *const MemProfile
|
|||
isr.registerIsr(isr.PAGE_FAULT, if (options.rt_test) rt_pageFault else pageFault) catch |e| {
|
||||
panic(@errorReturnTrace(), "Failed to register page fault ISR: {}\n", .{e});
|
||||
};
|
||||
log.logInfo("Done\n", .{});
|
||||
|
||||
if (options.rt_test) runtimeTests(v_end);
|
||||
}
|
||||
|
@ -410,7 +411,7 @@ test "virtToTableEntryIdx" {
|
|||
}
|
||||
|
||||
test "mapDirEntry" {
|
||||
var allocator = std.heap.direct_allocator;
|
||||
var allocator = std.heap.page_allocator;
|
||||
var dir: Directory = Directory{ .entries = [_]DirectoryEntry{0} ** ENTRIES_PER_DIRECTORY, .tables = [_]?*Table{null} ** ENTRIES_PER_DIRECTORY };
|
||||
var phys: usize = 0 * PAGE_SIZE_4MB;
|
||||
const phys_end: usize = phys + PAGE_SIZE_4MB;
|
||||
|
@ -425,7 +426,7 @@ test "mapDirEntry" {
|
|||
}
|
||||
|
||||
test "mapDirEntry returns errors correctly" {
|
||||
var allocator = std.heap.direct_allocator;
|
||||
var allocator = std.heap.page_allocator;
|
||||
var dir = Directory{ .entries = [_]DirectoryEntry{0} ** ENTRIES_PER_DIRECTORY, .tables = undefined };
|
||||
testing.expectError(PagingError.UnalignedVirtAddresses, mapDirEntry(&dir, 1, PAGE_SIZE_4KB + 1, 0, PAGE_SIZE_4KB, allocator));
|
||||
testing.expectError(PagingError.UnalignedPhysAddresses, mapDirEntry(&dir, 0, PAGE_SIZE_4KB, 1, PAGE_SIZE_4KB + 1, allocator));
|
||||
|
@ -435,7 +436,7 @@ test "mapDirEntry returns errors correctly" {
|
|||
}
|
||||
|
||||
test "mapDir" {
|
||||
var allocator = std.heap.direct_allocator;
|
||||
var allocator = std.heap.page_allocator;
|
||||
var dir = Directory{ .entries = [_]DirectoryEntry{0} ** ENTRIES_PER_DIRECTORY, .tables = [_]?*Table{null} ** ENTRIES_PER_DIRECTORY };
|
||||
const phys_start: usize = PAGE_SIZE_4MB * 2;
|
||||
const virt_start: usize = PAGE_SIZE_4MB * 4;
|
||||
|
|
|
@ -433,6 +433,7 @@ pub fn clearMask(irq_num: u8) void {
|
|||
///
|
||||
pub fn init() void {
|
||||
log.logInfo("Init pic\n", .{});
|
||||
defer log.logInfo("Done pic\n", .{});
|
||||
|
||||
// Initiate
|
||||
sendCommandMaster(ICW1_INITIALISATION | ICW1_EXPECT_ICW4);
|
||||
|
@ -467,8 +468,6 @@ pub fn init() void {
|
|||
// Clear the IRQ for the slave
|
||||
clearMask(IRQ_CASCADE_FOR_SLAVE);
|
||||
|
||||
log.logInfo("Done\n", .{});
|
||||
|
||||
if (build_options.rt_test) runtimeTests();
|
||||
}
|
||||
|
||||
|
|
|
@ -371,6 +371,8 @@ pub fn getFrequency() u32 {
|
|||
///
|
||||
pub fn init() void {
|
||||
log.logInfo("Init pit\n", .{});
|
||||
defer log.logInfo("Done pit\n", .{});
|
||||
|
||||
// Set up counter 0 at 10000hz in a square wave mode counting in binary
|
||||
const freq: u32 = 10000;
|
||||
setupCounter(CounterSelect.Counter0, freq, OCW_MODE_SQUARE_WAVE_GENERATOR | OCW_BINARY_COUNT_BINARY) catch |e| {
|
||||
|
@ -389,8 +391,6 @@ pub fn init() void {
|
|||
},
|
||||
};
|
||||
|
||||
log.logInfo("Done\n", .{});
|
||||
|
||||
if (build_options.rt_test) runtimeTests();
|
||||
}
|
||||
|
||||
|
|
|
@ -252,6 +252,7 @@ fn enableInterrupts() void {
|
|||
///
|
||||
pub fn init() void {
|
||||
log.logInfo("Init rtc\n", .{});
|
||||
defer log.logInfo("Done rtc\n", .{});
|
||||
|
||||
// Register the interrupt handler
|
||||
irq.registerIrq(pic.IRQ_REAL_TIME_CLOCK, rtcHandler) catch |err| switch (err) {
|
||||
|
@ -276,16 +277,12 @@ pub fn init() void {
|
|||
// Enable RTC interrupts
|
||||
enableInterrupts();
|
||||
|
||||
// Read status register C to clear any interrupts that may have happened during set up
|
||||
//const reg_c = cmos.readStatusRegister(cmos.StatusRegister.C, false);
|
||||
|
||||
// Can now enable interrupts
|
||||
arch.enableInterrupts();
|
||||
|
||||
// Read status register C to clear any interrupts that may have happened during set up
|
||||
const reg_c = cmos.readStatusRegister(cmos.StatusRegister.C, false);
|
||||
|
||||
log.logInfo("Done\n", .{});
|
||||
|
||||
if (build_options.rt_test) runtimeTests();
|
||||
}
|
||||
|
||||
|
|
|
@ -238,8 +238,9 @@ inline fn syscallArg(ctx: *arch.InterruptContext, comptime arg_idx: u32) u32 {
|
|||
///
|
||||
pub fn init() void {
|
||||
log.logInfo("Init syscalls\n", .{});
|
||||
defer log.logInfo("Done syscalls\n", .{});
|
||||
|
||||
isr.registerIsr(INTERRUPT, handle) catch unreachable;
|
||||
log.logInfo("Done\n", .{});
|
||||
if (options.rt_test) runtimeTests();
|
||||
}
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ pub fn Bitmap(comptime BitmapType: type) type {
|
|||
}
|
||||
|
||||
test "setEntry" {
|
||||
var bmp = try Bitmap(u32).init(31, std.heap.direct_allocator);
|
||||
var bmp = try Bitmap(u32).init(31, std.heap.page_allocator);
|
||||
testing.expectEqual(@as(u32, 31), bmp.num_free_entries);
|
||||
|
||||
try bmp.setEntry(0);
|
||||
|
@ -178,7 +178,7 @@ test "setEntry" {
|
|||
}
|
||||
|
||||
test "clearEntry" {
|
||||
var bmp = try Bitmap(u32).init(32, std.heap.direct_allocator);
|
||||
var bmp = try Bitmap(u32).init(32, std.heap.page_allocator);
|
||||
testing.expectEqual(@as(u32, 32), bmp.num_free_entries);
|
||||
|
||||
try bmp.setEntry(0);
|
||||
|
@ -204,7 +204,7 @@ test "clearEntry" {
|
|||
}
|
||||
|
||||
test "setFirstFree multiple bitmaps" {
|
||||
var bmp = try Bitmap(u8).init(9, std.heap.direct_allocator);
|
||||
var bmp = try Bitmap(u8).init(9, std.heap.page_allocator);
|
||||
|
||||
// Allocate the first entry
|
||||
testing.expectEqual(bmp.setFirstFree() orelse unreachable, 0);
|
||||
|
@ -239,7 +239,7 @@ test "setFirstFree multiple bitmaps" {
|
|||
testing.expectEqual(bmp.bitmaps[1], 1);
|
||||
}
|
||||
test "setFirstFree" {
|
||||
var bmp = try Bitmap(u32).init(32, std.heap.direct_allocator);
|
||||
var bmp = try Bitmap(u32).init(32, std.heap.page_allocator);
|
||||
|
||||
// Allocate the first entry
|
||||
testing.expectEqual(bmp.setFirstFree() orelse unreachable, 0);
|
||||
|
@ -260,7 +260,7 @@ test "setFirstFree" {
|
|||
}
|
||||
|
||||
test "isSet" {
|
||||
var bmp = try Bitmap(u32).init(32, std.heap.direct_allocator);
|
||||
var bmp = try Bitmap(u32).init(32, std.heap.page_allocator);
|
||||
|
||||
bmp.bitmaps[0] = 1;
|
||||
// Make sure that only the set entry is considered set
|
||||
|
@ -292,7 +292,7 @@ test "isSet" {
|
|||
}
|
||||
|
||||
test "indexToBit" {
|
||||
var bmp = try Bitmap(u8).init(10, std.heap.direct_allocator);
|
||||
var bmp = try Bitmap(u8).init(10, std.heap.page_allocator);
|
||||
testing.expectEqual(bmp.indexToBit(0), 1);
|
||||
testing.expectEqual(bmp.indexToBit(1), 2);
|
||||
testing.expectEqual(bmp.indexToBit(2), 4);
|
||||
|
|
|
@ -39,8 +39,9 @@ export fn kmain(mb_info: *multiboot.multiboot_info_t, mb_magic: u32) void {
|
|||
serial.init(serial.DEFAULT_BAUDRATE, serial.Port.COM1) catch |e| {
|
||||
panic_root.panic(@errorReturnTrace(), "Failed to initialise serial: {}", .{e});
|
||||
};
|
||||
if (build_options.rt_test)
|
||||
log.runtimeTests();
|
||||
|
||||
if (build_options.rt_test) log.runtimeTests();
|
||||
|
||||
const mem_profile = mem.init(mb_info);
|
||||
var buffer = mem_profile.vaddr_end[0..mem_profile.fixed_alloc_size];
|
||||
var fixed_allocator = std.heap.FixedBufferAllocator.init(buffer);
|
||||
|
@ -56,6 +57,7 @@ export fn kmain(mb_info: *multiboot.multiboot_info_t, mb_magic: u32) void {
|
|||
tty.init();
|
||||
|
||||
log.logInfo("Init done\n", .{});
|
||||
|
||||
tty.print("Hello Pluto from kernel :)\n", .{});
|
||||
// The panic runtime tests must run last as they never return
|
||||
if (options.rt_test) panic_root.runtimeTests();
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
const serial = @import("serial.zig");
|
||||
const fmt = @import("std").fmt;
|
||||
const std = @import("std");
|
||||
const fmt = std.fmt;
|
||||
|
||||
/// The errors that can occur when logging
|
||||
const LoggingError = error{};
|
||||
|
||||
/// The OutStream for the format function
|
||||
const OutStream = std.io.OutStream(void, LoggingError, logCallback);
|
||||
|
||||
pub const Level = enum {
|
||||
INFO,
|
||||
|
@ -8,8 +15,9 @@ pub const Level = enum {
|
|||
ERROR,
|
||||
};
|
||||
|
||||
fn logCallback(context: void, str: []const u8) anyerror!void {
|
||||
fn logCallback(context: void, str: []const u8) LoggingError!usize {
|
||||
serial.writeBytes(str, serial.Port.COM1);
|
||||
return str.len;
|
||||
}
|
||||
|
||||
///
|
||||
|
@ -21,7 +29,7 @@ fn logCallback(context: void, str: []const u8) anyerror!void {
|
|||
/// IN args: var - A struct of the parameters for the format string.
|
||||
///
|
||||
pub fn log(comptime level: Level, comptime format: []const u8, args: var) void {
|
||||
fmt.format({}, anyerror, logCallback, "[" ++ @tagName(level) ++ "] " ++ format, args) catch unreachable;
|
||||
fmt.format(OutStream{ .context = {} }, "[" ++ @tagName(level) ++ "] " ++ format, args) catch unreachable;
|
||||
}
|
||||
|
||||
///
|
||||
|
|
|
@ -53,36 +53,6 @@ const FIXED_ALLOC_SIZE: usize = 1024 * 1024;
|
|||
/// release-safe. This is a workaround until that is fixed.
|
||||
var ADDR_OFFSET: usize = undefined;
|
||||
|
||||
///
|
||||
/// Initialise the system's memory profile based on linker symbols and the multiboot info struct.
|
||||
///
|
||||
/// Arguments:
|
||||
/// IN mb_info: *multiboot.multiboot_info_t - The multiboot info passed by the bootloader.
|
||||
///
|
||||
/// Return: MemProfile
|
||||
/// The memory profile constructed from the exported linker symbols and the relevant multiboot info.
|
||||
///
|
||||
pub fn init(mb_info: *multiboot.multiboot_info_t) MemProfile {
|
||||
log.logInfo("Init mem\n", .{});
|
||||
defer log.logInfo("Done\n", .{});
|
||||
const mods_count = mb_info.mods_count;
|
||||
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 mem_profile = MemProfile{
|
||||
.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),
|
||||
// Total memory available including the initial 1MiB that grub doesn't include
|
||||
.mem_kb = mb_info.mem_upper + mb_info.mem_lower + 1024,
|
||||
.fixed_alloc_size = FIXED_ALLOC_SIZE,
|
||||
.boot_modules = @intToPtr([*]multiboot.multiboot_mod_list, physToVirt(mb_info.mods_addr))[0..mods_count],
|
||||
.mem_map = @intToPtr([*]multiboot.multiboot_memory_map_t, mmap_addr)[0..num_mmap_entries],
|
||||
};
|
||||
return mem_profile;
|
||||
}
|
||||
|
||||
///
|
||||
/// Convert a virtual address to its physical counterpart by subtracting the kernel virtual offset from the virtual address.
|
||||
///
|
||||
|
@ -94,7 +64,7 @@ pub fn init(mb_info: *multiboot.multiboot_info_t) MemProfile {
|
|||
///
|
||||
pub inline fn virtToPhys(virt: var) @TypeOf(virt) {
|
||||
const T = @TypeOf(virt);
|
||||
return switch (@typeId(T)) {
|
||||
return switch (@typeInfo(T)) {
|
||||
.Pointer => @intToPtr(T, @ptrToInt(virt) - ADDR_OFFSET),
|
||||
.Int => virt - ADDR_OFFSET,
|
||||
else => @compileError("Only pointers and integers are supported"),
|
||||
|
@ -112,13 +82,43 @@ pub inline fn virtToPhys(virt: var) @TypeOf(virt) {
|
|||
///
|
||||
pub inline fn physToVirt(phys: var) @TypeOf(phys) {
|
||||
const T = @TypeOf(phys);
|
||||
return switch (@typeId(T)) {
|
||||
return switch (@typeInfo(T)) {
|
||||
.Pointer => @intToPtr(T, @ptrToInt(phys) + ADDR_OFFSET),
|
||||
.Int => phys + ADDR_OFFSET,
|
||||
else => @compileError("Only pointers and integers are supported"),
|
||||
};
|
||||
}
|
||||
|
||||
///
|
||||
/// Initialise the system's memory profile based on linker symbols and the multiboot info struct.
|
||||
///
|
||||
/// Arguments:
|
||||
/// IN mb_info: *multiboot.multiboot_info_t - The multiboot info passed by the bootloader.
|
||||
///
|
||||
/// Return: MemProfile
|
||||
/// The memory profile constructed from the exported linker symbols and the relevant multiboot info.
|
||||
///
|
||||
pub fn init(mb_info: *multiboot.multiboot_info_t) MemProfile {
|
||||
log.logInfo("Init mem\n", .{});
|
||||
defer log.logInfo("Done mem\n", .{});
|
||||
|
||||
const mods_count = mb_info.mods_count;
|
||||
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);
|
||||
return .{
|
||||
.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),
|
||||
// Total memory available including the initial 1MiB that grub doesn't include
|
||||
.mem_kb = mb_info.mem_upper + mb_info.mem_lower + 1024,
|
||||
.fixed_alloc_size = FIXED_ALLOC_SIZE,
|
||||
.boot_modules = @intToPtr([*]multiboot.multiboot_mod_list, physToVirt(mb_info.mods_addr))[0..mods_count],
|
||||
.mem_map = @intToPtr([*]multiboot.multiboot_memory_map_t, mmap_addr)[0..num_mmap_entries],
|
||||
};
|
||||
}
|
||||
|
||||
test "physToVirt" {
|
||||
ADDR_OFFSET = 0xC0000000;
|
||||
const offset: usize = ADDR_OFFSET;
|
||||
|
|
|
@ -77,11 +77,11 @@ const SymbolMap = struct {
|
|||
/// The function name associated with that program address, or null if one wasn't found.
|
||||
///
|
||||
pub fn search(self: *const SymbolMap, addr: usize) ?[]const u8 {
|
||||
if (self.symbols.len == 0)
|
||||
if (self.symbols.items.len == 0)
|
||||
return null;
|
||||
// Find the first element whose address is greater than addr
|
||||
var previous_name: ?[]const u8 = null;
|
||||
for (self.symbols.toSliceConst()) |entry| {
|
||||
for (self.symbols.items) |entry| {
|
||||
if (entry.addr > addr)
|
||||
return previous_name;
|
||||
previous_name = entry.func_name;
|
||||
|
@ -116,7 +116,7 @@ pub fn panic(trace: ?*builtin.StackTrace, comptime format: []const u8, args: var
|
|||
} else {
|
||||
const first_ret_addr = @returnAddress();
|
||||
var last_addr: u64 = 0;
|
||||
var it = std.debug.StackIterator.init(first_ret_addr);
|
||||
var it = std.debug.StackIterator.init(first_ret_addr, null);
|
||||
while (it.next()) |ret_addr| {
|
||||
if (ret_addr != last_addr) logTraceAddress(ret_addr);
|
||||
last_addr = ret_addr;
|
||||
|
@ -278,7 +278,8 @@ fn parseMapEntry(start: *[*]const u8, end: *const u8) !MapEntry {
|
|||
///
|
||||
pub fn init(mem_profile: *const mem.MemProfile, allocator: *std.mem.Allocator) !void {
|
||||
log.logInfo("Init panic\n", .{});
|
||||
defer log.logInfo("Done\n", .{});
|
||||
defer log.logInfo("Done panic\n", .{});
|
||||
|
||||
// Exit if we haven't loaded all debug modules
|
||||
if (mem_profile.boot_modules.len < 1)
|
||||
return;
|
||||
|
@ -288,7 +289,7 @@ pub fn init(mem_profile: *const mem.MemProfile, allocator: *std.mem.Allocator) !
|
|||
const mod_start = mem.physToVirt(module.mod_start);
|
||||
const mod_end = mem.physToVirt(module.mod_end) - 1;
|
||||
const mod_str_ptr = mem.physToVirt(@intToPtr([*:0]u8, module.cmdline));
|
||||
if (std.mem.eql(u8, std.mem.toSlice(u8, mod_str_ptr), "kernel.map")) {
|
||||
if (std.mem.eql(u8, std.mem.span(mod_str_ptr), "kernel.map")) {
|
||||
kmap_start = mod_start;
|
||||
kmap_end = mod_end;
|
||||
break;
|
||||
|
@ -422,7 +423,7 @@ test "parseMapEntry fails without a name" {
|
|||
}
|
||||
|
||||
test "SymbolMap" {
|
||||
var allocator = std.heap.direct_allocator;
|
||||
var allocator = std.heap.page_allocator;
|
||||
var map = SymbolMap.init(allocator);
|
||||
try map.add("abc"[0..], 123);
|
||||
try map.addEntry(MapEntry{ .func_name = "def"[0..], .addr = 456 });
|
||||
|
|
|
@ -91,6 +91,8 @@ pub fn free(addr: usize) (PmmBitmap.BitmapError || PmmError)!void {
|
|||
///
|
||||
pub fn init(mem: *const MemProfile, allocator: *std.mem.Allocator) void {
|
||||
log.logInfo("Init pmm\n", .{});
|
||||
defer log.logInfo("Done pmm\n", .{});
|
||||
|
||||
bitmap = PmmBitmap.init(mem.mem_kb * 1024 / BLOCK_SIZE, allocator) catch @panic("Bitmap allocation failed");
|
||||
|
||||
// Occupy the regions of memory that the memory map describes as reserved
|
||||
|
@ -118,10 +120,8 @@ pub fn init(mem: *const MemProfile, allocator: *std.mem.Allocator) void {
|
|||
else => panic(@errorReturnTrace(), "Failed setting kernel code address 0x{x} as occupied: {}", .{ addr, e }),
|
||||
};
|
||||
}
|
||||
log.logInfo("Done\n", .{});
|
||||
if (build_options.rt_test) {
|
||||
runtimeTests(mem);
|
||||
}
|
||||
|
||||
if (build_options.rt_test) runtimeTests(mem);
|
||||
}
|
||||
|
||||
///
|
||||
|
@ -154,7 +154,7 @@ fn runtimeTests(mem: *const MemProfile) void {
|
|||
}
|
||||
|
||||
test "alloc" {
|
||||
bitmap = try Bitmap(u32).init(32, std.heap.direct_allocator);
|
||||
bitmap = try Bitmap(u32).init(32, std.heap.page_allocator);
|
||||
comptime var addr = 0;
|
||||
comptime var i = 0;
|
||||
// Allocate all entries, making sure they succeed and return the correct addresses
|
||||
|
@ -171,7 +171,7 @@ test "alloc" {
|
|||
}
|
||||
|
||||
test "free" {
|
||||
bitmap = try Bitmap(u32).init(32, std.heap.direct_allocator);
|
||||
bitmap = try Bitmap(u32).init(32, std.heap.page_allocator);
|
||||
comptime var i = 0;
|
||||
// Allocate and free all entries
|
||||
inline while (i < 32) : (i += 1) {
|
||||
|
@ -186,7 +186,7 @@ test "free" {
|
|||
|
||||
test "setAddr and isSet" {
|
||||
const num_entries: u32 = 32;
|
||||
bitmap = try Bitmap(u32).init(num_entries, std.heap.direct_allocator);
|
||||
bitmap = try Bitmap(u32).init(num_entries, std.heap.page_allocator);
|
||||
var addr: u32 = 0;
|
||||
var i: u32 = 0;
|
||||
while (i < num_entries) : ({
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const arch = @import("arch.zig").internals;
|
||||
const panic = @import("panic.zig").panic;
|
||||
const testing = @import("std").testing;
|
||||
const options = @import("build_options");
|
||||
const build_options = @import("build_options");
|
||||
|
||||
/// The I/O port numbers associated with each serial port
|
||||
pub const Port = enum(u16) {
|
||||
|
@ -147,12 +147,13 @@ pub fn init(baud: u32, port: Port) SerialError!void {
|
|||
// Send the divisor's msb
|
||||
arch.outb(port_int + 1, @truncate(u8, divisor >> 8));
|
||||
// Send the properties to use
|
||||
arch.outb(port_int + LCR, lcrValue(CHAR_LEN, SINGLE_STOP_BIT, PARITY_BIT, 0) catch |e| panic(@errorReturnTrace(), "Failed to setup serial properties: {}", .{e}));
|
||||
arch.outb(port_int + LCR, lcrValue(CHAR_LEN, SINGLE_STOP_BIT, PARITY_BIT, 0) catch |e| {
|
||||
panic(@errorReturnTrace(), "Failed to setup serial properties: {}", .{e});
|
||||
});
|
||||
// Stop initialisation
|
||||
arch.outb(port_int + 1, 0);
|
||||
|
||||
if (options.rt_test)
|
||||
runtimeTests();
|
||||
if (build_options.rt_test) runtimeTests();
|
||||
}
|
||||
|
||||
test "lcrValue computes the correct value" {
|
||||
|
|
|
@ -11,6 +11,9 @@ const vga = if (is_test) @import(mock_path ++ "vga_mock.zig") else @import("vga.
|
|||
const log = if (is_test) @import(mock_path ++ "log_mock.zig") else @import("log.zig");
|
||||
const panic = if (is_test) @import(mock_path ++ "panic_mock.zig").panic else @import("panic.zig").panic;
|
||||
|
||||
/// The OutStream for the format function
|
||||
const OutStream = std.io.OutStream(void, TtyError, printCallback);
|
||||
|
||||
/// The error set for if there is an error whiles printing.
|
||||
const TtyError = error{
|
||||
/// If the printing tries to print outside the video buffer.
|
||||
|
@ -427,8 +430,9 @@ fn printLogo() void {
|
|||
/// Errors:
|
||||
/// TtyError.OutOfBounds - If trying to print beyond the video buffer.
|
||||
///
|
||||
fn printCallback(ctx: void, str: []const u8) TtyError!void {
|
||||
fn printCallback(ctx: void, str: []const u8) TtyError!usize {
|
||||
try writeString(str);
|
||||
return str.len;
|
||||
}
|
||||
|
||||
///
|
||||
|
@ -441,7 +445,7 @@ fn printCallback(ctx: void, str: []const u8) TtyError!void {
|
|||
///
|
||||
pub fn print(comptime format: []const u8, args: var) void {
|
||||
// Printing can't error because of the scrolling, if it does, we have a big problem
|
||||
fmt.format({}, TtyError, printCallback, format, args) catch |e| {
|
||||
fmt.format(OutStream{ .context = {} }, format, args) catch |e| {
|
||||
log.logError("TTY: Error printing. Error: {}\n", .{e});
|
||||
};
|
||||
}
|
||||
|
@ -570,6 +574,7 @@ pub fn getVideoBufferAddress() usize {
|
|||
///
|
||||
pub fn init() void {
|
||||
log.logInfo("Init tty\n", .{});
|
||||
defer log.logInfo("Done tty\n", .{});
|
||||
|
||||
// Video buffer in higher half
|
||||
if (is_test) {
|
||||
|
@ -631,8 +636,6 @@ pub fn init() void {
|
|||
displayPageNumber();
|
||||
updateCursor();
|
||||
|
||||
log.logInfo("Done\n", .{});
|
||||
|
||||
if (build_options.rt_test) runtimeTests();
|
||||
}
|
||||
|
||||
|
|
|
@ -145,7 +145,6 @@ inline fn sendData(data: u8) void {
|
|||
inline fn getData() u8 {
|
||||
return arch.inb(PORT_DATA);
|
||||
}
|
||||
|
||||
///
|
||||
/// Set the VGA register port to write to and sending data to that VGA register port.
|
||||
///
|
||||
|
@ -287,6 +286,7 @@ pub fn setCursorShape(shape: CursorShape) void {
|
|||
///
|
||||
pub fn init() void {
|
||||
log.logInfo("Init vga\n", .{});
|
||||
defer log.logInfo("Done vga\n", .{});
|
||||
|
||||
// Set the maximum scan line to 0x0F
|
||||
sendPortData(REG_MAXIMUM_SCAN_LINE, CURSOR_SCANLINE_END);
|
||||
|
@ -294,8 +294,6 @@ pub fn init() void {
|
|||
// Set by default the underline cursor
|
||||
setCursorShape(CursorShape.UNDERLINE);
|
||||
|
||||
log.logInfo("Done\n", .{});
|
||||
|
||||
if (build_options.rt_test) runtimeTests();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,23 +1,39 @@
|
|||
def get_test_cases(TestCase):
|
||||
return [
|
||||
TestCase("GDT init", [r"Init gdt", r"Done"]),
|
||||
TestCase("GDT init", [r"Init gdt"]),
|
||||
TestCase("GDT tests", [r"GDT: Tested loading GDT"]),
|
||||
TestCase("IDT init", [r"Init idt", r"Done"]),
|
||||
TestCase("GDT done", [r"Done gdt"]),
|
||||
|
||||
TestCase("IDT init", [r"Init idt"]),
|
||||
TestCase("IDT tests", [r"IDT: Tested loading IDT"]),
|
||||
TestCase("PIC init", [r"Init pic", r"Done"]),
|
||||
TestCase("IDT done", [r"Done idt"]),
|
||||
|
||||
TestCase("PIC init", [r"Init pic"]),
|
||||
TestCase("PIC tests", [r"PIC: Tested masking"]),
|
||||
TestCase("ISR init", [r"Init isr", r"Done"]),
|
||||
TestCase("PIC done", [r"Done pic"]),
|
||||
|
||||
TestCase("ISR init", [r"Init isr"]),
|
||||
TestCase("ISR tests", [r"ISR: Tested registered handlers", r"ISR: Tested opened IDT entries"]),
|
||||
TestCase("IRQ init", [r"Init irq", r"Done"]),
|
||||
TestCase("ISR done", [r"Done isr"]),
|
||||
|
||||
TestCase("IRQ init", [r"Init irq"]),
|
||||
TestCase("IRQ tests", [r"IRQ: Tested registered handlers", r"IRQ: Tested opened IDT entries"]),
|
||||
TestCase("Paging init", [r"Init paging", r"Done"]),
|
||||
TestCase("IRQ done", [r"Done irq"]),
|
||||
|
||||
TestCase("Paging init", [r"Init paging"]),
|
||||
TestCase("Paging tests", [r"Paging: Tested accessing unmapped memory", r"Paging: Tested accessing mapped memory"]),
|
||||
TestCase("Paging done", [r"Done paging"]),
|
||||
|
||||
TestCase("PIT init", [r"Init pit"]),
|
||||
TestCase("PIT init", [r".+"], r"\[DEBUG\] "),
|
||||
TestCase("PIT init", [r"Done"]),
|
||||
TestCase("PIT tests", [r"PIT: Tested init", r"PIT: Tested wait ticks", r"PIT: Tested wait ticks 2"]),
|
||||
TestCase("RTC init", [r"Init rtc", r"Done"]),
|
||||
TestCase("PIT done", [r"Done pit"]),
|
||||
|
||||
TestCase("RTC init", [r"Init rtc"]),
|
||||
TestCase("RTC tests", [r"RTC: Tested init", r"RTC: Tested interrupts"]),
|
||||
TestCase("Syscalls init", [r"Init syscalls", r"Done"]),
|
||||
TestCase("Syscall tests", [r"Syscalls: Tested no args", r"Syscalls: Tested 1 arg", r"Syscalls: Tested 2 args", r"Syscalls: Tested 3 args", r"Syscalls: Tested 4 args", r"Syscalls: Tested 5 args"])
|
||||
TestCase("RTC done", [r"Done rtc"]),
|
||||
|
||||
TestCase("Syscalls init", [r"Init syscalls"]),
|
||||
TestCase("Syscalls tests", [r"Syscalls: Tested no args", r"Syscalls: Tested 1 arg", r"Syscalls: Tested 2 args", r"Syscalls: Tested 3 args", r"Syscalls: Tested 4 args", r"Syscalls: Tested 5 args"]),
|
||||
TestCase("Syscalls done", [r"Done syscalls"]),
|
||||
]
|
||||
|
|
|
@ -31,26 +31,40 @@ def test_pass(case, exp, expected_idx, found):
|
|||
def get_pre_archinit_cases():
|
||||
return [
|
||||
TestCase("Serial tests", [r"c", r"123"], ""),
|
||||
TestCase("Log info tests", [r"Test INFO level", r"Test INFO level with args a, 1", r"Test INFO function", r"Test INFO function with args a, 1"], "\[INFO\] "),
|
||||
TestCase("Log debug tests", [r"Test DEBUG level", r"Test DEBUG level with args a, 1", r"Test DEBUG function", r"Test DEBUG function with args a, 1"], "\[DEBUG\] "),
|
||||
TestCase("Log warning tests", [r"Test WARNING level", r"Test WARNING level with args a, 1", r"Test WARNING function", r"Test WARNING function with args a, 1"], "\[WARNING\] "),
|
||||
TestCase("Log error tests", [r"Test ERROR level", r"Test ERROR level with args a, 1", r"Test ERROR function", r"Test ERROR function with args a, 1"], "\[ERROR\] "),
|
||||
TestCase("Mem init", [r"Init mem", r"Done"]),
|
||||
TestCase("PMM init", [r"Init pmm", r"Done"]),
|
||||
|
||||
TestCase("Log info tests", [r"Test INFO level", r"Test INFO level with args a, 1", r"Test INFO function", r"Test INFO function with args a, 1"], r"\[INFO\] "),
|
||||
TestCase("Log debug tests", [r"Test DEBUG level", r"Test DEBUG level with args a, 1", r"Test DEBUG function", r"Test DEBUG function with args a, 1"], r"\[DEBUG\] "),
|
||||
TestCase("Log warning tests", [r"Test WARNING level", r"Test WARNING level with args a, 1", r"Test WARNING function", r"Test WARNING function with args a, 1"], r"\[WARNING\] "),
|
||||
TestCase("Log error tests", [r"Test ERROR level", r"Test ERROR level with args a, 1", r"Test ERROR function", r"Test ERROR function with args a, 1"], r"\[ERROR\] "),
|
||||
|
||||
TestCase("Mem init", [r"Init mem"]),
|
||||
TestCase("Mem done", [r"Done mem"]),
|
||||
|
||||
TestCase("PMM init", [r"Init pmm"]),
|
||||
TestCase("PMM tests", [r"PMM: Tested allocation"]),
|
||||
TestCase("PMM done", [r"Done pmm"]),
|
||||
|
||||
TestCase("Arch init starts", [r"Init arch \w+"])
|
||||
]
|
||||
|
||||
def get_post_archinit_cases():
|
||||
return [
|
||||
TestCase("Arch init finishes", [r"Arch init done"]),
|
||||
TestCase("Panic init", [r"Init panic", r"Done"]),
|
||||
TestCase("VGA init", [r"Init vga", r"Done"]),
|
||||
|
||||
TestCase("Panic init", [r"Init panic"]),
|
||||
TestCase("Panic done", [r"Done panic"]),
|
||||
|
||||
TestCase("VGA init", [r"Init vga"]),
|
||||
TestCase("VGA tests", [r"VGA: Tested max scan line", r"VGA: Tested cursor shape", r"VGA: Tested updating cursor"]),
|
||||
TestCase("TTY init", [r"Init tty", r"Done"]),
|
||||
TestCase("VGA done", [r"Done vga"]),
|
||||
|
||||
TestCase("TTY init", [r"Init tty"]),
|
||||
TestCase("TTY tests", [r"TTY: Tested globals", r"TTY: Tested printing"]),
|
||||
TestCase("TTY done", [r"Done tty"]),
|
||||
|
||||
TestCase("Init finishes", [r"Init done"]),
|
||||
TestCase("Panic tests", [r"Kernel panic: integer overflow", r"c[a-z\d]+: panic", r"c[a-z\d]+: panic.runtimeTests", r"c[a-z\d]+: kmain", r"c[a-z\d]+: start_higher_half"], "\[ERROR\] ")
|
||||
|
||||
TestCase("Panic tests", [r"Kernel panic: integer overflow", r"c[a-z\d]+: panic", r"c[a-z\d]+: panic.runtimeTests", r"c[a-z\d]+: kmain", r"c[a-z\d]+: start_higher_half"], r"\[ERROR\] ")
|
||||
]
|
||||
|
||||
def read_messages(proc):
|
||||
|
|
Loading…
Reference in a new issue