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#include <common/macros.h>
15#include <system/multiboot.h>
16
17#include <common/spinlock.h>
18
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))
21
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)
26
27namespace MaxOS::memory {
28
29 typedef void virtual_address_t;
30 typedef void physical_address_t;
31
41 typedef enum PageFlags {
42 NONE = 0,
43 PRESENT = (1 << 0),
44 WRITE = (1 << 1),
45 USER = (1 << 2),
46 WRITE_THROUGH = (1 << 3),
47 CACHE_DISABLED = (1 << 4),
48 ACCESSED = (1 << 5),
49 DIRTY = (1 << 6),
50 HUGE_PAGE = (1 << 7),
51 GLOBAL = (1 << 8),
52 NO_EXECUTE = (1ULL << 63)
53 } page_flags_t;
54
62 typedef struct PACKED PageTableEntry {
63
64 bool present : 1;
65 bool write : 1;
66 bool user : 1;
67 bool write_through : 1;
68 bool cache_disabled : 1;
69 bool accessed : 1;
70 bool dirty : 1;
71 bool huge_page : 1;
72 bool global : 1;
73 uint8_t available : 3;
74 uint64_t physical_address : 52;
75
76 } pte_t;
77
85 typedef struct PACKED PageMapLevel {
86
87 pte_t entries[512];
88
89 } pml_t;
90
91 constexpr uint64_t PAGE_SIZE = 0x1000;
92 constexpr uint8_t ROW_BITS = 64;
93
94 constexpr uint64_t HIGHER_HALF_KERNEL_OFFSET = 0xFFFFFFFF80000000;
95 constexpr uint64_t HIGHER_HALF_MEM_OFFSET = 0xFFFF800000000000;
96 constexpr uint64_t HIGHER_HALF_MEM_RESERVED = 0x280000000;
100 PAGE_SIZE;
101
109
110 private:
111
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;
118
119 uint64_t m_kernel_start_page;
120 uint64_t m_kernel_end;
121
122 system::Multiboot* m_multiboot;
123 multiboot_mmap_entry* m_mmap;
124 multiboot_tag_mmap* m_mmap_tag;
125
126 uint64_t* m_pml4_root_address;
127 pte_t* m_pml4_root;
128
129 bool m_initialised;
130 bool m_nx_allowed;
131
132 common::Spinlock m_lock;
133
134 // Table Management
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;
138
139 static uint64_t physical_address_of_entry(pte_t* entry);
140 pte_t* get_entry(virtual_address_t* virtual_address, pml_t* pml4_root);
141 static pml_t* get_higher_half_table(uint64_t index, uint64_t index2 = 510, uint64_t index3 = 510);
142
143 void initialise_bit_map();
144
145 public:
146
147 explicit PhysicalMemoryManager(system::Multiboot* multiboot);
149
150 // Vars
151 [[nodiscard]] uint64_t memory_size() const;
152 [[nodiscard]] uint64_t memory_used() const;
153
154 // Pml4
155 uint64_t* pml4_root_address();
156 static void unmap_lower_kernel();
157
158 // Frame Management
159 void* allocate_frame();
160 void free_frame(void* address);
161
162 void* allocate_area(uint64_t start_address, size_t size);
163 void free_area(uint64_t start_address, size_t size);
164
165 // Map
166 virtual_address_t* map(virtual_address_t* virtual_address, size_t flags);
167 virtual_address_t* map(physical_address_t* physical, virtual_address_t* virtual_address, size_t flags);
168 virtual_address_t* map(physical_address_t* physical, virtual_address_t* virtual_address, size_t flags, uint64_t* pml4_root);
169 void map_area(virtual_address_t* virtual_address_start, size_t length, size_t flags);
170 void map_area(physical_address_t* physical_address_start, virtual_address_t* virtual_address_start, size_t length, size_t flags);
171 void identity_map(physical_address_t* physical_address, size_t flags);
172
173 void unmap(virtual_address_t* virtual_address);
174 void unmap(virtual_address_t* virtual_address, uint64_t* pml4_root);
175 void unmap_area(virtual_address_t* virtual_address_start, size_t length);
176
177 // Tools
178 static size_t size_to_frames(size_t size);
179 static size_t align_to_page(size_t size);
180 static size_t align_direct_to_page(size_t size);
181 static size_t align_up_to_page(size_t size, size_t s_page_size);
182 static bool check_aligned(size_t size);
183
185 inline static PhysicalMemoryManager* s_current_manager = nullptr;
186 static void clean_page_table(uint64_t* table);
187
188 void reserve(uint64_t address);
189 void reserve(uint64_t address, size_t size, const char* = "Unknown");
191
192 physical_address_t* get_physical_address(virtual_address_t* virtual_address, uint64_t* pml4_root);
193 bool is_mapped(uintptr_t physical_address, uintptr_t virtual_address, uint64_t* pml4_root);
194
195 void change_page_flags(virtual_address_t* virtual_address, size_t flags, uint64_t* pml4_root);
196
197 // Higher Half Memory Management
198 static void* to_higher_region(uintptr_t physical_address);
199 static void* to_lower_region(uintptr_t virtual_address);
200 static void* to_io_region(uintptr_t physical_address);
201 static void* to_dm_region(uintptr_t physical_address);
202 static void* from_dm_region(uintptr_t physical_address);
203 static bool in_higher_region(uintptr_t virtual_address);
204 };
205}
206
207
208#endif // MAXOS_MEMORY_PHYSICAL_H
Enables a resource to be used by only one instance at a time through locking and unlocking.
Definition spinlock.h:21
Manages the physical memory of the system such as what pages are allocated/free and mapping of virtua...
Definition physical.h:108
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:930
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:970
void unmap_area(virtual_address_t *virtual_address_start, size_t length)
Unmaps an area of virtual memory.
Definition physical.cpp:627
static size_t align_direct_to_page(size_t size)
Aligns a address to the page size.
Definition physical.cpp:767
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:915
void reserve(uint64_t address)
Reserves a physical address.
Definition physical.cpp:777
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:552
void unmap(virtual_address_t *virtual_address)
Unmaps a virtual address using the kernel's pml4 table.
Definition physical.cpp:593
static size_t align_to_page(size_t size)
Aligns a size to the page size.
Definition physical.cpp:167
uint64_t memory_size() const
Gets total the memory size available for use (allocated or not)
Definition physical.cpp:746
static void clean_page_table(uint64_t *table)
Cleans a page table (fills it with 0 or null entries)
Definition physical.cpp:639
virtual_address_t * map(virtual_address_t *virtual_address, size_t flags)
Allocates a physical address to a virtual address.
Definition physical.cpp:538
uint64_t * pml4_root_address()
Gets the pml4 root address for the kernel.
Definition physical.cpp:736
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:899
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:883
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:870
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:945
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:847
static bool check_aligned(size_t size)
Checks if an address is aligned.
Definition physical.cpp:190
static PhysicalMemoryManager * s_current_manager
The current physical memory manager in use.
Definition physical.h:185
static size_t align_up_to_page(size_t size, size_t s_page_size)
Aligns a size up to the page size.
Definition physical.cpp:179
void identity_map(physical_address_t *physical_address, size_t flags)
Maps a physical address to its virtual address counter-part.
Definition physical.cpp:582
static size_t size_to_frames(size_t size)
Converts a size to the number of frames.
Definition physical.cpp:156
void free_area(uint64_t start_address, size_t size)
Frees an area of physical memory.
Definition physical.cpp:344
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:96
static bool in_higher_region(uintptr_t virtual_address)
Checks if a virtual address is in the higher region.
Definition physical.cpp:961
uint64_t memory_used() const
Gets the memory currently used.
Definition physical.cpp:756
void free_frame(void *address)
Frees a frame in the bit map.
Definition physical.cpp:256
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:829
void * allocate_area(uint64_t start_address, size_t size)
Allocate an area of physical memory (ie reserve it)
Definition physical.cpp:275
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:200
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:97
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:29
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:96
constexpr uint64_t HIGHER_HALF_KERNEL_OFFSET
Where the kernel is mapped in higher half memory.
Definition physical.h:94
constexpr uint64_t HIGHER_HALF_MEM_OFFSET
Where higher half memory starts.
Definition physical.h:95
void physical_address_t
A type representing a physical address (used for readability)
Definition physical.h:30
constexpr uint8_t ROW_BITS
The number of bits in the bitmap row.
Definition physical.h:92
constexpr uint64_t PAGE_SIZE
The size of a page (4KB)
Definition physical.h:91
PageFlags
Flags for page table entries.
Definition physical.h:41
@ PRESENT
The page is present in memory.
Definition physical.h:43
@ GLOBAL
The page can be shared between processes.
Definition physical.h:51
@ DIRTY
This page has been written to.
Definition physical.h:49
@ USER
This page is accessible from user mode.
Definition physical.h:45
@ CACHE_DISABLED
Dont let the CPU cache this page.
Definition physical.h:47
@ NONE
No flags.
Definition physical.h:42
Defines Spinlock and BlockingLock classes for thread synchronization.
Struct for a page map level (PML4, PDPT, PD, PT)
Definition physical.h:85
Struct for a page table entry.
Definition physical.h:62
uint8_t available
Extra metadata bytes available for OS use.
Definition physical.h:73
bool user
*copydoc PageFlags::USER
Definition physical.h:66
bool present
*copydoc PageFlags::PRESENT
Definition physical.h:64
uint64_t physical_address
The address the page represents in memory.
Definition physical.h:74
bool write
*copydoc PageFlags::WRITE
Definition physical.h:65
bool cache_disabled
*copydoc PageFlags::CACHE_DISABLED
Definition physical.h:68
bool global
*copydoc PageFlags::GLOBAL
Definition physical.h:72
bool write_through
*copydoc PageFlags::WRITE_THROUGH
Definition physical.h:67
bool dirty
*copydoc PageFlags::DIRTY
Definition physical.h:70
bool accessed
*copydoc PageFlags::ACCESSED
Definition physical.h:69
bool huge_page
*copydoc PageFlags::HUGE_PAGE
Definition physical.h:71
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