aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBobby <[email protected]>2026-02-15 21:05:01 +0530
committerBobby <[email protected]>2026-02-15 21:05:01 +0530
commita3d895c62740b386d3f802faebddd3c188e9688e (patch)
treea6fe729e0d2d52138b8fa0dbc16ab47185327829
parentdfd1508131f6b51600ab26a169cf4b09348b0ad2 (diff)
downloadakiba-a3d895c62740b386d3f802faebddd3c188e9688e.tar.xz
akiba-a3d895c62740b386d3f802faebddd3c188e9688e.zip
refactor: Modularize memory management constants and improve structure
-rw-r--r--mirai/common/constants/heap.zig6
-rw-r--r--mirai/common/constants/paging.zig11
-rw-r--r--mirai/common/constants/pmm.zig14
-rw-r--r--mirai/memory/heap.zig130
-rw-r--r--mirai/memory/paging.zig114
-rw-r--r--mirai/memory/pmm.zig128
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);
}
}