Merge pull request #106 from SamTebbs33/feature/load-bootmodules
Load grub modules on mem init
This commit is contained in:
commit
2587b9f16c
7 changed files with 49 additions and 14 deletions
|
@ -10,6 +10,7 @@ const pit = @import("pit.zig");
|
||||||
const paging = @import("paging.zig");
|
const paging = @import("paging.zig");
|
||||||
const syscalls = @import("syscalls.zig");
|
const syscalls = @import("syscalls.zig");
|
||||||
const mem = @import("../../mem.zig");
|
const mem = @import("../../mem.zig");
|
||||||
|
const multiboot = @import("../../multiboot.zig");
|
||||||
const MemProfile = mem.MemProfile;
|
const MemProfile = mem.MemProfile;
|
||||||
|
|
||||||
/// The interrupt context that is given to a interrupt handler. It contains most of the registers
|
/// The interrupt context that is given to a interrupt handler. It contains most of the registers
|
||||||
|
@ -215,7 +216,7 @@ pub fn haltNoInterrupts() noreturn {
|
||||||
/// IN comptime options: type - The build options that is passed to the kernel to be
|
/// IN comptime options: type - The build options that is passed to the kernel to be
|
||||||
/// used for run time testing.
|
/// used for run time testing.
|
||||||
///
|
///
|
||||||
pub fn init(mem_profile: *const MemProfile, allocator: *Allocator, comptime options: type) void {
|
pub fn init(mb_info: *multiboot.multiboot_info_t, mem_profile: *const MemProfile, allocator: *Allocator) void {
|
||||||
disableInterrupts();
|
disableInterrupts();
|
||||||
|
|
||||||
gdt.init();
|
gdt.init();
|
||||||
|
@ -227,9 +228,9 @@ pub fn init(mem_profile: *const MemProfile, allocator: *Allocator, comptime opti
|
||||||
|
|
||||||
pit.init();
|
pit.init();
|
||||||
|
|
||||||
paging.init(mem_profile, allocator);
|
paging.init(mb_info, mem_profile, allocator);
|
||||||
|
|
||||||
syscalls.init(options);
|
syscalls.init();
|
||||||
|
|
||||||
enableInterrupts();
|
enableInterrupts();
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ const MemProfile = @import("../../mem.zig").MemProfile;
|
||||||
const tty = @import("../../tty.zig");
|
const tty = @import("../../tty.zig");
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
const mem = @import("../../mem.zig");
|
const mem = @import("../../mem.zig");
|
||||||
|
const multiboot = @import("../../multiboot.zig");
|
||||||
const options = @import("build_options");
|
const options = @import("build_options");
|
||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
|
|
||||||
|
@ -290,7 +291,7 @@ fn pageFault(state: *arch.InterruptContext) void {
|
||||||
/// IN mem_profile: *const MemProfile - The memory profile of the system and kernel
|
/// IN mem_profile: *const MemProfile - The memory profile of the system and kernel
|
||||||
/// IN allocator: *std.mem.Allocator - The allocator to use
|
/// IN allocator: *std.mem.Allocator - The allocator to use
|
||||||
///
|
///
|
||||||
pub fn init(mem_profile: *const MemProfile, allocator: *std.mem.Allocator) void {
|
pub fn init(mb_info: *multiboot.multiboot_info_t, mem_profile: *const MemProfile, allocator: *std.mem.Allocator) void {
|
||||||
log.logInfo("Init paging\n");
|
log.logInfo("Init paging\n");
|
||||||
// Calculate start and end of mapping
|
// Calculate start and end of mapping
|
||||||
const v_start = std.mem.alignBackward(@ptrToInt(mem_profile.vaddr_start), PAGE_SIZE_4KB);
|
const v_start = std.mem.alignBackward(@ptrToInt(mem_profile.vaddr_start), PAGE_SIZE_4KB);
|
||||||
|
@ -318,6 +319,30 @@ pub fn init(mem_profile: *const MemProfile, allocator: *std.mem.Allocator) void
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the kernel mapping didn't cover the multiboot info, map it so it can be accessed by code later on
|
||||||
|
// There's no way to know the size, so an estimated size of 2MB is used. This will need increasing as the kernel gets bigger.
|
||||||
|
const mb_info_addr = std.mem.alignBackward(@ptrToInt(mb_info), PAGE_SIZE_4KB);
|
||||||
|
if (v_start > mb_info_addr) {
|
||||||
|
const mb_info_end = mb_info_addr + PAGE_SIZE_4MB / 2;
|
||||||
|
mapDir(kernel_directory, mb_info_addr, mb_info_end, mem.virtToPhys(mb_info_addr), mem.virtToPhys(mb_info_end), allocator) catch |e| {
|
||||||
|
panic(@errorReturnTrace(), "Failed to map mb_info in kernel directory: {}\n", e);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map in each boot module
|
||||||
|
for (mem_profile.boot_modules) |*module| {
|
||||||
|
const mod_p_struct_start = std.mem.alignBackward(@ptrToInt(module), PAGE_SIZE_4KB);
|
||||||
|
const mod_p_struct_end = std.mem.alignForward(mod_p_struct_start + @sizeOf(multiboot.multiboot_module_t), PAGE_SIZE_4KB);
|
||||||
|
mapDir(kernel_directory, mem.physToVirt(mod_p_struct_start), mem.physToVirt(mod_p_struct_end), mod_p_struct_start, mod_p_struct_end, allocator) catch |e| {
|
||||||
|
panic(@errorReturnTrace(), "Failed to map module struct: {}\n", e);
|
||||||
|
};
|
||||||
|
const mod_p_start = std.mem.alignBackward(module.mod_start, PAGE_SIZE_4KB);
|
||||||
|
const mod_p_end = std.mem.alignForward(module.mod_end, PAGE_SIZE_4KB);
|
||||||
|
mapDir(kernel_directory, mem.physToVirt(mod_p_start), mem.physToVirt(mod_p_end), mod_p_start, mod_p_end, allocator) catch |e| {
|
||||||
|
panic(@errorReturnTrace(), "Failed to map boot module in kernel directory: {}\n", e);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const dir_physaddr = @ptrToInt(mem.virtToPhys(kernel_directory));
|
const dir_physaddr = @ptrToInt(mem.virtToPhys(kernel_directory));
|
||||||
asm volatile ("mov %[addr], %%cr3"
|
asm volatile ("mov %[addr], %%cr3"
|
||||||
:
|
:
|
||||||
|
|
|
@ -3,6 +3,7 @@ const testing = @import("std").testing;
|
||||||
const assert = @import("std").debug.assert;
|
const assert = @import("std").debug.assert;
|
||||||
const isr = @import("isr.zig");
|
const isr = @import("isr.zig");
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
|
const options = @import("build_options");
|
||||||
|
|
||||||
/// The isr number associated with syscalls
|
/// The isr number associated with syscalls
|
||||||
pub const INTERRUPT: u16 = 0x80;
|
pub const INTERRUPT: u16 = 0x80;
|
||||||
|
@ -235,7 +236,7 @@ inline fn syscallArg(ctx: *arch.InterruptContext, comptime arg_idx: u32) u32 {
|
||||||
///
|
///
|
||||||
/// Initialise syscalls. Registers the isr associated with INTERRUPT.
|
/// Initialise syscalls. Registers the isr associated with INTERRUPT.
|
||||||
///
|
///
|
||||||
pub fn init(comptime options: type) void {
|
pub fn init() void {
|
||||||
log.logInfo("Init syscalls\n");
|
log.logInfo("Init syscalls\n");
|
||||||
isr.registerIsr(INTERRUPT, handle) catch unreachable;
|
isr.registerIsr(INTERRUPT, handle) catch unreachable;
|
||||||
log.logInfo("Done\n");
|
log.logInfo("Done\n");
|
||||||
|
|
|
@ -32,18 +32,17 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn
|
||||||
export fn kmain(mb_info: *multiboot.multiboot_info_t, mb_magic: u32) void {
|
export fn kmain(mb_info: *multiboot.multiboot_info_t, mb_magic: u32) void {
|
||||||
if (mb_magic == multiboot.MULTIBOOT_BOOTLOADER_MAGIC) {
|
if (mb_magic == multiboot.MULTIBOOT_BOOTLOADER_MAGIC) {
|
||||||
// Booted with compatible bootloader
|
// Booted with compatible bootloader
|
||||||
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);
|
|
||||||
|
|
||||||
serial.init(serial.DEFAULT_BAUDRATE, serial.Port.COM1) catch |e| {
|
serial.init(serial.DEFAULT_BAUDRATE, serial.Port.COM1) catch |e| {
|
||||||
panic_root(@errorReturnTrace(), "Failed to initialise serial: {}", e);
|
panic_root(@errorReturnTrace(), "Failed to initialise serial: {}", e);
|
||||||
};
|
};
|
||||||
if (build_options.rt_test)
|
if (build_options.rt_test)
|
||||||
log.runtimeTests();
|
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);
|
||||||
|
|
||||||
log.logInfo("Init arch " ++ @tagName(builtin.arch) ++ "\n");
|
log.logInfo("Init arch " ++ @tagName(builtin.arch) ++ "\n");
|
||||||
arch.init(&mem_profile, &fixed_allocator.allocator, build_options);
|
arch.init(mb_info, &mem_profile, &fixed_allocator.allocator);
|
||||||
log.logInfo("Arch init done\n");
|
log.logInfo("Arch init done\n");
|
||||||
vga.init();
|
vga.init();
|
||||||
tty.init();
|
tty.init();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
const multiboot = @import("multiboot.zig");
|
const multiboot = @import("multiboot.zig");
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const expectEqual = std.testing.expectEqual;
|
const expectEqual = std.testing.expectEqual;
|
||||||
|
const log = @import("log.zig");
|
||||||
|
|
||||||
pub const MemProfile = struct {
|
pub const MemProfile = struct {
|
||||||
vaddr_end: [*]u8,
|
vaddr_end: [*]u8,
|
||||||
|
@ -9,6 +10,7 @@ pub const MemProfile = struct {
|
||||||
physaddr_start: [*]u8,
|
physaddr_start: [*]u8,
|
||||||
mem_kb: u32,
|
mem_kb: u32,
|
||||||
fixed_alloc_size: u32,
|
fixed_alloc_size: u32,
|
||||||
|
boot_modules: []multiboot.multiboot_module_t,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The virtual end of the kernel code
|
/// The virtual end of the kernel code
|
||||||
|
@ -44,8 +46,10 @@ var ADDR_OFFSET: usize = undefined;
|
||||||
/// The memory profile constructed from the exported linker symbols and the relevant multiboot info.
|
/// The memory profile constructed from the exported linker symbols and the relevant multiboot info.
|
||||||
///
|
///
|
||||||
pub fn init(mb_info: *multiboot.multiboot_info_t) MemProfile {
|
pub fn init(mb_info: *multiboot.multiboot_info_t) MemProfile {
|
||||||
|
log.logInfo("Init mem\n");
|
||||||
|
const mods_count = mb_info.mods_count;
|
||||||
ADDR_OFFSET = @ptrToInt(&KERNEL_ADDR_OFFSET);
|
ADDR_OFFSET = @ptrToInt(&KERNEL_ADDR_OFFSET);
|
||||||
return MemProfile{
|
const mem_profile = MemProfile{
|
||||||
.vaddr_end = @ptrCast([*]u8, &KERNEL_VADDR_END),
|
.vaddr_end = @ptrCast([*]u8, &KERNEL_VADDR_END),
|
||||||
.vaddr_start = @ptrCast([*]u8, &KERNEL_VADDR_START),
|
.vaddr_start = @ptrCast([*]u8, &KERNEL_VADDR_START),
|
||||||
.physaddr_end = @ptrCast([*]u8, &KERNEL_PHYSADDR_END),
|
.physaddr_end = @ptrCast([*]u8, &KERNEL_PHYSADDR_END),
|
||||||
|
@ -53,7 +57,10 @@ pub fn init(mb_info: *multiboot.multiboot_info_t) MemProfile {
|
||||||
// Total memory available including the initial 1MiB that grub doesn't include
|
// Total memory available including the initial 1MiB that grub doesn't include
|
||||||
.mem_kb = mb_info.mem_upper + mb_info.mem_lower + 1024,
|
.mem_kb = mb_info.mem_upper + mb_info.mem_lower + 1024,
|
||||||
.fixed_alloc_size = FIXED_ALLOC_SIZE,
|
.fixed_alloc_size = FIXED_ALLOC_SIZE,
|
||||||
|
.boot_modules = @intToPtr([*]multiboot.multiboot_mod_list, physToVirt(mb_info.mods_addr))[0..mods_count],
|
||||||
};
|
};
|
||||||
|
log.logInfo("Done\n");
|
||||||
|
return mem_profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -65,7 +72,7 @@ pub fn init(mb_info: *multiboot.multiboot_info_t) MemProfile {
|
||||||
/// Return: @typeOf(virt)
|
/// Return: @typeOf(virt)
|
||||||
/// The physical address.
|
/// The physical address.
|
||||||
///
|
///
|
||||||
pub fn virtToPhys(virt: var) @typeOf(virt) {
|
pub inline fn virtToPhys(virt: var) @typeOf(virt) {
|
||||||
const T = @typeOf(virt);
|
const T = @typeOf(virt);
|
||||||
return switch (@typeId(T)) {
|
return switch (@typeId(T)) {
|
||||||
.Pointer => @intToPtr(T, @ptrToInt(virt) - ADDR_OFFSET),
|
.Pointer => @intToPtr(T, @ptrToInt(virt) - ADDR_OFFSET),
|
||||||
|
@ -83,7 +90,7 @@ pub fn virtToPhys(virt: var) @typeOf(virt) {
|
||||||
/// Return: @typeOf(virt)
|
/// Return: @typeOf(virt)
|
||||||
/// The virtual address.
|
/// The virtual address.
|
||||||
///
|
///
|
||||||
pub fn physToVirt(phys: var) @typeOf(phys) {
|
pub inline fn physToVirt(phys: var) @typeOf(phys) {
|
||||||
const T = @typeOf(phys);
|
const T = @typeOf(phys);
|
||||||
return switch (@typeId(T)) {
|
return switch (@typeId(T)) {
|
||||||
.Pointer => @intToPtr(T, @ptrToInt(phys) + ADDR_OFFSET),
|
.Pointer => @intToPtr(T, @ptrToInt(phys) + ADDR_OFFSET),
|
||||||
|
|
|
@ -4,6 +4,7 @@ const mem = @import("mem_mock.zig");
|
||||||
const MemProfile = mem.MemProfile;
|
const MemProfile = mem.MemProfile;
|
||||||
const gdt = @import("gdt_mock.zig");
|
const gdt = @import("gdt_mock.zig");
|
||||||
const idt = @import("idt_mock.zig");
|
const idt = @import("idt_mock.zig");
|
||||||
|
const multiboot = @import("../../../src/kernel/multiboot.zig");
|
||||||
|
|
||||||
const mock_framework = @import("mock_framework.zig");
|
const mock_framework = @import("mock_framework.zig");
|
||||||
pub const initTest = mock_framework.initTest;
|
pub const initTest = mock_framework.initTest;
|
||||||
|
@ -86,7 +87,7 @@ pub fn haltNoInterrupts() noreturn {
|
||||||
while (true) {}
|
while (true) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(mem_profile: *const MemProfile, allocator: *Allocator, comptime options: type) void {
|
pub fn init(mb_info: *multiboot.multiboot_info_t, mem_profile: *const MemProfile, allocator: *Allocator) void {
|
||||||
// I'll get back to this as this doesn't effect the GDT testing.
|
// I'll get back to this as this doesn't effect the GDT testing.
|
||||||
// When I come on to the mem.zig testing, I'll fix :)
|
// When I come on to the mem.zig testing, I'll fix :)
|
||||||
//return mock_framework.performAction("init", void, mem_profile, allocator);
|
//return mock_framework.performAction("init", void, mem_profile, allocator);
|
||||||
|
|
|
@ -35,6 +35,7 @@ def get_pre_archinit_cases():
|
||||||
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 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 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("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("Arch init starts", [r"Init arch \w+"])
|
TestCase("Arch init starts", [r"Init arch \w+"])
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue