9#ifndef MAXOS_MEMORY_PHYSICAL_H
10#define MAXOS_MEMORY_PHYSICAL_H
14#include <common/macros.h>
15#include <system/multiboot.h>
19#define ENTRIES_TO_ADDRESS(pml4, pdpr, pd, pt)((pml4 << 39) | (pdpr << 30) | (pd << 21) | (pt << 12))
20#define PMLX_GET_INDEX(ADDR, LEVEL) (((uint64_t)ADDR & ((uint64_t)0x1ff << (12 + LEVEL * 9))) >> (12 + LEVEL * 9))
22#define PML4_GET_INDEX(ADDR) PMLX_GET_INDEX(ADDR, 3)
23#define PML3_GET_INDEX(ADDR) PMLX_GET_INDEX(ADDR, 2)
24#define PML2_GET_INDEX(ADDR) PMLX_GET_INDEX(ADDR, 1)
25#define PML1_GET_INDEX(ADDR) PMLX_GET_INDEX(ADDR, 0)
27namespace MaxOS::memory {
46 WRITE_THROUGH = (1 << 3),
52 NO_EXECUTE = (1ULL << 63)
112 uint64_t* m_bit_map =
nullptr;
113 uint32_t m_total_entries;
114 uint32_t m_bitmap_size;
115 uint32_t m_used_frames = 0;
116 uint32_t m_setup_frames = 0;
117 uint64_t m_memory_size;
119 uint64_t m_kernel_start_page;
120 uint64_t m_kernel_end;
126 uint64_t* m_pml4_root_address;
135 pml_t* get_or_create_table(
pml_t* table,
size_t index,
size_t flags);
136 pml_t* get_and_create_table(
pml_t* parent_table, uint64_t table_index,
pml_t* table);
137 [[nodiscard]]
pte_t create_page_table_entry(uintptr_t address,
size_t flags)
const;
139 static uint64_t physical_address_of_entry(
pte_t* entry);
141 static pml_t* get_higher_half_table(uint64_t index, uint64_t index2 = 510, uint64_t index3 = 510);
143 void initialise_bit_map();
163 void free_area(uint64_t start_address,
size_t size);
188 void reserve(uint64_t address);
189 void reserve(uint64_t address,
size_t size,
const char* =
"Unknown");
193 bool is_mapped(uintptr_t physical_address, uintptr_t virtual_address, uint64_t* pml4_root);
Enables a resource to be used by only one instance at a time through locking and unlocking.
Manages the physical memory of the system such as what pages are allocated/free and mapping of virtua...
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 void unmap_lower_kernel()
Unmaps the kernel physical memory from the lower half that was set up during the kernel boot.
void unmap_area(virtual_address_t *virtual_address_start, size_t length)
Unmaps an area of virtual memory.
static size_t align_direct_to_page(size_t size)
Aligns a address to the page size.
static void * to_io_region(uintptr_t physical_address)
Converts a physical address to an IO region address if it is in the lower region using the higher hal...
void reserve(uint64_t address)
Reserves a physical address.
void map_area(virtual_address_t *virtual_address_start, size_t length, size_t flags)
Allocates a new area physical memory to a area virtual address.
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.
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 void * to_higher_region(uintptr_t physical_address)
Converts a physical address to a higher region address if it is in the lower region using the higher ...
bool is_mapped(uintptr_t physical_address, uintptr_t virtual_address, uint64_t *pml4_root)
Checks if a physical address is mapped to a virtual address.
static void * from_dm_region(uintptr_t physical_address)
Converts a direct map region address to a physical address if it is in the higher region using the hi...
void change_page_flags(virtual_address_t *virtual_address, size_t flags, uint64_t *pml4_root)
Changes the flags of a page.
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.
void identity_map(physical_address_t *physical_address, size_t flags)
Maps a physical address to its virtual address counter-part.
static size_t size_to_frames(size_t size)
Converts a size to the number of frames.
void free_area(uint64_t start_address, size_t size)
Frees an area of physical memory.
void reserve_kernel_regions(system::Multiboot *multiboot)
Reserves the kernel, multiboot modules, mmap regions and higher half mapping regions in the physical ...
static bool in_higher_region(uintptr_t virtual_address)
Checks if a virtual address is in the higher region.
uint64_t memory_used() const
Gets the memory currently used.
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_area(uint64_t start_address, size_t size)
Allocate an area of physical memory (ie reserve it)
void * allocate_frame()
Allocates a physical page of memory, if the PMM is not initalise it will use the anon memory instead ...
Parses and provides access to Multiboot 2 information.
constexpr uint64_t HIGHER_HALF_OFFSET
Where higher half memory usable space starts.
struct PACKED MaxOS::memory::PageMapLevel pml_t
Alias for PageMapLevel struct.
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.
struct PACKED MaxOS::memory::PageTableEntry pte_t
Alias for PageTableEntry struct.
constexpr uint64_t HIGHER_HALF_MEM_RESERVED
Reserved higher half memory for kernel use (10GB)
constexpr uint64_t HIGHER_HALF_KERNEL_OFFSET
Where the kernel is mapped in higher half memory.
constexpr uint64_t HIGHER_HALF_MEM_OFFSET
Where higher half memory starts.
void physical_address_t
A type representing a physical address (used for readability)
constexpr uint8_t ROW_BITS
The number of bits in the bitmap row.
constexpr uint64_t PAGE_SIZE
The size of a page (4KB)
PageFlags
Flags for page table entries.
@ PRESENT
The page is present in memory.
@ GLOBAL
The page can be shared between processes.
@ DIRTY
This page has been written to.
@ USER
This page is accessible from user mode.
@ CACHE_DISABLED
Dont let the CPU cache this page.
Defines Spinlock and BlockingLock classes for thread synchronization.
Struct for a page map level (PML4, PDPT, PD, PT)
Struct for a page table entry.
uint8_t available
Extra metadata bytes available for OS use.
bool user
*copydoc PageFlags::USER
bool present
*copydoc PageFlags::PRESENT
uint64_t physical_address
The address the page represents in memory.
bool write
*copydoc PageFlags::WRITE
bool cache_disabled
*copydoc PageFlags::CACHE_DISABLED
bool global
*copydoc PageFlags::GLOBAL
bool write_through
*copydoc PageFlags::WRITE_THROUGH
bool dirty
*copydoc PageFlags::DIRTY
bool accessed
*copydoc PageFlags::ACCESSED
bool huge_page
*copydoc PageFlags::HUGE_PAGE
An entry in the memory map containing information about a region of memory.
A tag containing the collection of memory map entries that outline the memory layout.