From 1ea9dbe79d6f70c2416c4fd522382ce0a4c4e7e7 Mon Sep 17 00:00:00 2001 From: DrDeano Date: Sun, 26 Jul 2020 13:21:06 +0100 Subject: [PATCH] Fix mapping of addresses that span the 4MB boundary Also removed unused variables Fixed unmapping of addresses that span the 4MB boundary Fixed clearing directory Fmt Improved paging maps and unmaps --- src/kernel/arch/x86/paging.zig | 75 +++++++++++++++++++++------------- src/kernel/vmm.zig | 4 +- test/mock/kernel/log_mock.zig | 29 ++----------- 3 files changed, 52 insertions(+), 56 deletions(-) diff --git a/src/kernel/arch/x86/paging.zig b/src/kernel/arch/x86/paging.zig index 7db4531..a206fff 100644 --- a/src/kernel/arch/x86/paging.zig +++ b/src/kernel/arch/x86/paging.zig @@ -119,7 +119,7 @@ pub var kernel_directory: Directory align(@truncate(u29, PAGE_SIZE_4KB)) = Direc /// The index into an array of directory entries. /// inline fn virtToDirEntryIdx(virt: usize) usize { - return (virt / PAGE_SIZE_4MB) % ENTRIES_PER_DIRECTORY; + return virt / PAGE_SIZE_4MB; } /// @@ -195,9 +195,7 @@ fn mapDirEntry(dir: *Directory, virt_start: usize, virt_end: usize, phys_start: return vmm.MapperError.MisalignedVirtualAddress; } - const entry = virt_start / PAGE_SIZE_4MB; - if (entry >= ENTRIES_PER_DIRECTORY) - return vmm.MapperError.InvalidVirtualAddress; + const entry = virtToDirEntryIdx(virt_start); var dir_entry = &dir.entries[entry]; setAttribute(dir_entry, DENTRY_PRESENT); @@ -249,6 +247,32 @@ fn mapDirEntry(dir: *Directory, virt_start: usize, virt_end: usize, phys_start: } } +/// +/// Unmap a page directory entry, clearing the present bits. +/// +/// Arguments: +/// IN virt_addr: usize - The start of the virtual space to map +/// IN virt_end: usize - The end of the virtual space to map +/// OUT dir: *Directory - The directory that this entry is in +/// +/// Error: vmm.MapperError +/// vmm.MapperError.NotMapped - If the region being unmapped wasn't mapped in the first place +/// +fn unmapDirEntry(dir: *Directory, virt_start: usize, virt_end: usize) vmm.MapperError!void { + const entry = virtToDirEntryIdx(virt_start); + var dir_entry = &dir.entries[entry]; + const table = dir.tables[entry] orelse return vmm.MapperError.NotMapped; + var addr = virt_start; + while (addr < virt_end) : (addr += PAGE_SIZE_4KB) { + var table_entry = &table.entries[virtToTableEntryIdx(addr)]; + if (table_entry.* & TENTRY_PRESENT != 0) { + clearAttribute(table_entry, TENTRY_PRESENT); + } else { + return vmm.MapperError.NotMapped; + } + } +} + /// /// Map a table entry by setting its bits to the appropriate values. /// Sets the entry to be present, writable, kernel access, write through, cache enabled, non-global and the page address bits. @@ -308,17 +332,20 @@ fn mapTableEntry(entry: *align(1) TableEntry, phys_addr: usize, attrs: vmm.Attri /// Error: vmm.MapperError || Allocator.Error /// * - See mapDirEntry /// -pub fn map(virt_start: usize, virt_end: usize, phys_start: usize, phys_end: usize, attrs: vmm.Attributes, allocator: *Allocator, dir: *Directory) (Allocator.Error || vmm.MapperError)!void { - var virt_addr = virt_start; +pub fn map(virtual_start: usize, virtual_end: usize, phys_start: usize, phys_end: usize, attrs: vmm.Attributes, allocator: *Allocator, dir: *Directory) (Allocator.Error || vmm.MapperError)!void { + var virt_addr = virtual_start; var phys_addr = phys_start; - var page = virt_addr / PAGE_SIZE_4KB; - var entry_idx = virt_addr / PAGE_SIZE_4MB; - while (entry_idx < ENTRIES_PER_DIRECTORY and virt_addr < virt_end) : ({ - phys_addr += PAGE_SIZE_4MB; - virt_addr += PAGE_SIZE_4MB; + var virt_next = std.math.min(virtual_end, std.mem.alignBackward(virt_addr, PAGE_SIZE_4MB) + PAGE_SIZE_4MB); + var phys_next = std.math.min(phys_end, std.mem.alignBackward(phys_addr, PAGE_SIZE_4MB) + PAGE_SIZE_4MB); + var entry_idx = virtToDirEntryIdx(virt_addr); + while (entry_idx < ENTRIES_PER_DIRECTORY and virt_addr < virtual_end) : ({ + virt_addr = virt_next; + phys_addr = phys_next; + virt_next = std.math.min(virtual_end, virt_next + PAGE_SIZE_4MB); + phys_next = std.math.min(phys_end, phys_next + PAGE_SIZE_4MB); entry_idx += 1; }) { - try mapDirEntry(dir, virt_addr, std.math.min(virt_end, virt_addr + PAGE_SIZE_4MB), phys_addr, std.math.min(phys_end, phys_addr + PAGE_SIZE_4MB), attrs, allocator); + try mapDirEntry(dir, virt_addr, virt_next, phys_addr, phys_next, attrs, allocator); } } @@ -335,27 +362,17 @@ pub fn map(virt_start: usize, virt_end: usize, phys_start: usize, phys_end: usiz /// pub fn unmap(virtual_start: usize, virtual_end: usize, dir: *Directory) (Allocator.Error || vmm.MapperError)!void { var virt_addr = virtual_start; - var page = virt_addr / PAGE_SIZE_4KB; - var entry_idx = virt_addr / PAGE_SIZE_4MB; + var virt_next = std.math.min(virtual_end, std.mem.alignBackward(virt_addr, PAGE_SIZE_4MB) + PAGE_SIZE_4MB); + var entry_idx = virtToDirEntryIdx(virt_addr); while (entry_idx < ENTRIES_PER_DIRECTORY and virt_addr < virtual_end) : ({ - virt_addr += PAGE_SIZE_4MB; + virt_addr = virt_next; + virt_next = std.math.min(virtual_end, virt_next + PAGE_SIZE_4MB); entry_idx += 1; }) { - var dir_entry = &dir.entries[entry_idx]; - const table = dir.tables[entry_idx] orelse return vmm.MapperError.NotMapped; - const end = std.math.min(virtual_end, virt_addr + PAGE_SIZE_4MB); - var addr = virt_addr; - while (addr < end) : (addr += PAGE_SIZE_4KB) { - var table_entry = &table.entries[virtToTableEntryIdx(addr)]; - if (table_entry.* & TENTRY_PRESENT != 0) { - clearAttribute(table_entry, TENTRY_PRESENT); - } else { - return vmm.MapperError.NotMapped; - } + try unmapDirEntry(dir, virt_addr, virt_next); + if (virt_next - virt_addr >= PAGE_SIZE_4MB) { + clearAttribute(&dir.entries[entry_idx], DENTRY_PRESENT); } - // If the region to be mapped covers all of this directory entry, set the whole thing as not present - if (virtual_end - virt_addr >= PAGE_SIZE_4MB) - clearAttribute(dir_entry, DENTRY_PRESENT); } } diff --git a/src/kernel/vmm.zig b/src/kernel/vmm.zig index 841f306..01ce320 100644 --- a/src/kernel/vmm.zig +++ b/src/kernel/vmm.zig @@ -291,7 +291,7 @@ pub fn VirtualMemoryManager(comptime Payload: type) type { try block_list.append(addr); // The map function failing isn't the caller's responsibility so panic as it shouldn't happen self.mapper.mapFn(vaddr, vaddr + BLOCK_SIZE, addr, addr + BLOCK_SIZE, attrs, self.allocator, self.payload) catch |e| { - panic(@errorReturnTrace(), "Failed to map virtual memory: {}\n", .{e}); + panic(@errorReturnTrace(), "Failed to map virtual memory: {X}\n", .{e}); }; vaddr += BLOCK_SIZE; } @@ -377,7 +377,7 @@ pub fn init(mem_profile: *const mem.MemProfile, allocator: *Allocator) Allocator 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 }), + else => panic(@errorReturnTrace(), "Failed mapping region in VMM {X}: {}\n", .{ entry, e }), }; } diff --git a/test/mock/kernel/log_mock.zig b/test/mock/kernel/log_mock.zig index 4a4b93f..79327d6 100644 --- a/test/mock/kernel/log_mock.zig +++ b/test/mock/kernel/log_mock.zig @@ -1,3 +1,4 @@ +const std = @import("std"); const mock_framework = @import("mock_framework.zig"); pub const initTest = mock_framework.initTest; pub const freeTest = mock_framework.freeTest; @@ -5,29 +6,7 @@ pub const addTestParams = mock_framework.addTestParams; pub const addConsumeFunction = mock_framework.addConsumeFunction; pub const addRepeatFunction = mock_framework.addRepeatFunction; -pub const Level = enum { - INFO, - DEBUG, - WARNING, - ERROR, -}; - -pub fn log(comptime level: Level, comptime format: []const u8, args: anytype) void { - //return mock_framework.performAction("log", void, level, format, args); -} - -pub fn logInfo(comptime format: []const u8, args: anytype) void { - //return mock_framework.performAction("logInfo", void, format, args); -} - -pub fn logDebug(comptime format: []const u8, args: anytype) void { - //return mock_framework.performAction("logDebug", void, format, args); -} - -pub fn logWarning(comptime format: []const u8, args: anytype) void { - //return mock_framework.performAction("logWarning", void, format, args); -} - -pub fn logError(comptime format: []const u8, args: anytype) void { - //return mock_framework.performAction("logError", void, format, args); +pub fn log(comptime level: std.log.Level, comptime format: []const u8, args: anytype) void { + // Just print to std print + std.debug.print(format, args); }