22 for (
size_t i = 0; i < pageAmount; i++)
27 for (
size_t j = 0; j < i; j++)
130 panic(
NULL,
"Attempted to free address space still in use by CPUs");
167 for (
size_t i = 0; i < pageAmount; i++)
197 for (
uint64_t i = 0; i < amount; i++)
234 for (
uint64_t i = 0; i < amount; i++)
263 if (newPinnedPage ==
NULL)
333 if (space ==
NULL ||
address ==
NULL || terminator ==
NULL || objectSize == 0 || maxCount == 0)
339 size_t terminatorMatchedBytes = 0;
351 while (current < end)
380 for (
uintptr_t scanAddr = current; scanAddr < scanEnd; scanAddr++)
382 if (*(
uint8_t*)scanAddr == term)
392 while (scanAddr < scanEnd)
394 if (*((
uint8_t*)scanAddr) == ((
uint8_t*)terminator)[terminatorMatchedBytes])
396 terminatorMatchedBytes++;
397 if (terminatorMatchedBytes == objectSize)
405 scanAddr = scanAddr - terminatorMatchedBytes + objectSize;
406 terminatorMatchedBytes = 0;
446 if (space ==
NULL || (addr ==
NULL && length != 0))
477 pageAmount, alignment, &addr) !=
ERR)
485 pageAmount, alignment, &addr) !=
ERR)
497 if (space ==
NULL || mapping ==
NULL || length == 0)
519 if (virtAddr !=
NULL &&
532 if (virtAddr ==
NULL)
536 if (virtAddr ==
NULL)
548 if ((
uintptr_t)virtAddr % alignment != 0)
587 if (newCallbacks ==
NULL)
604 bitmap_set(&space->callbackBitmap, callbackId);
606 callback->
func = func;
632 if (space ==
NULL || mapping ==
NULL)
#define assert(expression)
EFI_PHYSICAL_ADDRESS buffer
bool stack_pointer_is_in_stack(stack_pointer_t *stack, uintptr_t addr, uint64_t length)
Check if an region is within the stack.
void stack_pointer_poke(uint64_t offset)
Poke the stack to ensure that a page fault will occur at the given offset.
#define CPU_MAX
Maximum number of CPUs supported.
static uintptr_t address
Mapped virtual address of the HPET registers.
NORETURN void panic(const interrupt_frame_t *frame, const char *format,...)
Panic the kernel, printing a message and halting.
#define PFN_TO_PHYS(_pfn)
Convert a PFN to its physical address.
uintptr_t phys_addr_t
Physical address type.
static uint64_t page_table_count_pages_with_flags(page_table_t *table, void *addr, size_t amount, pml_flags_t flags)
Counts the number of pages in a range that have all the specified flags set.
static uint64_t page_table_traverse(page_table_t *table, page_table_traverse_t *traverse, const void *addr, pml_flags_t flags)
Allows for fast traversal of the page table by caching previously accessed layers.
pml_index_t
Indexes into a pml level.
static uint64_t page_table_get_phys_addr(page_table_t *table, void *addr, phys_addr_t *out)
Retrieves the physical address mapped to a given virtual address.
#define PML_CALLBACK_NONE
Special callback ID that indicates no callback is associated with the page.
static bool page_table_is_unmapped(page_table_t *table, void *addr, size_t amount)
Checks if a range of virtual addresses is completely unmapped.
#define PML_ADDR_TO_INDEX(addr, level)
Calculates the index into a page table level for a given virtual address.
static uint64_t page_table_map(page_table_t *table, void *addr, phys_addr_t phys, size_t amount, pml_flags_t flags, pml_callback_id_t callbackId)
Maps a range of virtual addresses to physical addresses in the page table.
uint8_t pml_callback_id_t
Callback ID type.
#define PAGE_TABLE_TRAVERSE_CREATE
Create a page_table_traverse_t initializer.
#define PML_MAX_CALLBACK
Maximum number of callbacks that can be registered for a page table.
static void page_table_deinit(page_table_t *table)
Deinitializes a page table, freeing all allocated pages.
#define PHYS_ADDR_INVALID
Invalid physical address.
size_t pfn_t
Page Frame Number type.
static uint64_t page_table_init(page_table_t *table, pml_alloc_pages_t allocPages, pml_free_pages_t freePages)
Initializes a page table.
static bool page_table_is_mapped(page_table_t *table, const void *addr, size_t amount)
Checks if a range of virtual addresses is completely mapped.
static uint64_t page_table_find_unmapped_region(page_table_t *table, void *startAddr, void *endAddr, size_t amount, size_t alignment, void **outAddr)
Finds the first contiguous unmapped region with the given number of pages within the specified addres...
#define PML_ENSURE_LOWER_HALF(addr)
Ensures that the given address is in the lower half of the address space.
void pmm_free_pages(pfn_t *pfns, size_t count)
Free multiple pages of physical memory.
uint64_t pmm_alloc_pages(pfn_t *pfns, size_t count)
Allocate multiple pages of physical memory.
void pmm_free(pfn_t pfn)
Free a single page of physical memory.
pfn_t pmm_alloc(void)
Allocate a single page of physical memory.
pfn_t pmm_alloc_bitmap(size_t count, pfn_t maxPfn, pfn_t alignPfn)
Allocate a contiguous region of physical memory using the bitmap.
uint64_t space_pin_terminated(space_t *space, const void *address, const void *terminator, size_t objectSize, size_t maxCount, stack_pointer_t *userStack)
Pins a region of memory terminated by a terminator value.
void * space_mapping_end(space_t *space, space_mapping_t *mapping, errno_t err)
Performs cleanup after changes to the address space mappings.
bool space_is_mapped(space_t *space, const void *virtAddr, size_t length)
Checks if a virtual memory region is fully mapped.
void space_unpin(space_t *space, const void *address, size_t length)
Unpins pages in a region previously pinned with space_pin() or space_pin_string().
void space_free_callback(space_t *space, pml_callback_id_t callbackId)
Free a callback.
uint64_t space_mapping_start(space_t *space, space_mapping_t *mapping, void *virtAddr, phys_addr_t physAddr, size_t length, size_t alignment, pml_flags_t flags)
Prepare for changes to the address space mappings.
void(* space_callback_func_t)(void *data)
Space callback function.
space_flags_t
Flags for space initialization.
pml_callback_id_t space_alloc_callback(space_t *space, size_t pageAmount, space_callback_func_t func, void *data)
Allocate a callback.
uint64_t space_user_page_count(space_t *space)
Get the number of user pages allocated in the address space.
phys_addr_t space_virt_to_phys(space_t *space, const void *virtAddr)
Translate a virtual address to a physical address in the address space.
uint64_t space_pin(space_t *space, const void *buffer, size_t length, stack_pointer_t *userStack)
Pins pages within a region of the address space.
uint64_t space_check_access(space_t *space, const void *addr, size_t length)
Checks if a virtual memory region is within the allowed address range of the space.
void space_deinit(space_t *space)
Deinitializes a virtual address space.
uint64_t space_init(space_t *space, uintptr_t startAddress, uintptr_t endAddress, space_flags_t flags)
Initializes a virtual address space.
@ SPACE_MAP_KERNEL_HEAP
Map the kernel heap into the address space.
@ SPACE_MAP_IDENTITY
Map the identity mapped physical memory into the address space.
@ SPACE_MAP_KERNEL_BINARY
Map the kernel binary into the address space.
#define VMM_KERNEL_HEAP_MAX
The maximum address for the kernel heap.
#define VMM_KERNEL_BINARY_MAX
The maximum address for the content of the kernel binary.
space_t * vmm_kernel_space_get(void)
Retrieves the kernel's address space.
#define VMM_IDENTITY_MAPPED_MIN
The minimum address for the identity mapped physical memory.
#define VMM_USER_SPACE_MAX
The maximum address for user space.
#define VMM_KERNEL_BINARY_MIN
The minimum address for the content of the kernel binary./*#end#*/.
#define VMM_USER_SPACE_MIN
The minimum address for user space.
#define VMM_IDENTITY_MAPPED_MAX
The maximum address for the identity mapped physical memory.
#define VMM_KERNEL_HEAP_MIN
The minimum address for the kernel heap.
static void lock_init(lock_t *lock)
Initializes a lock.
#define LOCK_SCOPE(lock)
Acquires a lock for the reminder of the current scope.
static void lock_release(lock_t *lock)
Releases a lock.
static void lock_acquire(lock_t *lock)
Acquires a lock, blocking until it is available.
void map_init(map_t *map)
Initialize a map.
void map_entry_init(map_entry_t *entry)
Initialize a map entry.
static map_key_t map_key_uint64(uint64_t uint64)
Create a map key from a uint64_t.
uint64_t map_insert(map_t *map, const map_key_t *key, map_entry_t *value)
Insert a key-value pair into the map.
void map_remove(map_t *map, map_entry_t *entry)
Remove a entry from the map.
map_entry_t * map_get(map_t *map, const map_key_t *key)
Get a value from the map by key.
#define EINVAL
Invalid argument.
#define EFAULT
Bad address.
#define ENOMEM
Out of memory.
#define EOVERFLOW
Value too large for defined data type.
#define errno
Error number variable.
static uint64_t bitmap_find_first_clear(bitmap_t *map, uint64_t startIdx, uint64_t endIdx)
Find the first clear bit in the bitmap.
static bool bitmap_is_empty(bitmap_t *map)
Check if the bitmap is empty (all bits clear).
static void bitmap_clear(bitmap_t *map, uint64_t index)
Clear a bit in the bitmap.
static void bitmap_set(bitmap_t *map, uint64_t index)
Set a bit in the bitmap.
#define BITMAP_FOR_EACH_SET(idx, map)
Iterate over each set bit in the bitmap.
#define BITMAP_DEFINE_INIT(name, bits)
Initialize a bitmap defined with BITMAP_DEFINE.
#define ROUND_DOWN(number, multiple)
#define ROUND_UP(number, multiple)
#define BYTES_TO_PAGES(amount)
Convert a size in bytes to pages.
#define NULL
Pointer error value.
#define ERR
Integer error value.
#define PAGE_SIZE
The size of a memory page in bytes.
#define CONTAINER_OF(ptr, type, member)
Container of macro.
static const path_flag_t flags[]
static uint64_t space_pmm_bitmap_alloc_pages(pfn_t *pfns, size_t pageAmount)
static void space_map_kernel_space_region(space_t *space, uintptr_t start, uintptr_t end)
static void space_update_free_address(space_t *space, uintptr_t virtAddr, uint64_t pageAmount)
static uint64_t space_populate_user_region(space_t *space, const void *buffer, size_t pageAmount)
static uint64_t space_pin_depth_inc(space_t *space, const void *address, uint64_t amount)
static void * space_find_free_region(space_t *space, uint64_t pageAmount, uint64_t alignment)
static void space_align_region(void **virtAddr, size_t *length)
static void space_pin_depth_dec(space_t *space, const void *address, uint64_t amount)
static void space_unmap_kernel_space_region(space_t *space, uintptr_t start, uintptr_t end)
#define atomic_init(obj, value)
__UINTPTR_TYPE__ uintptr_t
_PUBLIC void * malloc(size_t size)
_PUBLIC void free(void *ptr)
_PUBLIC void * memcpy(void *_RESTRICT s1, const void *_RESTRICT s2, size_t n)
_PUBLIC void * memset(void *s, int c, size_t n)
pml_alloc_pages_t allocPages
Helper structure for fast traversal of the page table.
uint64_t present
If set the page is present in memory and readable.
A entry in a page table without a specified address or callback ID.
pml_entry_t entries[PML_INDEX_AMOUNT]
space_callback_func_t func
Helper structure for managing address space mappings.
uint64_t pinCount
The number of times this page is pinned, will be unpinned when it reaches 0.
Virtual address space structure.
map_t pinnedPages
Map of pages with a pin depth greater than 1.
uintptr_t startAddress
The start address for allocations in this address space.
uint64_t callbacksLength
Length of the callbacks array.
uintptr_t endAddress
The end address for allocations in this address space.
page_table_t pageTable
The page table associated with the address space.
uintptr_t freeAddress
The next available free virtual address in this address space.
atomic_uint16_t shootdownAcks
space_callback_t * callbacks
Structure to define a stack in memory.
static space_t kernelSpace