#include "memory/KernelVM.h" #include "arch/MMU.h" #include static const u64 KERNEL_VM_RANGE_START = 0xfffffffff0000000; static Bitmap g_kernelvm_bitmap; static u8 bitmap_memory[4096]; static const usize KERNEL_VM_RANGE_SIZE = (sizeof(bitmap_memory) * 8) * ARCH_PAGE_SIZE; static const u64 KERNEL_VM_RANGE_END = KERNEL_VM_RANGE_SIZE + KERNEL_VM_RANGE_START; static_assert(KERNEL_VM_RANGE_END == 0xfffffffff8000000); static usize g_used_vm; namespace KernelVM { void init() { g_kernelvm_bitmap.initialize(bitmap_memory, sizeof(bitmap_memory)); } Result alloc_one_page() { for (u64 index = 0; index < g_kernelvm_bitmap.size(); index++) { if (g_kernelvm_bitmap.get(index)) continue; g_kernelvm_bitmap.set(index, true); g_used_vm += ARCH_PAGE_SIZE; return KERNEL_VM_RANGE_START + (index * ARCH_PAGE_SIZE); } return err(ENOMEM); } Result alloc_several_pages(usize count) { u64 first_free_index = 0; u64 free_contiguous_pages = 0; for (u64 index = 0; index < g_kernelvm_bitmap.size(); index++) { if (g_kernelvm_bitmap.get(index)) { free_contiguous_pages = 0; continue; } // At this point, we have a free page. if (!free_contiguous_pages) first_free_index = index; free_contiguous_pages++; // Found enough contiguous free pages!! if (free_contiguous_pages == count) { g_used_vm += ARCH_PAGE_SIZE * count; g_kernelvm_bitmap.clear_region(first_free_index, count, true); return KERNEL_VM_RANGE_START + (first_free_index * ARCH_PAGE_SIZE); } } return err(ENOMEM); } Result free_one_page(u64 address) { if (address < KERNEL_VM_RANGE_START) return err(EFAULT); u64 index = (address - KERNEL_VM_RANGE_START) / ARCH_PAGE_SIZE; if (index >= g_kernelvm_bitmap.size()) return err(EFAULT); g_kernelvm_bitmap.set(index, false); g_used_vm -= ARCH_PAGE_SIZE; return {}; } Result free_several_pages(u64 address, usize count) { if (address < KERNEL_VM_RANGE_START) return err(EFAULT); if (address + (count * ARCH_PAGE_SIZE) >= KERNEL_VM_RANGE_END) return err(EFAULT); u64 index = (address - KERNEL_VM_RANGE_START) / ARCH_PAGE_SIZE; g_kernelvm_bitmap.clear_region(index, count, false); g_used_vm -= ARCH_PAGE_SIZE * count; return {}; } usize used() { return g_used_vm; } usize free() { return KERNEL_VM_RANGE_SIZE - g_used_vm; } }