diff options
Diffstat (limited to 'mirai/memory/paging.zig')
| -rw-r--r-- | mirai/memory/paging.zig | 114 |
1 files changed, 48 insertions, 66 deletions
diff --git a/mirai/memory/paging.zig b/mirai/memory/paging.zig index 7dade55..e50fc56 100644 --- a/mirai/memory/paging.zig +++ b/mirai/memory/paging.zig @@ -1,35 +1,32 @@ -//! Page Table Manager - Hybrid kernel with independent user page tables +//! Page Table Manager -const memory = @import("../asm/memory.zig"); +const asm_memory = @import("../asm/memory.zig"); +const memory_const = @import("../common/constants/memory.zig"); +const paging_const = @import("../common/constants/paging.zig"); const pmm = @import("pmm.zig"); -const system = @import("../system/system.zig"); +const pmm_const = @import("../common/constants/pmm.zig"); -pub const PAGE_SIZE = system.constants.PAGE_SIZE; -pub const HIGHER_HALF_START = system.constants.HIGHER_HALF_START; +pub const PAGE_SIZE = memory_const.PAGE_SIZE; +pub const HIGHER_HALF_START = memory_const.HIGHER_HALF_START; -pub const PAGE_PRESENT = system.constants.PTE_PRESENT; -pub const PAGE_WRITABLE = system.constants.PTE_WRITABLE; -pub const PAGE_USER = system.constants.PTE_USER; - -const KERNEL_START = system.constants.KERNEL_PHYSICAL_START; -const KERNEL_END = system.constants.KERNEL_PHYSICAL_END; +pub const PAGE_PRESENT = paging_const.PTE_PRESENT; +pub const PAGE_WRITABLE = paging_const.PTE_WRITABLE; +pub const PAGE_USER = paging_const.PTE_USER; fn zero_page(virt: u64) void { const ptr: [*]volatile u8 = @ptrFromInt(virt); - var i: usize = 0; - while (i < PAGE_SIZE) : (i += 1) { + for (0..PAGE_SIZE) |i| { ptr[i] = 0; } } -// Map a page in the current page table (used by kernel for its own mappings) pub fn map_page(virt: u64, phys: u64, flags: u64) !void { const pml4_index = (virt >> 39) & 0x1FF; const pdpt_index = (virt >> 30) & 0x1FF; const pd_index = (virt >> 21) & 0x1FF; const pt_index = (virt >> 12) & 0x1FF; - const pml4_phys = memory.read_page_table_base() & ~@as(u64, 0xFFF); + const pml4_phys = asm_memory.read_page_table_base() & ~@as(u64, paging_const.OFFSET_MASK); const pml4: [*]volatile u64 = @ptrFromInt(pml4_phys + HIGHER_HALF_START); var pdpt_phys: u64 = undefined; @@ -39,12 +36,11 @@ pub fn map_page(virt: u64, phys: u64, flags: u64) !void { pml4[pml4_index] = pdpt_phys | PAGE_PRESENT | PAGE_WRITABLE | flags; pdpt_was_new = true; } else { - pdpt_phys = pml4[pml4_index] & ~@as(u64, 0xFFF); + pdpt_phys = pml4[pml4_index] & paging_const.PTE_MASK; } const pdpt: [*]volatile u64 = @ptrFromInt(pdpt_phys + HIGHER_HALF_START); - // If we just created this PDPT, zero only the entry we're about to use if (pdpt_was_new) { pdpt[pdpt_index] = 0; } @@ -56,12 +52,11 @@ pub fn map_page(virt: u64, phys: u64, flags: u64) !void { pdpt[pdpt_index] = pd_phys | PAGE_PRESENT | PAGE_WRITABLE | flags; pd_was_new = true; } else { - pd_phys = pdpt[pdpt_index] & ~@as(u64, 0xFFF); + pd_phys = pdpt[pdpt_index] & paging_const.PTE_MASK; } const pd: [*]volatile u64 = @ptrFromInt(pd_phys + HIGHER_HALF_START); - // If we just created this PD, zero only the entry we're about to use if (pd_was_new) { pd[pd_index] = 0; } @@ -73,58 +68,48 @@ pub fn map_page(virt: u64, phys: u64, flags: u64) !void { pd[pd_index] = pt_phys | PAGE_PRESENT | PAGE_WRITABLE | flags; pt_was_new = true; } else { - pt_phys = pd[pd_index] & ~@as(u64, 0xFFF); + pt_phys = pd[pd_index] & paging_const.PTE_MASK; } const pt: [*]volatile u64 = @ptrFromInt(pt_phys + HIGHER_HALF_START); - // If we just created this PT, zero only the entry we're about to use if (pt_was_new) { pt[pt_index] = 0; } pt[pt_index] = phys | PAGE_PRESENT | flags; - // Flush TLB for the new mapping - memory.invalidate_page(virt); + asm_memory.invalidate_page(virt); } -// Create completely independent page table structure for user pub fn create_page_table() !u64 { const new_pml4_phys = pmm.alloc_page() orelse return error.OutOfMemory; const new_pml4: [*]volatile u64 = @ptrFromInt(new_pml4_phys + HIGHER_HALF_START); - var i: usize = 0; - while (i < 512) : (i += 1) { + for (0..paging_const.PML4_ENTRIES) |i| { new_pml4[i] = 0; } - const kernel_pml4_phys = memory.read_page_table_base() & ~@as(u64, 0xFFF); + const kernel_pml4_phys = asm_memory.read_page_table_base() & ~@as(u64, paging_const.OFFSET_MASK); const kernel_pml4: [*]volatile u64 = @ptrFromInt(kernel_pml4_phys + HIGHER_HALF_START); - // Copy higher-half mappings (PML4[256-511]) for kernel heap/data access - i = 256; - while (i < 512) : (i += 1) { + for (paging_const.KERNEL_PML4_START..paging_const.PML4_ENTRIES) |i| { new_pml4[i] = kernel_pml4[i]; } - // Map kernel (0x100000-0x1000000 = 16MB) as supervisor-only - var addr: u64 = 0x100000; - while (addr < 0x1000000) : (addr += PAGE_SIZE) { + var addr: u64 = pmm_const.KERNEL_BASE; + while (addr < pmm_const.KERNEL_MAP_END) : (addr += PAGE_SIZE) { _ = try map_page_in_table(new_pml4_phys, addr, addr, PAGE_PRESENT | PAGE_WRITABLE); } - // Map MMIO region (0x80000000-0x82000000 = 32MB) for framebuffer and AHCI - // Supervisor-only - addr = 0x80000000; - while (addr < 0x82000000) : (addr += PAGE_SIZE) { + addr = pmm_const.MMIO_FRAMEBUFFER_BASE; + while (addr < pmm_const.MMIO_FRAMEBUFFER_BASE + 0x2000000) : (addr += PAGE_SIZE) { _ = try map_page_in_table(new_pml4_phys, addr, addr, PAGE_PRESENT | PAGE_WRITABLE); } return new_pml4_phys; } -// Map a page in a specific page table pub fn map_page_in_table(page_table_phys: u64, virt: u64, phys: u64, flags: u64) !struct { bool, u64 } { const pml4_index = (virt >> 39) & 0x1FF; const pdpt_index = (virt >> 30) & 0x1FF; @@ -139,7 +124,7 @@ pub fn map_page_in_table(page_table_phys: u64, virt: u64, phys: u64, flags: u64) zero_page(pdpt_phys + HIGHER_HALF_START); pml4[pml4_index] = pdpt_phys | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER; } else { - pdpt_phys = pml4[pml4_index] & ~@as(u64, 0xFFF); + pdpt_phys = pml4[pml4_index] & paging_const.PTE_MASK; } const pdpt: [*]volatile u64 = @ptrFromInt(pdpt_phys + HIGHER_HALF_START); @@ -150,7 +135,7 @@ pub fn map_page_in_table(page_table_phys: u64, virt: u64, phys: u64, flags: u64) zero_page(pd_phys + HIGHER_HALF_START); pdpt[pdpt_index] = pd_phys | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER; } else { - pd_phys = pdpt[pdpt_index] & ~@as(u64, 0xFFF); + pd_phys = pdpt[pdpt_index] & paging_const.PTE_MASK; } const pd: [*]volatile u64 = @ptrFromInt(pd_phys + HIGHER_HALF_START); @@ -161,7 +146,7 @@ pub fn map_page_in_table(page_table_phys: u64, virt: u64, phys: u64, flags: u64) zero_page(pt_phys + HIGHER_HALF_START); pd[pd_index] = pt_phys | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER; } else { - pt_phys = pd[pd_index] & ~@as(u64, 0xFFF); + pt_phys = pd[pd_index] & paging_const.PTE_MASK; } const pt: [*]volatile u64 = @ptrFromInt(pt_phys + HIGHER_HALF_START); @@ -171,8 +156,7 @@ pub fn map_page_in_table(page_table_phys: u64, virt: u64, phys: u64, flags: u64) pt[pt_index] = phys | flags | PAGE_PRESENT; return .{ false, phys }; } else { - const existing_phys = pt[pt_index] & ~@as(u64, 0xFFF); - // Update entry if flags changed (e.g., upgrading to writable) + const existing_phys = pt[pt_index] & paging_const.PTE_MASK; pt[pt_index] = existing_phys | flags | PAGE_PRESENT; return .{ true, existing_phys }; } @@ -183,24 +167,23 @@ pub fn get_physical_address(page_table: u64, vaddr: u64) !u64 { const pdp_index = (vaddr >> 30) & 0x1FF; const pd_index = (vaddr >> 21) & 0x1FF; const pt_index = (vaddr >> 12) & 0x1FF; - const offset = vaddr & 0xFFF; + const offset = vaddr & paging_const.OFFSET_MASK; const pml4 = @as([*]u64, @ptrFromInt(page_table + HIGHER_HALF_START)); - if ((pml4[pml4_index] & 1) == 0) return error.NotMapped; + if ((pml4[pml4_index] & PAGE_PRESENT) == 0) return error.NotMapped; - const pdp = @as([*]u64, @ptrFromInt((pml4[pml4_index] & ~@as(u64, 0xFFF)) + HIGHER_HALF_START)); - if ((pdp[pdp_index] & 1) == 0) return error.NotMapped; + const pdp = @as([*]u64, @ptrFromInt((pml4[pml4_index] & paging_const.PTE_MASK) + HIGHER_HALF_START)); + if ((pdp[pdp_index] & PAGE_PRESENT) == 0) return error.NotMapped; - const pd = @as([*]u64, @ptrFromInt((pdp[pdp_index] & ~@as(u64, 0xFFF)) + HIGHER_HALF_START)); - if ((pd[pd_index] & 1) == 0) return error.NotMapped; + const pd = @as([*]u64, @ptrFromInt((pdp[pdp_index] & paging_const.PTE_MASK) + HIGHER_HALF_START)); + if ((pd[pd_index] & PAGE_PRESENT) == 0) return error.NotMapped; - const pt = @as([*]u64, @ptrFromInt((pd[pd_index] & ~@as(u64, 0xFFF)) + HIGHER_HALF_START)); - if ((pt[pt_index] & 1) == 0) return error.NotMapped; + const pt = @as([*]u64, @ptrFromInt((pd[pd_index] & paging_const.PTE_MASK) + HIGHER_HALF_START)); + if ((pt[pt_index] & PAGE_PRESENT) == 0) return error.NotMapped; - return (pt[pt_index] & ~@as(u64, 0xFFF)) + offset; + return (pt[pt_index] & paging_const.PTE_MASK) + offset; } -// Get the page table entry for a virtual address (returns null if not mapped) pub fn get_page_entry(page_table_phys: u64, virt: u64) ?u64 { const pml4_index = (virt >> 39) & 0x1FF; const pdpt_index = (virt >> 30) & 0x1FF; @@ -210,56 +193,55 @@ pub fn get_page_entry(page_table_phys: u64, virt: u64) ?u64 { const pml4: [*]volatile u64 = @ptrFromInt(page_table_phys + HIGHER_HALF_START); if ((pml4[pml4_index] & PAGE_PRESENT) == 0) return null; - const pdpt_phys = pml4[pml4_index] & ~@as(u64, 0xFFF); + const pdpt_phys = pml4[pml4_index] & paging_const.PTE_MASK; const pdpt: [*]volatile u64 = @ptrFromInt(pdpt_phys + HIGHER_HALF_START); if ((pdpt[pdpt_index] & PAGE_PRESENT) == 0) return null; - const pd_phys = pdpt[pdpt_index] & ~@as(u64, 0xFFF); + const pd_phys = pdpt[pdpt_index] & paging_const.PTE_MASK; const pd: [*]volatile u64 = @ptrFromInt(pd_phys + HIGHER_HALF_START); if ((pd[pd_index] & PAGE_PRESENT) == 0) return null; - const pt_phys = pd[pd_index] & ~@as(u64, 0xFFF); + const pt_phys = pd[pd_index] & paging_const.PTE_MASK; const pt: [*]volatile u64 = @ptrFromInt(pt_phys + HIGHER_HALF_START); return pt[pt_index]; } pub fn virt_to_phys(cr3: u64, virt: u64) ?u64 { - // Walk the 4-level page table const pml4_addr = cr3 + HIGHER_HALF_START; const pml4 = @as([*]u64, @ptrFromInt(pml4_addr)); const pml4_index = (virt >> 39) & 0x1FF; const pml4_entry = pml4[pml4_index]; - if ((pml4_entry & 1) == 0) return null; // Not present + if ((pml4_entry & PAGE_PRESENT) == 0) return null; - const pdp_addr = (pml4_entry & 0x000FFFFFFFFFF000) + HIGHER_HALF_START; + const pdp_addr = (pml4_entry & paging_const.PTE_MASK) + HIGHER_HALF_START; const pdp = @as([*]u64, @ptrFromInt(pdp_addr)); const pdp_index = (virt >> 30) & 0x1FF; const pdp_entry = pdp[pdp_index]; - if ((pdp_entry & 1) == 0) return null; // Not present + if ((pdp_entry & PAGE_PRESENT) == 0) return null; - const pd_addr = (pdp_entry & 0x000FFFFFFFFFF000) + HIGHER_HALF_START; + const pd_addr = (pdp_entry & paging_const.PTE_MASK) + HIGHER_HALF_START; const pd = @as([*]u64, @ptrFromInt(pd_addr)); const pd_index = (virt >> 21) & 0x1FF; const pd_entry = pd[pd_index]; - if ((pd_entry & 1) == 0) return null; // Not present + if ((pd_entry & PAGE_PRESENT) == 0) return null; - const pt_addr = (pd_entry & 0x000FFFFFFFFFF000) + HIGHER_HALF_START; + const pt_addr = (pd_entry & paging_const.PTE_MASK) + HIGHER_HALF_START; const pt = @as([*]u64, @ptrFromInt(pt_addr)); const pt_index = (virt >> 12) & 0x1FF; const pt_entry = pt[pt_index]; - if ((pt_entry & 1) == 0) return null; // Not present + if ((pt_entry & PAGE_PRESENT) == 0) return null; - const phys_base = pt_entry & 0x000FFFFFFFFFF000; - const offset = virt & 0xFFF; + const phys_base = pt_entry & paging_const.PTE_MASK; + const offset = virt & paging_const.OFFSET_MASK; return phys_base + offset; } |
