| 242 | } |
| 243 | |
| 244 | auto VirtualMemory::RecursiveClonePageTable(uint64_t* src_table, |
| 245 | uint64_t* dst_table, size_t level, |
| 246 | bool copy_mappings) |
| 247 | -> Expected<void> { |
| 248 | assert(src_table != nullptr && "RecursiveClonePageTable: src_table is null"); |
| 249 | assert(dst_table != nullptr && "RecursiveClonePageTable: dst_table is null"); |
| 250 | |
| 251 | for (size_t i = 0; i < kEntriesPerTable; ++i) { |
| 252 | uint64_t src_pte = src_table[i]; |
| 253 | if (!cpu_io::virtual_memory::IsPageTableEntryValid(src_pte)) { |
| 254 | continue; |
| 255 | } |
| 256 | |
| 257 | if (level > 0) { |
| 258 | // 非最后一级,需要递归复制子页表 |
| 259 | auto src_pa = cpu_io::virtual_memory::PageTableEntryToPhysical(src_pte); |
| 260 | auto* src_next_table = reinterpret_cast<uint64_t*>(src_pa); |
| 261 | |
| 262 | // 分配新的子页表 |
| 263 | auto* dst_next_table = aligned_alloc(cpu_io::virtual_memory::kPageSize, |
| 264 | cpu_io::virtual_memory::kPageSize); |
| 265 | if (dst_next_table == nullptr) { |
| 266 | return std::unexpected(Error(ErrorCode::kVmAllocationFailed)); |
| 267 | } |
| 268 | |
| 269 | // 清零新页表 |
| 270 | std::memset(dst_next_table, 0, cpu_io::virtual_memory::kPageSize); |
| 271 | |
| 272 | // 递归复制子页表 |
| 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()) { |
| 277 | aligned_free(dst_next_table); |
| 278 | return std::unexpected(result.error()); |
| 279 | } |
| 280 | |
| 281 | // 设置目标页表项指向新的子页表 |
| 282 | dst_table[i] = cpu_io::virtual_memory::PhysicalToPageTableEntry( |
| 283 | reinterpret_cast<uint64_t>(dst_next_table), |
| 284 | cpu_io::virtual_memory::GetTableEntryPermissions()); |
| 285 | } else { |
| 286 | // 最后一级页表 |
| 287 | if (copy_mappings) { |
| 288 | // 直接复制页表项(共享物理页) |
| 289 | dst_table[i] = src_pte; |
| 290 | } |
| 291 | // 如果不复制映射,保持目标页表项为 0 |
| 292 | } |
| 293 | } |
| 294 | |
| 295 | return {}; |
| 296 | } |
| 297 | |
| 298 | auto VirtualMemory::FindPageTableEntry(void* page_dir, void* virtual_addr, |
| 299 | bool allocate) -> Expected<uint64_t*> { |
nothing calls this directly
no test coverage detected