26 "Failed to allocate kernel page directory");
32 const auto& basic_info = BasicInfoSingleton::instance();
35 MapMMIO(basic_info.physical_memory_addr, basic_info.physical_memory_size)
37 klog::Err(
"Failed to map kernel memory: {}", err.message());
44 klog::Info(
"Kernel memory mapped from {:#X} to {:#X}",
45 basic_info.physical_memory_addr,
46 basic_info.physical_memory_addr + basic_info.physical_memory_size);
63 for (uint64_t addr = start_page; addr < end_page;
65 auto result = MapPage(kernel_page_dir_,
reinterpret_cast<void*
>(addr),
66 reinterpret_cast<void*
>(addr), flags);
67 if (!result.has_value()) {
68 return std::unexpected(result.error());
71 return reinterpret_cast<void*
>(phys_addr);
75 void* physical_addr, uint32_t flags)
77 assert(page_dir !=
nullptr &&
"MapPage: page_dir is null");
80 auto pte_result = FindPageTableEntry(page_dir, virtual_addr,
true);
81 if (!pte_result.has_value()) {
85 auto pte = pte_result.value();
91 if (existing_pa ==
reinterpret_cast<uint64_t
>(physical_addr) &&
95 "MapPage: duplicate va = {:#x}, pa = {:#X}, flags = {:#X}, skip",
96 static_cast<uint64_t
>(
reinterpret_cast<uintptr_t
>(virtual_addr)),
97 static_cast<uint64_t
>(existing_pa),
static_cast<uint64_t
>(flags));
102 "MapPage: remap va = {:#x} from pa = {:#X} to pa = {:#x}",
103 static_cast<uint64_t
>(
reinterpret_cast<uintptr_t
>(virtual_addr)),
104 static_cast<uint64_t
>(existing_pa),
105 static_cast<uint64_t
>(
reinterpret_cast<uintptr_t
>(physical_addr)));
110 reinterpret_cast<uint64_t
>(physical_addr), flags);
119 assert(page_dir !=
nullptr &&
"UnmapPage: page_dir is null");
121 auto pte_result = FindPageTableEntry(page_dir, virtual_addr,
false);
122 if (!pte_result.has_value()) {
126 auto pte = pte_result.value();
143 assert(page_dir !=
nullptr &&
"GetMapping: page_dir is null");
145 auto pte_result = FindPageTableEntry(page_dir, virtual_addr,
false);
146 if (!pte_result.has_value()) {
150 auto pte = pte_result.value();
156 return reinterpret_cast<void*
>(
162 if (page_dir ==
nullptr) {
167 RecursiveFreePageTable(
reinterpret_cast<uint64_t*
>(page_dir),
174 klog::Debug(
"Destroyed page directory at address: {:#x}",
175 static_cast<uint64_t
>(
reinterpret_cast<uintptr_t
>(page_dir)));
180 assert(src_page_dir !=
nullptr &&
181 "ClonePageDirectory: source page directory is nullptr");
186 if (dst_page_dir ==
nullptr) {
194 auto result = RecursiveClonePageTable(
195 reinterpret_cast<uint64_t*
>(src_page_dir),
196 reinterpret_cast<uint64_t*
>(dst_page_dir),
198 if (!result.has_value()) {
200 DestroyPageDirectory(dst_page_dir,
false);
201 return std::unexpected(result.error());
204 klog::Debug(
"Cloned page directory from {:#x} to {:#x}",
205 static_cast<uint64_t
>(
reinterpret_cast<uintptr_t
>(src_page_dir)),
206 static_cast<uint64_t
>(
reinterpret_cast<uintptr_t
>(dst_page_dir)));
211 bool free_pages) ->
void {
212 if (table ==
nullptr) {
217 for (
size_t i = 0; i < kEntriesPerTable; ++i) {
218 uint64_t pte = table[i];
227 RecursiveFreePageTable(
reinterpret_cast<uint64_t*
>(pa), level - 1,
229 }
else if (free_pages) {
245 uint64_t* dst_table,
size_t level,
248 assert(src_table !=
nullptr &&
"RecursiveClonePageTable: src_table is null");
249 assert(dst_table !=
nullptr &&
"RecursiveClonePageTable: dst_table is null");
251 for (
size_t i = 0; i < kEntriesPerTable; ++i) {
252 uint64_t src_pte = src_table[i];
260 auto* src_next_table =
reinterpret_cast<uint64_t*
>(src_pa);
265 if (dst_next_table ==
nullptr) {
273 auto result = RecursiveClonePageTable(
274 src_next_table,
reinterpret_cast<uint64_t*
>(dst_next_table),
275 level - 1, copy_mappings);
276 if (!result.has_value()) {
278 return std::unexpected(result.error());
283 reinterpret_cast<uint64_t
>(dst_next_table),
289 dst_table[i] = src_pte;
300 auto* current_table =
reinterpret_cast<uint64_t*
>(page_dir);
301 auto vaddr =
reinterpret_cast<uint64_t
>(virtual_addr);
308 auto* pte = ¤t_table[vpn];
311 current_table =
reinterpret_cast<uint64_t*
>(
318 if (new_table ==
nullptr) {
326 reinterpret_cast<uint64_t
>(new_table),
329 current_table =
reinterpret_cast<uint64_t*
>(new_table);
339 return ¤t_table[vpn];
auto MapMMIO(uint64_t phys_addr, size_t size, uint32_t flags=cpu_io::virtual_memory::GetKernelPagePermissions()) -> Expected< void * >
映射设备内存 (MMIO)
auto DestroyPageDirectory(void *page_dir, bool free_pages=false) -> void
回收页表,释放所有映射和子页表
auto GetMapping(void *page_dir, void *virtual_addr) -> Expected< void * >
获取虚拟地址对应的物理地址映射
auto InitCurrentCore() const -> void
初始化当前核心的页表
auto FindPageTableEntry(void *page_dir, void *virtual_addr, bool allocate=false) -> Expected< uint64_t * >
在页表中查找虚拟地址对应的页表项
auto RecursiveFreePageTable(uint64_t *table, size_t level, bool free_pages) -> void
递归释放页表
auto MapPage(void *page_dir, void *virtual_addr, void *physical_addr, uint32_t flags) -> Expected< void >
映射单个页面
auto RecursiveClonePageTable(uint64_t *src_table, uint64_t *dst_table, size_t level, bool copy_mappings) -> Expected< void >
递归复制页表
auto ClonePageDirectory(void *src_page_dir, bool copy_mappings=true) -> Expected< void * >
复制页表
auto UnmapPage(void *page_dir, void *virtual_addr) -> Expected< void >
取消映射单个页面
std::expected< T, Error > Expected
std::expected 别名模板
static constexpr size_t kPageSize
void SetPageDirectory(uint64_t pd)
static constexpr size_t kPteAttributeBits
auto GetVirtualPageNumber(uint64_t virtual_addr, size_t level) -> uint64_t
auto PageTableEntryToPhysical(uint64_t pte) -> uint64_t
auto PageAlign(uint64_t addr) -> uint64_t
auto IsPageTableEntryValid(uint64_t pte) -> bool
auto GetTableEntryPermissions() -> uint64_t
static constexpr size_t kPageTableLevels
auto PhysicalToPageTableEntry(uint64_t physical_addr, uint64_t flags) -> uint64_t
auto PageAlignUp(uint64_t addr) -> uint64_t
auto Err(etl::format_string< Args... > fmt, Args &&... args) -> void
以 ERROR 级别记录日志
auto Info(etl::format_string< Args... > fmt, Args &&... args) -> void
以 INFO 级别记录日志
auto Debug(etl::format_string< Args... > fmt, Args &&... args) -> void
以 DEBUG 级别记录日志(SIMPLEKERNEL_MIN_LOG_LEVEL > 0 时编译期消除)
auto Warn(etl::format_string< Args... > fmt, Args &&... args) -> void
以 WARN 级别记录日志
void aligned_free(void *ptr)
void * aligned_alloc(size_t alignment, size_t size)