| 296 | } |
| 297 | |
| 298 | auto VirtualMemory::FindPageTableEntry(void* page_dir, void* virtual_addr, |
| 299 | bool allocate) -> Expected<uint64_t*> { |
| 300 | auto* current_table = reinterpret_cast<uint64_t*>(page_dir); |
| 301 | auto vaddr = reinterpret_cast<uint64_t>(virtual_addr); |
| 302 | |
| 303 | // 遍历页表层级 |
| 304 | for (size_t level = cpu_io::virtual_memory::kPageTableLevels - 1; level > 0; |
| 305 | --level) { |
| 306 | // 获取当前级别的虚拟页号 |
| 307 | auto vpn = cpu_io::virtual_memory::GetVirtualPageNumber(vaddr, level); |
| 308 | auto* pte = ¤t_table[vpn]; |
| 309 | if (cpu_io::virtual_memory::IsPageTableEntryValid(*pte)) { |
| 310 | // 页表项有效,获取下一级页表 |
| 311 | current_table = reinterpret_cast<uint64_t*>( |
| 312 | cpu_io::virtual_memory::PageTableEntryToPhysical(*pte)); |
| 313 | } else { |
| 314 | // 页表项无效 |
| 315 | if (allocate) { |
| 316 | auto* new_table = aligned_alloc(cpu_io::virtual_memory::kPageSize, |
| 317 | cpu_io::virtual_memory::kPageSize); |
| 318 | if (new_table == nullptr) { |
| 319 | return std::unexpected(Error(ErrorCode::kVmAllocationFailed)); |
| 320 | } |
| 321 | // 清零新页表 |
| 322 | std::memset(new_table, 0, cpu_io::virtual_memory::kPageSize); |
| 323 | |
| 324 | // 设置中间页表项 |
| 325 | *pte = cpu_io::virtual_memory::PhysicalToPageTableEntry( |
| 326 | reinterpret_cast<uint64_t>(new_table), |
| 327 | cpu_io::virtual_memory::GetTableEntryPermissions()); |
| 328 | |
| 329 | current_table = reinterpret_cast<uint64_t*>(new_table); |
| 330 | } else { |
| 331 | return std::unexpected(Error(ErrorCode::kVmPageNotMapped)); |
| 332 | } |
| 333 | } |
| 334 | } |
| 335 | |
| 336 | // 返回最底层页表中的页表项 |
| 337 | auto vpn = cpu_io::virtual_memory::GetVirtualPageNumber(vaddr, 0); |
| 338 | |
| 339 | return ¤t_table[vpn]; |
| 340 | } |
nothing calls this directly
no test coverage detected