Max OS 0.3
Loading...
Searching...
No Matches
physical.h
Go to the documentation of this file.
1
9#ifndef MAXOS_MEMORY_PHYSICAL_H
10#define MAXOS_MEMORY_PHYSICAL_H
11
12#include <cstdint>
13#include <cstddef>
14
15#include <libcommon/macros.h>
16#include <libcommon/spinlock.h>
17
18#include <system/multiboot.h>
19
20#define ENTRIES_TO_ADDRESS(pml4, pdpr, pd, pt)((pml4 << 39) | (pdpr << 30) | (pd << 21) | (pt << 12))
21#define PMLX_GET_INDEX(ADDR, LEVEL) (((uint64_t)ADDR & ((uint64_t)0x1ff << (12 + LEVEL * 9))) >> (12 + LEVEL * 9))
22
23#define PML4_GET_INDEX(ADDR) PMLX_GET_INDEX(ADDR, 3)
24#define PML3_GET_INDEX(ADDR) PMLX_GET_INDEX(ADDR, 2)
25#define PML2_GET_INDEX(ADDR) PMLX_GET_INDEX(ADDR, 1)
26#define PML1_GET_INDEX(ADDR) PMLX_GET_INDEX(ADDR, 0)
27
28namespace MaxOS::memory {
29
30 typedef void virtual_address_t;
31 typedef void physical_address_t;
32
42 typedef enum PageFlags {
43 NONE = 0,
44 PRESENT = (1 << 0),
45 WRITE = (1 << 1),
46 USER = (1 << 2),
47 WRITE_THROUGH = (1 << 3),
48 CACHE_DISABLED = (1 << 4),
49 ACCESSED = (1 << 5),
50 DIRTY = (1 << 6),
51 HUGE_PAGE = (1 << 7),
52 GLOBAL = (1 << 8),
53 NO_EXECUTE = (1ULL << 63)
54 } page_flags_t;
55
63 typedef struct PACKED PageTableEntry {
64
65 bool present: 1;
66 bool write: 1;
67 bool user: 1;
68 bool write_through: 1;
70 bool accessed: 1;
71 bool dirty: 1;
72 bool huge_page: 1;
73 bool global: 1;
74 uint8_t available: 3;
75 uint64_t physical_address: 52;
76
77 } pte_t;
78
86 typedef struct PACKED PageMapLevel {
87
88 pte_t entries[512];
89
90 } pml_t;
91
92 constexpr uint64_t PAGE_SIZE = 0x1000;
93 constexpr uint8_t ROW_BITS = 64;
94
95 constexpr uint64_t HIGHER_HALF_KERNEL_OFFSET = 0xFFFFFFFF80000000;
96 constexpr uint64_t HIGHER_HALF_MEM_OFFSET = 0xFFFF800000000000;
97 constexpr uint64_t HIGHER_HALF_MEM_RESERVED = 0x280000000;
100
108 private:
109
110 uint64_t* m_bit_map = nullptr;
111 uint32_t m_total_entries;
112 uint32_t m_bitmap_size;
113 uint32_t m_used_frames = 0;
114 uint32_t m_setup_frames = 0;
115 uint64_t m_memory_size;
116
117 uint64_t m_kernel_start_page;
118 uint64_t m_kernel_end;
119
120 system::Multiboot* m_multiboot;
121 multiboot_mmap_entry* m_mmap;
122 multiboot_tag_mmap* m_mmap_tag;
123
124 uint64_t* m_pml4_root_address;
125 pte_t* m_pml4_root;
126
127 bool m_initialised;
128 bool m_nx_allowed;
129
130 common::Spinlock m_lock;
131
132 // Table Management
133 pml_t* get_or_create_table(pml_t* table, size_t index, size_t flags);
134 pml_t* get_and_create_table(pml_t* parent_table, uint64_t table_index, pml_t* table);
135 [[nodiscard]] pte_t create_page_table_entry(uintptr_t address, size_t flags) const;
136
137 static uint64_t physical_address_of_entry(pte_t* entry);
138 pte_t* get_entry(virtual_address_t* virtual_address, pml_t* pml4_root);
139 static pml_t* get_higher_half_table(uint64_t index, uint64_t index2 = 510, uint64_t index3 = 510);
140
141 void initialise_bit_map();
142
143 public:
144
145 explicit PhysicalMemoryManager(system::Multiboot* multiboot);
147
148 // Vars
149 [[nodiscard]] uint64_t memory_size() const;
150 [[nodiscard]] uint64_t memory_used() const;
151
152 // Pml4
153 uint64_t* pml4_root_address();
154 static void unmap_lower_kernel();
155
156 // Frame Management
157 void* allocate_frame();
158 void free_frame(void* address);
159
160 void* allocate_area(uint64_t start_address, size_t size);
161 void free_area(uint64_t start_address, size_t size);
162
163 // Map
164 virtual_address_t* map(virtual_address_t* virtual_address, size_t flags);
165 virtual_address_t* map(physical_address_t* physical, virtual_address_t* virtual_address, size_t flags);
166 virtual_address_t* map(physical_address_t* physical, virtual_address_t* virtual_address, size_t flags, uint64_t* pml4_root);
167 void map_area(virtual_address_t* virtual_address_start, size_t length, size_t flags);
168 void map_area(physical_address_t* physical_address_start, virtual_address_t* virtual_address_start, size_t length, size_t flags);
169 void identity_map(physical_address_t* physical_address, size_t flags);
170
171 void unmap(virtual_address_t* virtual_address);
172 void unmap(virtual_address_t* virtual_address, uint64_t* pml4_root);
173 void unmap_area(virtual_address_t* virtual_address_start, size_t length);
174
175 // Tools
176 static size_t size_to_frames(size_t size);
177 static size_t align_to_page(size_t size);
178 static size_t align_direct_to_page(size_t size);
179 static size_t align_up_to_page(size_t size, size_t s_page_size);
180 static bool check_aligned(size_t size);
181
183 inline static PhysicalMemoryManager* s_current_manager = nullptr;
184 static void clean_page_table(uint64_t* table);
185
186 void reserve(uint64_t address);
187 void reserve(uint64_t address, size_t size, const char* = "Unknown");
189
190 physical_address_t* get_physical_address(virtual_address_t* virtual_address, uint64_t* pml4_root);
191 bool is_mapped(uintptr_t physical_address, uintptr_t virtual_address, uint64_t* pml4_root);
192
193 void change_page_flags(virtual_address_t* virtual_address, size_t flags, uint64_t* pml4_root);
194
195 // Higher Half Memory Management
196 static void* to_higher_region(uintptr_t physical_address);
197 static void* to_lower_region(uintptr_t virtual_address);
198 static void* to_io_region(uintptr_t physical_address);
199 static void* to_dm_region(uintptr_t physical_address);
200 static void* from_dm_region(uintptr_t physical_address);
201 static bool in_higher_region(uintptr_t virtual_address);
202 };
203}
204
205
206#endif // MAXOS_MEMORY_PHYSICAL_H
Manages the physical memory of the system such as what pages are allocated/free and mapping of virtua...
Definition physical.h:107
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...
Definition physical.cpp:929
static void unmap_lower_kernel()
Unmaps the kernel physical memory from the lower half that was set up during the kernel boot.
Definition physical.cpp:969
void unmap_area(virtual_address_t *virtual_address_start, size_t length)
Unmaps an area of virtual memory.
Definition physical.cpp:624
static size_t align_direct_to_page(size_t size)
Aligns a address to the page size.
Definition physical.cpp:764
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...
Definition physical.cpp:914
void reserve(uint64_t address)
Reserves a physical address.
Definition physical.cpp:774
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.
Definition physical.cpp:549
void unmap(virtual_address_t *virtual_address)
Unmaps a virtual address using the kernel's pml4 table.
Definition physical.cpp:590
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)
Definition physical.cpp:155
uint64_t memory_size() const
Gets total the memory size available for use (allocated or not)
Definition physical.cpp:743
static void clean_page_table(uint64_t *table)
Cleans a page table (fills it with 0 or null entries)
Definition physical.cpp:636
virtual_address_t * map(virtual_address_t *virtual_address, size_t flags)
Allocates a physical address to a virtual address.
Definition physical.cpp:535
uint64_t * pml4_root_address()
Gets the pml4 root address for the kernel.
Definition physical.cpp:733
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...
Definition physical.cpp:898
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 ...
Definition physical.cpp:882
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.
Definition physical.cpp:869
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...
Definition physical.cpp:944
void change_page_flags(virtual_address_t *virtual_address, size_t flags, uint64_t *pml4_root)
Changes the flags of a page.
Definition physical.cpp:846
static bool check_aligned(size_t size)
Checks if an address is aligned.
Definition physical.cpp:178
static PhysicalMemoryManager * s_current_manager
The current physical memory manager in use.
Definition physical.h:183
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.
Definition physical.cpp:167
void identity_map(physical_address_t *physical_address, size_t flags)
Maps a physical address to its virtual address counter-part.
Definition physical.cpp:579
static size_t size_to_frames(size_t size)
Converts a size to the number of frames.
Definition physical.cpp:144
void free_area(uint64_t start_address, size_t size)
Frees an area of physical memory.
Definition physical.cpp:341
void reserve_kernel_regions(system::Multiboot *multiboot)
Reserves the kernel, multiboot modules, mmap regions and higher half mapping regions in the physical ...
Definition physical.cpp:89
static bool in_higher_region(uintptr_t virtual_address)
Checks if a virtual address is in the higher region.
Definition physical.cpp:960
uint64_t memory_used() const
Gets the memory currently used.
Definition physical.cpp:753
void free_frame(void *address)
Frees a frame in the bit map.
Definition physical.cpp:250
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)
Definition physical.cpp:828
void * allocate_area(uint64_t start_address, size_t size)
Allocate an area of physical memory (ie reserve it)
Definition physical.cpp:270
void * allocate_frame()
Allocates a physical page of memory, if the PMM is not initalise it will use the anon memory instead ...
Definition physical.cpp:188
Parses and provides access to Multiboot 2 information.
Definition multiboot.h:518
constexpr uint64_t HIGHER_HALF_OFFSET
Where higher half memory usable space starts.
Definition physical.h:98
struct PACKED MaxOS::memory::PageMapLevel pml_t
Alias for PageMapLevel struct.
void virtual_address_t
A type representing a virtual address (used for readability)
Definition physical.h:30
constexpr uint64_t HIGHER_HALF_DIRECT_MAP
Where the map of physical memory to higher half starts.
Definition physical.h:99
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)
Definition physical.h:97
constexpr uint64_t HIGHER_HALF_KERNEL_OFFSET
Where the kernel is mapped in higher half memory.
Definition physical.h:95
constexpr uint64_t HIGHER_HALF_MEM_OFFSET
Where higher half memory starts.
Definition physical.h:96
void physical_address_t
A type representing a physical address (used for readability)
Definition physical.h:31
constexpr uint8_t ROW_BITS
The number of bits in the bitmap row.
Definition physical.h:93
constexpr uint64_t PAGE_SIZE
The size of a page (4KB)
Definition physical.h:92
PageFlags
Flags for page table entries.
Definition physical.h:42
@ PRESENT
The page is present in memory.
Definition physical.h:44
@ GLOBAL
The page can be shared between processes.
Definition physical.h:52
@ DIRTY
This page has been written to.
Definition physical.h:50
@ USER
This page is accessible from user mode.
Definition physical.h:46
@ CACHE_DISABLED
Dont let the CPU cache this page.
Definition physical.h:48
@ NONE
No flags.
Definition physical.h:43
Struct for a page map level (PML4, PDPT, PD, PT)
Definition physical.h:86
Struct for a page table entry.
Definition physical.h:63
uint8_t available
Extra metadata bytes available for OS use.
Definition physical.h:74
bool user
*copydoc PageFlags::USER
Definition physical.h:67
bool present
*copydoc PageFlags::PRESENT
Definition physical.h:65
uint64_t physical_address
The address the page represents in memory.
Definition physical.h:75
bool write
*copydoc PageFlags::WRITE
Definition physical.h:66
bool cache_disabled
*copydoc PageFlags::CACHE_DISABLED
Definition physical.h:69
bool global
*copydoc PageFlags::GLOBAL
Definition physical.h:73
bool write_through
*copydoc PageFlags::WRITE_THROUGH
Definition physical.h:68
bool dirty
*copydoc PageFlags::DIRTY
Definition physical.h:71
bool accessed
*copydoc PageFlags::ACCESSED
Definition physical.h:70
bool huge_page
*copydoc PageFlags::HUGE_PAGE
Definition physical.h:72
An entry in the memory map containing information about a region of memory.
Definition multiboot.h:222
A tag containing the collection of memory map entries that outline the memory layout.
Definition multiboot.h:288