summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/hle/kernel/k_page_table_base.cpp75
-rw-r--r--src/core/hle/kernel/k_page_table_base.h1
-rw-r--r--src/core/hle/kernel/k_process.cpp6
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
434Result 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
434void KPageTableBase::Finalize() { 505void 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}