diff options
Diffstat (limited to 'src/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/k_page_table_base.cpp | 75 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_page_table_base.h | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_process.cpp | 6 |
3 files changed, 81 insertions, 1 deletions
diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp index 73fbda331..f01eaa164 100644 --- a/src/core/hle/kernel/k_page_table_base.cpp +++ b/src/core/hle/kernel/k_page_table_base.cpp | |||
| @@ -431,9 +431,82 @@ Result KPageTableBase::InitializeForProcess(Svc::CreateProcessFlag as_type, bool | |||
| 431 | m_memory_block_slab_manager)); | 431 | m_memory_block_slab_manager)); |
| 432 | } | 432 | } |
| 433 | 433 | ||
| 434 | Result KPageTableBase::FinalizeProcess() { | ||
| 435 | // Only process tables should be finalized. | ||
| 436 | ASSERT(!this->IsKernel()); | ||
| 437 | |||
| 438 | // HLE processes don't have memory mapped. | ||
| 439 | R_SUCCEED_IF(m_impl == nullptr); | ||
| 440 | |||
| 441 | // NOTE: Here Nintendo calls an unknown OnFinalize function. | ||
| 442 | // this->OnFinalize(); | ||
| 443 | |||
| 444 | // NOTE: Here Nintendo calls a second unknown OnFinalize function. | ||
| 445 | // this->OnFinalize2(); | ||
| 446 | |||
| 447 | // Get implementation objects. | ||
| 448 | auto& impl = this->GetImpl(); | ||
| 449 | auto& mm = m_kernel.MemoryManager(); | ||
| 450 | |||
| 451 | // Traverse, freeing all pages. | ||
| 452 | { | ||
| 453 | // Get the address space size. | ||
| 454 | const size_t as_size = this->GetAddressSpaceSize(); | ||
| 455 | |||
| 456 | // Begin the traversal. | ||
| 457 | TraversalContext context; | ||
| 458 | TraversalEntry cur_entry = { | ||
| 459 | .phys_addr = 0, | ||
| 460 | .block_size = 0, | ||
| 461 | }; | ||
| 462 | |||
| 463 | bool cur_valid = false; | ||
| 464 | TraversalEntry next_entry; | ||
| 465 | bool next_valid; | ||
| 466 | size_t tot_size = 0; | ||
| 467 | |||
| 468 | next_valid = impl.BeginTraversal(std::addressof(next_entry), std::addressof(context), | ||
| 469 | this->GetAddressSpaceStart()); | ||
| 470 | |||
| 471 | // Iterate over entries. | ||
| 472 | while (true) { | ||
| 473 | if ((!next_valid && !cur_valid) || | ||
| 474 | (next_valid && cur_valid && | ||
| 475 | next_entry.phys_addr == cur_entry.phys_addr + cur_entry.block_size)) { | ||
| 476 | cur_entry.block_size += next_entry.block_size; | ||
| 477 | } else { | ||
| 478 | if (cur_valid && IsHeapPhysicalAddressForFinalize(cur_entry.phys_addr)) { | ||
| 479 | mm.Close(cur_entry.phys_addr, cur_entry.block_size / PageSize); | ||
| 480 | } | ||
| 481 | |||
| 482 | // Update tracking variables. | ||
| 483 | tot_size += cur_entry.block_size; | ||
| 484 | cur_entry = next_entry; | ||
| 485 | cur_valid = next_valid; | ||
| 486 | } | ||
| 487 | |||
| 488 | if (cur_entry.block_size + tot_size >= as_size) { | ||
| 489 | break; | ||
| 490 | } | ||
| 491 | |||
| 492 | next_valid = | ||
| 493 | impl.ContinueTraversal(std::addressof(next_entry), std::addressof(context)); | ||
| 494 | } | ||
| 495 | |||
| 496 | // Handle the last block. | ||
| 497 | if (cur_valid && IsHeapPhysicalAddressForFinalize(cur_entry.phys_addr)) { | ||
| 498 | mm.Close(cur_entry.phys_addr, cur_entry.block_size / PageSize); | ||
| 499 | } | ||
| 500 | } | ||
| 501 | |||
| 502 | R_SUCCEED(); | ||
| 503 | } | ||
| 504 | |||
| 434 | void KPageTableBase::Finalize() { | 505 | void KPageTableBase::Finalize() { |
| 506 | this->FinalizeProcess(); | ||
| 507 | |||
| 435 | auto HostUnmapCallback = [&](KProcessAddress addr, u64 size) { | 508 | auto HostUnmapCallback = [&](KProcessAddress addr, u64 size) { |
| 436 | if (Settings::IsFastmemEnabled()) { | 509 | if (m_impl->fastmem_arena) { |
| 437 | m_system.DeviceMemory().buffer.Unmap(GetInteger(addr), size, false); | 510 | m_system.DeviceMemory().buffer.Unmap(GetInteger(addr), size, false); |
| 438 | } | 511 | } |
| 439 | }; | 512 | }; |
diff --git a/src/core/hle/kernel/k_page_table_base.h b/src/core/hle/kernel/k_page_table_base.h index 077cafc96..748419f86 100644 --- a/src/core/hle/kernel/k_page_table_base.h +++ b/src/core/hle/kernel/k_page_table_base.h | |||
| @@ -241,6 +241,7 @@ public: | |||
| 241 | KResourceLimit* resource_limit, Core::Memory::Memory& memory, | 241 | KResourceLimit* resource_limit, Core::Memory::Memory& memory, |
| 242 | KProcessAddress aslr_space_start); | 242 | KProcessAddress aslr_space_start); |
| 243 | 243 | ||
| 244 | Result FinalizeProcess(); | ||
| 244 | void Finalize(); | 245 | void Finalize(); |
| 245 | 246 | ||
| 246 | bool IsKernel() const { | 247 | bool IsKernel() const { |
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 068e71dff..ae332a550 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp | |||
| @@ -171,6 +171,12 @@ void KProcess::Finalize() { | |||
| 171 | m_resource_limit->Close(); | 171 | m_resource_limit->Close(); |
| 172 | } | 172 | } |
| 173 | 173 | ||
| 174 | // Clear expensive resources, as the destructor is not called for guest objects. | ||
| 175 | for (auto& interface : m_arm_interfaces) { | ||
| 176 | interface.reset(); | ||
| 177 | } | ||
| 178 | m_exclusive_monitor.reset(); | ||
| 179 | |||
| 174 | // Perform inherited finalization. | 180 | // Perform inherited finalization. |
| 175 | KSynchronizationObject::Finalize(); | 181 | KSynchronizationObject::Finalize(); |
| 176 | } | 182 | } |