diff options
| author | Bobby <[email protected]> | 2026-02-15 21:05:01 +0530 |
|---|---|---|
| committer | Bobby <[email protected]> | 2026-02-15 21:05:01 +0530 |
| commit | a3d895c62740b386d3f802faebddd3c188e9688e (patch) | |
| tree | a6fe729e0d2d52138b8fa0dbc16ab47185327829 | |
| parent | dfd1508131f6b51600ab26a169cf4b09348b0ad2 (diff) | |
| download | akiba-a3d895c62740b386d3f802faebddd3c188e9688e.tar.xz akiba-a3d895c62740b386d3f802faebddd3c188e9688e.zip | |
refactor: Modularize memory management constants and improve structure
| -rw-r--r-- | mirai/common/constants/heap.zig | 6 | ||||
| -rw-r--r-- | mirai/common/constants/paging.zig | 11 | ||||
| -rw-r--r-- | mirai/common/constants/pmm.zig | 14 | ||||
| -rw-r--r-- | mirai/memory/heap.zig | 130 | ||||
| -rw-r--r-- | mirai/memory/paging.zig | 114 | ||||
| -rw-r--r-- | mirai/memory/pmm.zig | 128 |
6 files changed, 147 insertions, 256 deletions
diff --git a/mirai/common/constants/heap.zig b/mirai/common/constants/heap.zig new file mode 100644 index 0000000..8bd3f26 --- /dev/null +++ b/mirai/common/constants/heap.zig @@ -0,0 +1,6 @@ +//! Heap allocator constants + +pub const SIZE_CLASSES = [_]usize{ 16, 32, 64, 128, 256, 512, 1024, 2048 }; +pub const NUM_CACHES: usize = SIZE_CLASSES.len; +pub const LARGE_ALLOC_THRESHOLD: usize = 2048; +pub const MAX_LARGE_PAGES: usize = 64; diff --git a/mirai/common/constants/paging.zig b/mirai/common/constants/paging.zig new file mode 100644 index 0000000..0a9e9bb --- /dev/null +++ b/mirai/common/constants/paging.zig @@ -0,0 +1,11 @@ +//! Paging constants + +pub const PTE_PRESENT: u64 = 1 << 0; +pub const PTE_WRITABLE: u64 = 1 << 1; +pub const PTE_USER: u64 = 1 << 2; + +pub const PTE_MASK: u64 = 0x000FFFFFFFFFF000; +pub const OFFSET_MASK: u64 = 0xFFF; + +pub const PML4_ENTRIES: usize = 512; +pub const KERNEL_PML4_START: usize = 256; diff --git a/mirai/common/constants/pmm.zig b/mirai/common/constants/pmm.zig new file mode 100644 index 0000000..292d0f6 --- /dev/null +++ b/mirai/common/constants/pmm.zig @@ -0,0 +1,14 @@ +//! Physical memory manager constants + +pub const MEMORY_AVAILABLE: u32 = 1; + +pub const FIRST_MB: u64 = 0x100000; +pub const KERNEL_BASE: u64 = 0x100000; +pub const KERNEL_MAP_END: u64 = 0x1000000; + +pub const MMIO_FRAMEBUFFER_BASE: u64 = 0x80000000; +pub const MMIO_FRAMEBUFFER_SIZE: u64 = 0x10000000; +pub const MMIO_PCI_BASE: u64 = 0xE0000000; +pub const MMIO_PCI_SIZE: u64 = 0x10000000; + +pub const BITMAP_MARK_USED: u8 = 0xFF; diff --git a/mirai/memory/heap.zig b/mirai/memory/heap.zig index 7c013d0..e21456e 100644 --- a/mirai/memory/heap.zig +++ b/mirai/memory/heap.zig @@ -1,15 +1,12 @@ //! Kernel Heap Allocator -//! Size-segregated allocator with object caching +const heap_const = @import("../common/constants/heap.zig"); +const memory_const = @import("../common/constants/memory.zig"); const pmm = @import("pmm.zig"); const serial = @import("../drivers/serial/serial.zig"); -const system = @import("../system/system.zig"); -const PAGE_SIZE = system.constants.PAGE_SIZE; -const HIGHER_HALF_START = system.constants.HIGHER_HALF_START; - -const SIZE_CLASSES = [_]usize{ 16, 32, 64, 128, 256, 512, 1024, 2048 }; -const NUM_CACHES = SIZE_CLASSES.len; +const PAGE_SIZE = memory_const.PAGE_SIZE; +const HIGHER_HALF = memory_const.HIGHER_HALF_START; const SlabHeader = struct { free_count: usize, @@ -30,15 +27,14 @@ const SlabCache = struct { slab_list: ?*SlabHeader, }; -var caches: [NUM_CACHES]SlabCache = undefined; +var caches: [heap_const.NUM_CACHES]SlabCache = undefined; var initialized: bool = false; pub fn init() void { - serial.print("\n=== Heap Allocator ===\n"); + serial.print("\n=== Heap ===\n"); - var i: usize = 0; - while (i < NUM_CACHES) : (i += 1) { - const size = SIZE_CLASSES[i]; + for (0..heap_const.NUM_CACHES) |i| { + const size = heap_const.SIZE_CLASSES[i]; const usable_space = PAGE_SIZE - @sizeOf(SlabHeader); const objects_per_slab = usable_space / size; @@ -48,11 +44,7 @@ pub fn init() void { .slab_list = null, }; - serial.print(" Cache "); - serial.print_hex(size); - serial.print("B: "); - serial.print_hex(objects_per_slab); - serial.print(" objects/slab\n"); + serial.printf("Cache {}B: {} objects/slab\n", .{ size, objects_per_slab }); } initialized = true; @@ -63,7 +55,7 @@ pub fn alloc(size: usize) ?[*]u8 { if (!initialized) return null; if (size == 0) return null; - if (size > 2048) { + if (size > heap_const.LARGE_ALLOC_THRESHOLD) { return alloc_large(size); } @@ -75,7 +67,7 @@ pub fn free(ptr: [*]u8, size: usize) void { if (!initialized) return; if (size == 0) return; - if (size > 2048) { + if (size > heap_const.LARGE_ALLOC_THRESHOLD) { free_large(ptr, size); return; } @@ -85,13 +77,12 @@ pub fn free(ptr: [*]u8, size: usize) void { } fn find_cache_index(size: usize) usize { - var i: usize = 0; - while (i < NUM_CACHES) : (i += 1) { - if (size <= SIZE_CLASSES[i]) { + for (0..heap_const.NUM_CACHES) |i| { + if (size <= heap_const.SIZE_CLASSES[i]) { return i; } } - return NUM_CACHES - 1; + return heap_const.NUM_CACHES - 1; } fn alloc_from_cache(cache: *SlabCache) ?[*]u8 { @@ -118,14 +109,10 @@ fn alloc_from_cache(cache: *SlabCache) ?[*]u8 { fn create_slab(cache: *SlabCache) ?*SlabHeader { const phys_page = pmm.alloc_page() orelse return null; + const virt_addr = phys_page + HIGHER_HALF; - // Physical 0-4GB already mapped to 0xFFFF800000000000+ by boot.s - const virt_addr = phys_page + HIGHER_HALF_START; - - // Zero the page const page_ptr: [*]volatile u8 = @ptrFromInt(virt_addr); - var i: usize = 0; - while (i < PAGE_SIZE) : (i += 1) { + for (0..PAGE_SIZE) |i| { page_ptr[i] = 0; } @@ -136,10 +123,8 @@ fn create_slab(cache: *SlabCache) ?*SlabHeader { slab.next_slab = null; slab.prev_slab = null; - // Initialize freelist const first_obj_addr = virt_addr + @sizeOf(SlabHeader); - var j: usize = 0; - while (j < cache.objects_per_slab) : (j += 1) { + for (0..cache.objects_per_slab) |j| { const obj_addr = first_obj_addr + (j * cache.object_size); const obj: *FreeObject = @ptrFromInt(obj_addr); @@ -177,7 +162,6 @@ fn free_to_cache(cache: *SlabCache, ptr: [*]u8) void { slab.first_free = obj; slab.free_count += 1; - // If slab is completely free and not the only slab, return to PMM if (slab.free_count == slab.total_count) { if (slab.next_slab != null or slab.prev_slab != null) { return_slab_to_pmm(cache, slab); @@ -186,7 +170,6 @@ fn free_to_cache(cache: *SlabCache, ptr: [*]u8) void { } fn return_slab_to_pmm(cache: *SlabCache, slab: *SlabHeader) void { - // Unlink from cache if (slab.prev_slab) |prev| { prev.next_slab = slab.next_slab; } else { @@ -197,99 +180,36 @@ fn return_slab_to_pmm(cache: *SlabCache, slab: *SlabHeader) void { next.prev_slab = slab.prev_slab; } - // Free the page const slab_addr = @intFromPtr(slab); - const phys_addr = slab_addr - HIGHER_HALF_START; + const phys_addr = slab_addr - HIGHER_HALF; pmm.free_page(phys_addr); } fn alloc_large(size: usize) ?[*]u8 { const num_pages = (size + PAGE_SIZE - 1) / PAGE_SIZE; - // Try to allocate contiguous pages - var pages: [64]u64 = undefined; // Max 256KB allocation - if (num_pages > 64) return null; + var pages: [heap_const.MAX_LARGE_PAGES]u64 = undefined; + if (num_pages > heap_const.MAX_LARGE_PAGES) return null; - var i: usize = 0; - while (i < num_pages) : (i += 1) { + for (0..num_pages) |i| { pages[i] = pmm.alloc_page() orelse { - // Allocation failed - free what we got - var j: usize = 0; - while (j < i) : (j += 1) { + for (0..i) |j| { pmm.free_page(pages[j]); } return null; }; } - // Return first page as virtual address - const result: [*]u8 = @ptrFromInt(pages[0] + HIGHER_HALF_START); + const result: [*]u8 = @ptrFromInt(pages[0] + HIGHER_HALF); return result; } fn free_large(ptr: [*]u8, size: usize) void { const num_pages = (size + PAGE_SIZE - 1) / PAGE_SIZE; const base_virt = @intFromPtr(ptr); - const base_phys = base_virt - HIGHER_HALF_START; + const base_phys = base_virt - HIGHER_HALF; - // Free each page - var i: usize = 0; - while (i < num_pages) : (i += 1) { + for (0..num_pages) |i| { pmm.free_page(base_phys + (i * PAGE_SIZE)); } } - -pub fn print_stats() void { - if (!initialized) { - serial.print("Heap not initialized\n"); - return; - } - - serial.print("\n=== Heap Statistics ===\n"); - - var total_slabs: usize = 0; - var total_used: usize = 0; - var total_free: usize = 0; - - var i: usize = 0; - while (i < NUM_CACHES) : (i += 1) { - const cache = &caches[i]; - - var cache_total: usize = 0; - var cache_free: usize = 0; - var slab_count: usize = 0; - - var current = cache.slab_list; - while (current) |slab| { - slab_count += 1; - cache_total += slab.total_count; - cache_free += slab.free_count; - current = slab.next_slab; - } - - if (slab_count > 0) { - const used = cache_total - cache_free; - total_slabs += slab_count; - total_used += used * cache.object_size; - total_free += cache_free * cache.object_size; - - serial.print("Cache "); - serial.print_hex(cache.object_size); - serial.print("B: "); - serial.print_hex(slab_count); - serial.print(" slabs, "); - serial.print_hex(used); - serial.print("/"); - serial.print_hex(cache_total); - serial.print(" objects\n"); - } - } - - serial.print("\nTotal: "); - serial.print_hex(total_slabs); - serial.print(" slabs, "); - serial.print_hex(total_used); - serial.print(" bytes used, "); - serial.print_hex(total_free); - serial.print(" bytes free\n"); -} 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; } diff --git a/mirai/memory/pmm.zig b/mirai/memory/pmm.zig index 5d62936..a4b67d8 100644 --- a/mirai/memory/pmm.zig +++ b/mirai/memory/pmm.zig @@ -1,12 +1,14 @@ -//! Physical Memory Manager - Tracks free/used 4KB pages using a bitmap +//! Physical Memory Manager -const memory = @import("../asm/memory.zig"); +const asm_memory = @import("../asm/memory.zig"); +const memory_const = @import("../common/constants/memory.zig"); const multiboot = @import("../boot/multiboot/multiboot.zig"); +const paging_const = @import("../common/constants/paging.zig"); +const pmm_const = @import("../common/constants/pmm.zig"); const serial = @import("../drivers/serial/serial.zig"); -const system = @import("../system/system.zig"); -const PAGE_SIZE = system.constants.PAGE_SIZE; -const HIGHER_HALF_START = system.constants.HIGHER_HALF_START; +const PAGE_SIZE = memory_const.PAGE_SIZE; +const HIGHER_HALF = memory_const.HIGHER_HALF_START; var bitmap: [*]u8 = undefined; var bitmap_size: usize = 0; @@ -15,12 +17,11 @@ var used_pages: u64 = 0; var initialized: bool = false; pub fn init(kernel_end_phys: u64, memory_map: []multiboot.MemoryEntry) void { - serial.print("\n=== Physical Memory Manager ===\n"); + serial.print("\n=== PMM ===\n"); - // Find highest memory address var highest_addr: u64 = 0; for (memory_map) |entry| { - if (entry.entry_type == 1) { // Available + if (entry.entry_type == pmm_const.MEMORY_AVAILABLE) { const end = entry.base + entry.length; if (end > highest_addr) { highest_addr = end; @@ -29,67 +30,37 @@ pub fn init(kernel_end_phys: u64, memory_map: []multiboot.MemoryEntry) void { } total_pages = highest_addr / PAGE_SIZE; - bitmap_size = (total_pages + 7) / 8; // Convert bits to bytes - - serial.print("Total memory: "); - serial.print_hex(highest_addr / (1024 * 1024)); - serial.print(" MB\n"); - serial.print("Total pages: "); - serial.print_hex(total_pages); - serial.print("\n"); - serial.print("Bitmap size: "); - serial.print_hex(bitmap_size); - serial.print(" bytes\n"); - - // Place bitmap in higher-half memory (after kernel) + bitmap_size = (total_pages + 7) / 8; + + serial.printf("Memory: {} MB, {} pages\n", .{ highest_addr / (1024 * 1024), total_pages }); + const bitmap_phys = align_up(kernel_end_phys, PAGE_SIZE); - bitmap = @ptrFromInt(bitmap_phys + HIGHER_HALF_START); - - serial.print("Bitmap physical: "); - serial.print_hex(bitmap_phys); - serial.print("\n"); - serial.print("Bitmap virtual: "); - serial.print_hex(@intFromPtr(bitmap)); - serial.print("\n"); - - // Mark all pages as used initially - var i: usize = 0; - while (i < bitmap_size) : (i += 1) { - bitmap[i] = 0xFF; + bitmap = @ptrFromInt(bitmap_phys + HIGHER_HALF); + + for (0..bitmap_size) |i| { + bitmap[i] = pmm_const.BITMAP_MARK_USED; } used_pages = total_pages; - // Mark available regions as free for (memory_map) |entry| { - if (entry.entry_type == 1) { // Available + if (entry.entry_type == pmm_const.MEMORY_AVAILABLE) { free_region(entry.base, entry.length); } } - // Reserve kernel and bitmap - const kernel_size = kernel_end_phys - 0x100000; + const kernel_size = kernel_end_phys - pmm_const.KERNEL_BASE; const bitmap_pages = (bitmap_size + PAGE_SIZE - 1) / PAGE_SIZE; - reserve_region(0, 0x100000); // Reserve first 1MB - reserve_region(0x100000, kernel_size); + reserve_region(0, pmm_const.FIRST_MB); + reserve_region(pmm_const.KERNEL_BASE, kernel_size); reserve_region(bitmap_phys, bitmap_pages * PAGE_SIZE); - // Reserve MMIO regions (PCI, AHCI, framebuffer, etc.) - // PCI configuration space and above - reserve_region(0xE0000000, 0x10000000); // 256MB PCI MMIO region - reserve_region(0x80000000, 0x10000000); // Framebuffer and device MMIO (includes AHCI ABAR at 0x81084000) + reserve_region(pmm_const.MMIO_PCI_BASE, pmm_const.MMIO_PCI_SIZE); + reserve_region(pmm_const.MMIO_FRAMEBUFFER_BASE, pmm_const.MMIO_FRAMEBUFFER_SIZE); - // Reserve currently active page tables to prevent reallocation reserve_active_page_tables(); - serial.print("Free pages: "); - serial.print_hex(total_pages - used_pages); - serial.print(" ("); - serial.print_hex((total_pages - used_pages) * PAGE_SIZE / (1024 * 1024)); - serial.print(" MB)\n"); - serial.print("Used pages: "); - serial.print_hex(used_pages); - serial.print("\n"); + serial.printf("Free: {} pages ({} MB)\n", .{ total_pages - used_pages, (total_pages - used_pages) * PAGE_SIZE / (1024 * 1024) }); initialized = true; } @@ -97,8 +68,7 @@ pub fn init(kernel_end_phys: u64, memory_map: []multiboot.MemoryEntry) void { pub fn alloc_page() ?u64 { if (!initialized) return null; - var i: u64 = 0; - while (i < total_pages) : (i += 1) { + for (0..total_pages) |i| { if (!is_page_used(i)) { set_page_used(i); return i * PAGE_SIZE; @@ -120,8 +90,7 @@ fn free_region(base: u64, length: u64) void { const start_page = align_up(base, PAGE_SIZE) / PAGE_SIZE; const end_page = align_down(base + length, PAGE_SIZE) / PAGE_SIZE; - var page = start_page; - while (page < end_page) : (page += 1) { + for (start_page..end_page) |page| { if (page < total_pages) { set_page_free(page); } @@ -132,8 +101,7 @@ fn reserve_region(base: u64, length: u64) void { const start_page = base / PAGE_SIZE; const end_page = (base + length + PAGE_SIZE - 1) / PAGE_SIZE; - var page = start_page; - while (page < end_page) : (page += 1) { + for (start_page..end_page) |page| { if (page < total_pages) { set_page_used(page); } @@ -142,13 +110,13 @@ fn reserve_region(base: u64, length: u64) void { fn is_page_used(page: u64) bool { const byte_index = page / 8; - const bit_index = @as(u3, @truncate(page % 8)); + const bit_index: u3 = @truncate(page % 8); return (bitmap[byte_index] & (@as(u8, 1) << bit_index)) != 0; } fn set_page_used(page: u64) void { const byte_index = page / 8; - const bit_index = @as(u3, @truncate(page % 8)); + const bit_index: u3 = @truncate(page % 8); if ((bitmap[byte_index] & (@as(u8, 1) << bit_index)) == 0) { bitmap[byte_index] |= (@as(u8, 1) << bit_index); used_pages += 1; @@ -157,7 +125,7 @@ fn set_page_used(page: u64) void { fn set_page_free(page: u64) void { const byte_index = page / 8; - const bit_index = @as(u3, @truncate(page % 8)); + const bit_index: u3 = @truncate(page % 8); if ((bitmap[byte_index] & (@as(u8, 1) << bit_index)) != 0) { bitmap[byte_index] &= ~(@as(u8, 1) << bit_index); used_pages -= 1; @@ -172,43 +140,33 @@ fn align_down(addr: u64, alignment: u64) u64 { return addr & ~(alignment - 1); } -/// Reserve all page table pages currently in use by walking CR3 hierarchy fn reserve_active_page_tables() void { - const PAGE_PRESENT: u64 = 1; - - const cr3 = memory.read_page_table_base() & ~@as(u64, 0xFFF); + const cr3 = asm_memory.read_page_table_base() & ~@as(u64, paging_const.OFFSET_MASK); - // Reserve PML4 page reserve_region(cr3, PAGE_SIZE); - const pml4: [*]volatile u64 = @ptrFromInt(cr3 + HIGHER_HALF_START); + const pml4: [*]volatile u64 = @ptrFromInt(cr3 + HIGHER_HALF); - // Walk PML4 - var pml4_i: usize = 0; - while (pml4_i < 512) : (pml4_i += 1) { - if ((pml4[pml4_i] & PAGE_PRESENT) == 0) continue; + for (0..paging_const.PML4_ENTRIES) |pml4_i| { + if ((pml4[pml4_i] & paging_const.PTE_PRESENT) == 0) continue; - const pdpt_phys = pml4[pml4_i] & ~@as(u64, 0xFFF); + const pdpt_phys = pml4[pml4_i] & paging_const.PTE_MASK; reserve_region(pdpt_phys, PAGE_SIZE); - const pdpt: [*]volatile u64 = @ptrFromInt(pdpt_phys + HIGHER_HALF_START); + const pdpt: [*]volatile u64 = @ptrFromInt(pdpt_phys + HIGHER_HALF); - // Walk PDPT - var pdpt_i: usize = 0; - while (pdpt_i < 512) : (pdpt_i += 1) { - if ((pdpt[pdpt_i] & PAGE_PRESENT) == 0) continue; + for (0..paging_const.PML4_ENTRIES) |pdpt_i| { + if ((pdpt[pdpt_i] & paging_const.PTE_PRESENT) == 0) continue; - const pd_phys = pdpt[pdpt_i] & ~@as(u64, 0xFFF); + const pd_phys = pdpt[pdpt_i] & paging_const.PTE_MASK; reserve_region(pd_phys, PAGE_SIZE); - const pd: [*]volatile u64 = @ptrFromInt(pd_phys + HIGHER_HALF_START); + const pd: [*]volatile u64 = @ptrFromInt(pd_phys + HIGHER_HALF); - // Walk PD - var pd_i: usize = 0; - while (pd_i < 512) : (pd_i += 1) { - if ((pd[pd_i] & PAGE_PRESENT) == 0) continue; + for (0..paging_const.PML4_ENTRIES) |pd_i| { + if ((pd[pd_i] & paging_const.PTE_PRESENT) == 0) continue; - const pt_phys = pd[pd_i] & ~@as(u64, 0xFFF); + const pt_phys = pd[pd_i] & paging_const.PTE_MASK; reserve_region(pt_phys, PAGE_SIZE); } } |
