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 syscalls = @import("syscalls.zig"); | ||||
| const mem = @import("../../mem.zig"); | ||||
| const multiboot = @import("../../multiboot.zig"); | ||||
| const MemProfile = mem.MemProfile; | ||||
| 
 | ||||
| /// 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 | ||||
| ///                                         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(); | ||||
| 
 | ||||
|     gdt.init(); | ||||
|  | @ -227,9 +228,9 @@ pub fn init(mem_profile: *const MemProfile, allocator: *Allocator, comptime opti | |||
| 
 | ||||
|     pit.init(); | ||||
| 
 | ||||
|     paging.init(mem_profile, allocator); | ||||
|     paging.init(mb_info, mem_profile, allocator); | ||||
| 
 | ||||
|     syscalls.init(options); | ||||
|     syscalls.init(); | ||||
| 
 | ||||
|     enableInterrupts(); | ||||
| } | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ const MemProfile = @import("../../mem.zig").MemProfile; | |||
| const tty = @import("../../tty.zig"); | ||||
| const log = @import("../../log.zig"); | ||||
| const mem = @import("../../mem.zig"); | ||||
| const multiboot = @import("../../multiboot.zig"); | ||||
| const options = @import("build_options"); | ||||
| 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 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"); | ||||
|     // Calculate start and end of mapping | ||||
|     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)); | ||||
|     asm volatile ("mov %[addr], %%cr3" | ||||
|         : | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ const testing = @import("std").testing; | |||
| const assert = @import("std").debug.assert; | ||||
| const isr = @import("isr.zig"); | ||||
| const log = @import("../../log.zig"); | ||||
| const options = @import("build_options"); | ||||
| 
 | ||||
| /// The isr number associated with syscalls | ||||
| 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. | ||||
| /// | ||||
| pub fn init(comptime options: type) void { | ||||
| pub fn init() void { | ||||
|     log.logInfo("Init syscalls\n"); | ||||
|     isr.registerIsr(INTERRUPT, handle) catch unreachable; | ||||
|     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 { | ||||
|     if (mb_magic == multiboot.MULTIBOOT_BOOTLOADER_MAGIC) { | ||||
|         // 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| { | ||||
|             panic_root(@errorReturnTrace(), "Failed to initialise serial: {}", e); | ||||
|         }; | ||||
|         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); | ||||
| 
 | ||||
|         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"); | ||||
|         vga.init(); | ||||
|         tty.init(); | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| const multiboot = @import("multiboot.zig"); | ||||
| const std = @import("std"); | ||||
| const expectEqual = std.testing.expectEqual; | ||||
| const log = @import("log.zig"); | ||||
| 
 | ||||
| pub const MemProfile = struct { | ||||
|     vaddr_end: [*]u8, | ||||
|  | @ -9,6 +10,7 @@ pub const MemProfile = struct { | |||
|     physaddr_start: [*]u8, | ||||
|     mem_kb: u32, | ||||
|     fixed_alloc_size: u32, | ||||
|     boot_modules: []multiboot.multiboot_module_t, | ||||
| }; | ||||
| 
 | ||||
| /// 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. | ||||
| /// | ||||
| 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); | ||||
|     return MemProfile{ | ||||
|     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), | ||||
|  | @ -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 | ||||
|         .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], | ||||
|     }; | ||||
|     log.logInfo("Done\n"); | ||||
|     return mem_profile; | ||||
| } | ||||
| 
 | ||||
| /// | ||||
|  | @ -65,7 +72,7 @@ pub fn init(mb_info: *multiboot.multiboot_info_t) MemProfile { | |||
| /// Return: @typeOf(virt) | ||||
| ///     The physical address. | ||||
| /// | ||||
| pub fn virtToPhys(virt: var) @typeOf(virt) { | ||||
| pub inline fn virtToPhys(virt: var) @typeOf(virt) { | ||||
|     const T = @typeOf(virt); | ||||
|     return switch (@typeId(T)) { | ||||
|         .Pointer => @intToPtr(T, @ptrToInt(virt) - ADDR_OFFSET), | ||||
|  | @ -83,7 +90,7 @@ pub fn virtToPhys(virt: var) @typeOf(virt) { | |||
| /// Return: @typeOf(virt) | ||||
| ///     The virtual address. | ||||
| /// | ||||
| pub fn physToVirt(phys: var) @typeOf(phys) { | ||||
| pub inline fn physToVirt(phys: var) @typeOf(phys) { | ||||
|     const T = @typeOf(phys); | ||||
|     return switch (@typeId(T)) { | ||||
|         .Pointer => @intToPtr(T, @ptrToInt(phys) + ADDR_OFFSET), | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ const mem = @import("mem_mock.zig"); | |||
| const MemProfile = mem.MemProfile; | ||||
| const gdt = @import("gdt_mock.zig"); | ||||
| const idt = @import("idt_mock.zig"); | ||||
| const multiboot = @import("../../../src/kernel/multiboot.zig"); | ||||
| 
 | ||||
| const mock_framework = @import("mock_framework.zig"); | ||||
| pub const initTest = mock_framework.initTest; | ||||
|  | @ -86,7 +87,7 @@ pub fn haltNoInterrupts() noreturn { | |||
|     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. | ||||
|     // When I come on to the mem.zig testing, I'll fix :) | ||||
|     //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 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("Arch init starts", [r"Init arch \w+"]) | ||||
|         ] | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Sam Tebbs
						Sam Tebbs