diff options
| author | Bobby <[email protected]> | 2026-02-24 06:56:58 +0530 |
|---|---|---|
| committer | Bobby <[email protected]> | 2026-02-24 06:56:58 +0530 |
| commit | 5fe89e6f5b6fd6f5b5589b9e5d4714e0f4fbe5e8 (patch) | |
| tree | 2ae2a13678844b82b43583ca28eed4d4b6223ec0 /mirai.old/kata/memory.zig | |
| parent | 297c66b480a238dad5ce7f03405fe6f5b9123701 (diff) | |
| download | akiba-5fe89e6f5b6fd6f5b5589b9e5d4714e0f4fbe5e8.tar.xz akiba-5fe89e6f5b6fd6f5b5589b9e5d4714e0f4fbe5e8.zip | |
Bunch of stuff moved as .old for new arch change
Diffstat (limited to 'mirai.old/kata/memory.zig')
| -rw-r--r-- | mirai.old/kata/memory.zig | 288 |
1 files changed, 288 insertions, 0 deletions
diff --git a/mirai.old/kata/memory.zig b/mirai.old/kata/memory.zig new file mode 100644 index 0000000..f90c9f0 --- /dev/null +++ b/mirai.old/kata/memory.zig @@ -0,0 +1,288 @@ +//! Kata memory management + +const asm_memory = @import("../asm/memory.zig"); +const memory_const = @import("../common/constants/memory.zig"); +const memory_limits = @import("../common/limits/memory.zig"); +const paging = @import("../memory/paging.zig"); +const paging_const = @import("../common/constants/paging.zig"); +const pmm = @import("../memory/pmm.zig"); +const types = @import("types.zig"); + +const HIGHER_HALF = memory_const.HIGHER_HALF_START; +const PAGE_SIZE = memory_const.PAGE_SIZE; + +const KERNEL_VMALLOC_START: u64 = 0xFFFFFF8000000000; +var next_vmalloc_addr: u64 = KERNEL_VMALLOC_START; + +pub const VirtualBuffer = struct { + data: []u8, + virt_base: u64, + phys_pages: [1024]u64, + num_pages: usize, + + pub fn alloc(size: usize) !VirtualBuffer { + const num_pages = (size + PAGE_SIZE - 1) / PAGE_SIZE; + if (num_pages > 1024) return error.AllocationTooLarge; + + var buffer: VirtualBuffer = undefined; + buffer.num_pages = num_pages; + + var i: usize = 0; + errdefer { + var j: usize = 0; + while (j < i) : (j += 1) { + pmm.free_page(buffer.phys_pages[j]); + } + } + + while (i < num_pages) : (i += 1) { + buffer.phys_pages[i] = pmm.alloc_page() orelse return error.OutOfMemory; + } + + buffer.virt_base = next_vmalloc_addr; + next_vmalloc_addr += num_pages * PAGE_SIZE; + + i = 0; + errdefer { + var j: usize = 0; + while (j < num_pages) : (j += 1) { + pmm.free_page(buffer.phys_pages[j]); + } + } + + while (i < num_pages) : (i += 1) { + const virt_addr = buffer.virt_base + (i * PAGE_SIZE); + const phys_addr = buffer.phys_pages[i]; + + try paging.map_page(virt_addr, phys_addr, paging.PAGE_WRITABLE); + + const zero_ptr: [*]volatile u8 = @ptrFromInt(phys_addr + HIGHER_HALF); + for (0..PAGE_SIZE) |j| { + zero_ptr[j] = 0; + } + } + + const data_ptr: [*]u8 = @ptrFromInt(buffer.virt_base); + buffer.data = data_ptr[0..size]; + + return buffer; + } + + pub fn free(self: *VirtualBuffer) void { + for (0..self.num_pages) |i| { + pmm.free_page(self.phys_pages[i]); + } + } +}; + +pub fn setup(kata: *types.Kata, framebuffer_phys: u64, framebuffer_size: u64) !void { + kata.page_table = try paging.create_page_table(); + + kata.user_stack_top = memory_const.USER_STACK_TOP; + kata.user_stack_bottom = memory_const.USER_STACK_TOP - (memory_const.USER_STACK_MAX_PAGES * PAGE_SIZE); + kata.user_stack_committed = memory_const.USER_STACK_TOP - (memory_const.USER_STACK_INITIAL_PAGES * PAGE_SIZE); + + const serial = @import("../drivers/serial/serial.zig"); + + for (0..memory_const.USER_STACK_INITIAL_PAGES) |i| { + const page = pmm.alloc_page() orelse return error.OutOfMemory; + + // Check if we got Ash's PD + if (pmm.ash_pd_phys != 0 and page == pmm.ash_pd_phys) { + serial.printf("SETUP: Got Ash's PD {x} for user stack page!\n", .{page}); + } + + const virt = kata.user_stack_committed + (i * PAGE_SIZE); + _ = try paging.map_page_in_table(kata.page_table, virt, page, paging.PAGE_WRITABLE | paging.PAGE_USER); + + const page_ptr: [*]volatile u8 = @ptrFromInt(page + HIGHER_HALF); + for (0..PAGE_SIZE) |j| { + page_ptr[j] = 0; + } + } + + const first_page = pmm.alloc_page() orelse return error.OutOfMemory; + + // Check if we got Ash's PD for kernel stack + if (pmm.ash_pd_phys != 0 and first_page == pmm.ash_pd_phys) { + serial.printf("SETUP: Got Ash's PD {x} for kernel stack!\n", .{first_page}); + } + + const kernel_stack_base = first_page; + + // Identity map first page + _ = try paging.map_page_in_table(kata.page_table, first_page, first_page, paging.PAGE_WRITABLE); + + // Zero the page + var page_ptr: [*]volatile u8 = @ptrFromInt(first_page + HIGHER_HALF); + for (0..PAGE_SIZE) |j| { + page_ptr[j] = 0; + } + + // Allocate remaining pages, checking for contiguity + var i: u64 = 1; + while (i < memory_const.KERNEL_STACK_PAGES) : (i += 1) { + const page = pmm.alloc_page() orelse return error.OutOfMemory; + const expected = first_page + (i * PAGE_SIZE); + + if (page != expected) { + // Non-contiguous - free what we got and use smaller stack + pmm.free_page(page); + break; + } + + // Identity map this page + _ = try paging.map_page_in_table(kata.page_table, page, page, paging.PAGE_WRITABLE); + + // Zero the page + page_ptr = @ptrFromInt(page + HIGHER_HALF); + for (0..PAGE_SIZE) |j| { + page_ptr[j] = 0; + } + } + + // Stack top is at the end of allocated contiguous pages (identity address) + const actual_stack_size = i * PAGE_SIZE; + kata.stack_top = kernel_stack_base + actual_stack_size; + + if (framebuffer_phys != 0 and framebuffer_size > 0) { + const fb_pages = (framebuffer_size + PAGE_SIZE - 1) / PAGE_SIZE; + for (0..fb_pages) |fi| { + const phys = framebuffer_phys + (fi * PAGE_SIZE); + _ = try paging.map_page_in_table( + kata.page_table, + phys, + phys, + paging.PAGE_WRITABLE | paging.PAGE_USER, + ); + } + } +} + +pub fn load_segment( + kata: *types.Kata, + vaddr: u64, + elf_data: []const u8, + data_offset: u64, + data_size: u64, + mem_size: u64, + flags: u32, +) !void { + if (mem_size == 0) return; + if (data_size > mem_size) return error.InvalidSegment; + if (data_offset + data_size > elf_data.len) return error.SegmentOutOfBounds; + + if (!memory_limits.is_kata_range(vaddr, mem_size)) { + return error.InvalidAddress; + } + + const page_aligned_vaddr = vaddr & ~@as(u64, 0xFFF); + const offset_in_page = vaddr - page_aligned_vaddr; + + const total_size = offset_in_page + mem_size; + const num_pages = (total_size + PAGE_SIZE - 1) / PAGE_SIZE; + + var page_flags: u64 = paging.PAGE_USER; + if ((flags & 0x2) != 0) { + page_flags |= paging.PAGE_WRITABLE; + } + + for (0..num_pages) |i| { + const page_vaddr = page_aligned_vaddr + (i * PAGE_SIZE); + + var page_phys: u64 = 0; + const existing_entry = paging.get_page_entry(kata.page_table, page_vaddr); + + if (existing_entry != null and (existing_entry.? & paging.PAGE_PRESENT) != 0) { + page_phys = existing_entry.? & ~@as(u64, 0xFFF); + + const existing_writable = (existing_entry.? & paging.PAGE_WRITABLE) != 0; + const new_writable = (page_flags & paging.PAGE_WRITABLE) != 0; + + if (new_writable and !existing_writable) { + _ = try paging.map_page_in_table(kata.page_table, page_vaddr, page_phys, page_flags); + } + } else { + page_phys = pmm.alloc_page() orelse return error.OutOfMemory; + + // Check if we got Ash's PD + if (pmm.ash_pd_phys != 0 and page_phys == pmm.ash_pd_phys) { + const serial = @import("../drivers/serial/serial.zig"); + serial.printf("KATA-MEM: Got Ash's PD {x} for data page at vaddr {x}!\n", .{ page_phys, page_vaddr }); + } + + _ = try paging.map_page_in_table(kata.page_table, page_vaddr, page_phys, page_flags); + + const zero_ptr: [*]volatile u8 = @ptrFromInt(page_phys + HIGHER_HALF); + for (0..PAGE_SIZE) |j| { + zero_ptr[j] = 0; + } + } + + const dest_ptr: [*]volatile u8 = @ptrFromInt(page_phys + HIGHER_HALF); + + const page_offset = if (i == 0) offset_in_page else 0; + const segment_pos: u64 = if (i == 0) 0 else (i * PAGE_SIZE - offset_in_page); + + if (segment_pos < data_size) { + const bytes_remaining = data_size - segment_pos; + const bytes_to_copy = @min(PAGE_SIZE - page_offset, bytes_remaining); + const elf_pos = data_offset + segment_pos; + + if (elf_pos + bytes_to_copy <= elf_data.len) { + const src = elf_data[elf_pos .. elf_pos + bytes_to_copy]; + + for (0..bytes_to_copy) |k| { + dest_ptr[page_offset + k] = src[k]; + } + } + } + } +} + +pub fn cleanup(kata: *types.Kata) void { + if (kata.page_table != 0) { + const current_cr3 = asm_memory.read_page_table_base(); + if (current_cr3 != kata.page_table) { + paging.destroy_page_table(kata.page_table); + kata.page_table = 0; + } + // If CR3 == kata.page_table, leave page_table intact for Shinigami + } + kata.stack_top = 0; + kata.user_stack_top = 0; + kata.user_stack_bottom = 0; + kata.user_stack_committed = 0; +} + +/// Called by Shinigami to destroy a zombie's page table. +/// Safe because Shinigami runs with its own page table. +pub fn destroy_zombie_page_table(page_table: u64) void { + paging.destroy_page_table(page_table); +} + +pub fn grow_stack(kata: *types.Kata, fault_addr: u64) bool { + const page_addr = fault_addr & ~@as(u64, 0xFFF); + + if (page_addr >= kata.user_stack_committed or page_addr < kata.user_stack_bottom) { + return false; + } + + var addr = kata.user_stack_committed - PAGE_SIZE; + while (addr >= page_addr) : (addr -= PAGE_SIZE) { + const page = pmm.alloc_page() orelse return false; + _ = paging.map_page_in_table(kata.page_table, addr, page, paging.PAGE_WRITABLE | paging.PAGE_USER) catch return false; + + const page_ptr: [*]volatile u8 = @ptrFromInt(page + HIGHER_HALF); + for (0..PAGE_SIZE) |j| { + page_ptr[j] = 0; + } + + asm_memory.invalidate_page(addr); + + if (addr == 0) break; + } + + kata.user_stack_committed = page_addr; + return true; +} |
