Today I implemented something called the "pt_space_allocator," which stands for "page table space allocator." Because kernel's memory allocator has not been initalized in the kernel setup stage, we need alternative way to allocate a space for kernel's page table to reside. That's where this comes in—a simple kstruct-like allocator specialized for page table space.
__attribute__ ((section(".kernel_setup_stage"))) struct {
max_t start_addr;
max_t end_addr;
max_t current_addr;
}kernel_pt_space_manager;
The system is identical to the kstruct allocator. It starts with a starting address and end address, increment the current_address to the amount of memory allocated. Because of this, it only has the function for allocating, not for freeing the memory.
/// @brief Rudimentary allocator for kernel's page table
max_t page::alloc_pt_space(max_t size , max_t alignment) {
max_t addr = memory::align_address(kernel_pt_space_manager.current_addr , alignment); // Align address
kernel_pt_space_manager.current_addr = addr+size; // increment address
if(kernel_pt_space_manager.current_addr >= kernel_pt_space_manager.end_addr) return 0x00;
return addr;
}
The method it uses to determine what part of the memory to use as the allocation pool is as follows:
With this system, when setting up the page table for higher half kernel, we can have a safe space to set up PML4 table, without having to use the pmem allocator.
Also, I briefly thought about how the memory map is going to be for the higher-half design, and I think we should map all the usable free pool from the memory into one giant contiguous virtual memory space, so that the memory management becomes less fragmented and much more easier. For that, we need some kind of interface function that can map any arbitrary physical page into virtual page, which is going to be little bit tricky to implement.