15using namespace MaxOS::memory;
16using namespace MaxOS::common;
17using namespace MaxOS::processes;
18using namespace MaxOS::processes::resources;
39 for (
size_t i = 256; i < 512; i++) {
43 m_pml4_root_address[i] = (uint64_t)m_pml4_root_physical_address |
PRESENT |
WRITE;
53 asm volatile(
"mov %0, %%cr3"::
"r"((uint64_t)m_pml4_root_physical_address) :
"memory");
62 m_first_region = m_current_region;
77 while (region !=
nullptr) {
83 if (i == m_current_chunk && region == m_current_region)
87 if (region->chunks[i].flags &
SHARED)
92 for (
size_t j = 0; j < pages; j++) {
102 region = region->next;
116 return allocate(0, requested_size, actual_size, flags);
129 return allocate(0, requested_size, actual_size, flags);
145 if (requested_size == 0)
152 if (address < m_next_available_address)
165 free_chunk_t* reusable_chunk = address == 0 ? find_and_remove_free_chunk(actual_size) :
nullptr;
166 if (reusable_chunk !=
nullptr) {
174 for (
size_t i = 0; i < pages; i++) {
178 if (frame !=
nullptr)
195 chunk->
size = actual_size;
196 chunk->
flags = flags;
200 return (
void*)chunk_start;
209 fill_up_to_address(address, flags,
false);
217 chunk->
size = actual_size;
218 chunk->
flags = flags;
222 m_next_available_address += actual_size;
231 for (
size_t i = 0; i < pages; i++) {
235 ASSERT(frame !=
nullptr,
"Failed to allocate frame (from current region)\n");
249void VirtualMemoryManager::new_region() {
253 ASSERT(new_region_physical !=
nullptr,
"Failed to allocate new VMM region\n");
260 new_region->next =
nullptr;
264 new_region->chunks[i].size = 0;
265 new_region->chunks[i].flags = 0;
266 new_region->chunks[i].start_address = 0;
270 if (m_current_region)
271 m_current_region->next = new_region;
273 m_current_region = new_region;
285 if (address ==
nullptr)
291 while (region !=
nullptr) {
297 if (region->chunks[i].start_address == (uintptr_t)address) {
298 chunk = ®ion->chunks[i];
304 if (chunk !=
nullptr)
308 region = region->next;
312 if (chunk ==
nullptr)
316 if (chunk->
flags & VirtualFlags::SHARED) {
320 if (resource.second->type() != resource_type_t::SHARED_MEMORY)
325 if ((
void*)shared->physical_address() != address)
355 while (region !=
nullptr) {
361 if (region->chunks[i].size != 0)
362 result += region->chunks[i].size;
366 region = region->next;
378void VirtualMemoryManager::add_free_chunk(uintptr_t start_address,
size_t size) {
382 new_chunk->start_address = start_address;
383 new_chunk->size = size;
384 new_chunk->next = m_free_chunks;
387 m_free_chunks = new_chunk;
398free_chunk_t* VirtualMemoryManager::find_and_remove_free_chunk(
size_t size) {
403 while (current !=
nullptr) {
406 if (current->
size >= size) {
409 if (previous !=
nullptr) {
412 m_free_chunks = current->
next;
422 current = current->
next;
441virtual_memory_chunk_t* VirtualMemoryManager::find_containing_chunk(
const void* start_address,
size_t size) {
445 while (region !=
nullptr) {
449 auto chunk = region->chunks[i];
450 auto chunk_start = (
void*)chunk.start_address;
451 auto chunk_end = (
void*)(chunk.start_address + chunk.size);
454 if (!(start_address >= chunk_start && start_address <= chunk_end))
458 if (!(start_address + size <= chunk_end))
461 return ®ion->chunks[i];
464 region = region->next;
478 return m_pml4_root_physical_address;
493 if (block !=
nullptr)
509 if (size == 0 || physical_address == 0)
531 for (
size_t i = 0; i < pages; i++)
555 if (!other_vmm || !start_address || size == 0)
560 size_t offset = (size_t)start_address - aligned_start;
561 size_t total_size = offset + size;
570 size_t range_pages = paged_size /
PAGE_SIZE;
573 for (
size_t i = 0; i < range_pages; i++) {
574 uintptr_t virtual_page = aligned_start + i *
PAGE_SIZE;
577 if (virtual_page +
PAGE_SIZE <= aligned_start)
581 if (virtual_page >= aligned_start + paged_size)
586 if (frame ==
nullptr)
593 return dest + offset;
605 if (!start_address || size == 0)
610 size_t offset = (size_t)start_address - aligned_start;
611 size_t total_size = offset + size;
615 auto containing_chunk = find_containing_chunk(start_address, size);
619 for (
size_t i = 0; i < chunk_pages; i++) {
620 uintptr_t virtual_page = containing_chunk->start_address + i *
PAGE_SIZE;
623 if (virtual_page +
PAGE_SIZE <= aligned_start)
627 if (virtual_page >= aligned_start + paged_size)
635 free((
void*)aligned_start,
false);
647void VirtualMemoryManager::fill_up_to_address(uintptr_t address,
size_t flags,
bool mark_used) {
653 ASSERT(address >= m_next_available_address,
"FAILED TO FILL: Address is before the next available address - 0x%x < 0x%x\n", address, m_next_available_address);
656 size_t size = address - m_next_available_address;
661 chunk->
flags = flags;
665 m_next_available_address += size;
670 for (
size_t i = 0; i < pages; i++) {
674 ASSERT(frame !=
nullptr,
"Failed to allocate frame (from fill up)\n");
694 if (m_pml4_root_address ==
nullptr)
698 return m_pml4_root_address;
static MemoryManager * s_kernel_memory_manager
The memory manager for any kernel processes and all kernel allocations.
static void * to_dm_region(uintptr_t physical_address)
Converts a physical address to a direct map region address if it is in the lower region using the hig...
static size_t align_direct_to_page(size_t size)
Aligns a address to the page size.
void unmap(virtual_address_t *virtual_address)
Unmaps a virtual address using the kernel's pml4 table.
static size_t align_to_page(size_t size)
Aligns a size to the page size. (Rounds up to the next multiple of PAGE_SIZE)
uint64_t memory_size() const
Gets total the memory size available for use (allocated or not)
static void clean_page_table(uint64_t *table)
Cleans a page table (fills it with 0 or null entries)
virtual_address_t * map(virtual_address_t *virtual_address, size_t flags)
Allocates a physical address to a virtual address.
uint64_t * pml4_root_address()
Gets the pml4 root address for the kernel.
static void * to_lower_region(uintptr_t virtual_address)
Converts a virtual address to a lower region address if it is in the higher region using the higher h...
static bool check_aligned(size_t size)
Checks if an address is aligned.
static PhysicalMemoryManager * s_current_manager
The current physical memory manager in use.
static size_t align_up_to_page(size_t size, size_t s_page_size)
Aligns a size up to the page size, given a page size to a power of 2.
static size_t size_to_frames(size_t size)
Converts a size to the number of frames.
void free_frame(void *address)
Frees a frame in the bit map.
physical_address_t * get_physical_address(virtual_address_t *virtual_address, uint64_t *pml4_root)
Gets the physical address from a virtual address (if it exists)
void * allocate_frame()
Allocates a physical page of memory, if the PMM is not initalise it will use the anon memory instead ...
Manages the virtual memory of the system and provides functions to allocate and free memory in the vi...
VirtualMemoryManager()
Construct a new Virtual Memory Manager object and set up the initial page tables (kernel mapped into ...
void * load_physical_into_address_space(uintptr_t physical_address, size_t size, size_t flags)
Load physical memory into the VMM's address space.
void free(void *address, bool reusable_pages=true)
Free a chunk of virtual memory.
void * allocate(size_t requested_size, size_t &actual_size, size_t flags)
Allocate a new chunk of virtual memory.
void * allocate(size_t size, size_t flags)
Allocate a new chunk of virtual memory.
void unload_range_from_process(const void *start_address, size_t size)
Unload a shared range of pages from this vmm.
size_t memory_used()
Returns the amount of memory used.
uint64_t * pml4_root_address_physical()
Get the physical address of the PML4 root.
~VirtualMemoryManager()
Destroy the Virtual Memory Manager object and free all used pages.
uint64_t * pml4_root_address()
Get the virtual address of the PML4 root.
void * load_range_from_process(VirtualMemoryManager *other_vmm, const void *start_address, size_t size)
Loads the pages from a virtual memory region in another vmm into this one.
void * load_shared_memory(const string &name)
Load shared memory into the VMM's address space.
static Process * current_process()
Gets the process on the currently executing core.
resources::ResourceManager resource_manager
The manger for resources used by this process.
A block memory that is mapped into multiple processes.
Resource * get_resource(uint64_t handle)
Gets a resource based on the handle id.
void close_resource(uint64_t handle, size_t flags)
Un registers the resource and then closes it.
common::Map< uint64_t, Resource * > resources()
Get the resources currently open.
Defines a Logger class for logging messages with different severity levels to multiple output streams...
void virtual_address_t
A type representing a virtual address (used for readability)
constexpr uint64_t HIGHER_HALF_DIRECT_MAP
Where the map of physical memory to higher half starts.
void physical_address_t
A type representing a physical address (used for readability)
constexpr uint64_t PAGE_SIZE
The size of a page (4KB)
@ PRESENT
The page is present in memory.
@ WRITE
Memory in this page is writable.
Defines a GlobalScheduler and Scheduler for managing processes and threads.
A chunk of memory that has been freed and is available for allocation. A node in a linked list.
size_t size
The size of the chunk's memory region in bytes.
uintptr_t start_address
The first virtual address that this chunk covers.
struct FreeChunk * next
Pointer to the next free chunk in the list (not sequential in memory)
A container for a region of virtual memory that has been allocated by the Virtual Memory Manager.
size_t flags
The flags for the memory (see VirtualFlags)
uintptr_t start_address
The first virtual address that this chunk covers.
size_t size
The size of the chunk's memory region in bytes.
Defines a VirtualMemoryManager class for managing virtual memory allocation and mapping to physical m...
struct PACKED MaxOS::memory::VirtualMemoryRegion virtual_memory_region_t
Alias for VirtualMemoryRegion struct.
@ SHARED
The memory is shared between multiple processes.
@ RESERVE
Reserve the memory but do not map any physical memory to it.
constexpr size_t CHUNKS_PER_PAGE
Number of chunks per virtual memory region (limited to fit in one page)
constexpr size_t VMM_RESERVED
The starting address for the VMM to start allocating from when in higher half (otherwise can cause co...