summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/kernel/k_memory_block_manager.cpp4
-rw-r--r--src/core/hle/kernel/k_memory_block_manager.h4
-rw-r--r--src/core/hle/kernel/k_page_table_base.cpp73
3 files changed, 18 insertions, 63 deletions
diff --git a/src/core/hle/kernel/k_memory_block_manager.cpp b/src/core/hle/kernel/k_memory_block_manager.cpp
index 58a1e7216..f08a6e448 100644
--- a/src/core/hle/kernel/k_memory_block_manager.cpp
+++ b/src/core/hle/kernel/k_memory_block_manager.cpp
@@ -28,14 +28,14 @@ Result KMemoryBlockManager::Initialize(KProcessAddress st, KProcessAddress nd,
28} 28}
29 29
30void KMemoryBlockManager::Finalize(KMemoryBlockSlabManager* slab_manager, 30void KMemoryBlockManager::Finalize(KMemoryBlockSlabManager* slab_manager,
31 HostUnmapCallback&& host_unmap_callback) { 31 BlockCallback&& block_callback) {
32 // Erase every block until we have none left. 32 // Erase every block until we have none left.
33 auto it = m_memory_block_tree.begin(); 33 auto it = m_memory_block_tree.begin();
34 while (it != m_memory_block_tree.end()) { 34 while (it != m_memory_block_tree.end()) {
35 KMemoryBlock* block = std::addressof(*it); 35 KMemoryBlock* block = std::addressof(*it);
36 it = m_memory_block_tree.erase(it); 36 it = m_memory_block_tree.erase(it);
37 block_callback(block->GetAddress(), block->GetSize());
37 slab_manager->Free(block); 38 slab_manager->Free(block);
38 host_unmap_callback(block->GetAddress(), block->GetSize());
39 } 39 }
40 40
41 ASSERT(m_memory_block_tree.empty()); 41 ASSERT(m_memory_block_tree.empty());
diff --git a/src/core/hle/kernel/k_memory_block_manager.h b/src/core/hle/kernel/k_memory_block_manager.h
index cb7b6f430..377628504 100644
--- a/src/core/hle/kernel/k_memory_block_manager.h
+++ b/src/core/hle/kernel/k_memory_block_manager.h
@@ -85,11 +85,11 @@ public:
85public: 85public:
86 KMemoryBlockManager(); 86 KMemoryBlockManager();
87 87
88 using HostUnmapCallback = std::function<void(Common::ProcessAddress, u64)>; 88 using BlockCallback = std::function<void(Common::ProcessAddress, u64)>;
89 89
90 Result Initialize(KProcessAddress st, KProcessAddress nd, 90 Result Initialize(KProcessAddress st, KProcessAddress nd,
91 KMemoryBlockSlabManager* slab_manager); 91 KMemoryBlockSlabManager* slab_manager);
92 void Finalize(KMemoryBlockSlabManager* slab_manager, HostUnmapCallback&& host_unmap_callback); 92 void Finalize(KMemoryBlockSlabManager* slab_manager, BlockCallback&& block_callback);
93 93
94 iterator end() { 94 iterator end() {
95 return m_memory_block_tree.end(); 95 return m_memory_block_tree.end();
diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp
index f01eaa164..3f0a39d33 100644
--- a/src/core/hle/kernel/k_page_table_base.cpp
+++ b/src/core/hle/kernel/k_page_table_base.cpp
@@ -435,69 +435,14 @@ Result KPageTableBase::FinalizeProcess() {
435 // Only process tables should be finalized. 435 // Only process tables should be finalized.
436 ASSERT(!this->IsKernel()); 436 ASSERT(!this->IsKernel());
437 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. 438 // NOTE: Here Nintendo calls an unknown OnFinalize function.
442 // this->OnFinalize(); 439 // this->OnFinalize();
443 440
444 // NOTE: Here Nintendo calls a second unknown OnFinalize function. 441 // NOTE: Here Nintendo calls a second unknown OnFinalize function.
445 // this->OnFinalize2(); 442 // this->OnFinalize2();
446 443
447 // Get implementation objects. 444 // NOTE: Here Nintendo does a page table walk to discover heap pages to free.
448 auto& impl = this->GetImpl(); 445 // We will use the block manager finalization below to free them.
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 446
502 R_SUCCEED(); 447 R_SUCCEED();
503} 448}
@@ -505,14 +450,24 @@ Result KPageTableBase::FinalizeProcess() {
505void KPageTableBase::Finalize() { 450void KPageTableBase::Finalize() {
506 this->FinalizeProcess(); 451 this->FinalizeProcess();
507 452
508 auto HostUnmapCallback = [&](KProcessAddress addr, u64 size) { 453 auto BlockCallback = [&](KProcessAddress addr, u64 size) {
509 if (m_impl->fastmem_arena) { 454 if (m_impl->fastmem_arena) {
510 m_system.DeviceMemory().buffer.Unmap(GetInteger(addr), size, false); 455 m_system.DeviceMemory().buffer.Unmap(GetInteger(addr), size, false);
511 } 456 }
457
458 // Get physical pages.
459 KPageGroup pg(m_kernel, m_block_info_manager);
460 this->MakePageGroup(pg, addr, size / PageSize);
461
462 // Free the pages.
463 pg.CloseAndReset();
512 }; 464 };
513 465
514 // Finalize memory blocks. 466 // Finalize memory blocks.
515 m_memory_block_manager.Finalize(m_memory_block_slab_manager, std::move(HostUnmapCallback)); 467 {
468 KScopedLightLock lk(m_general_lock);
469 m_memory_block_manager.Finalize(m_memory_block_slab_manager, std::move(BlockCallback));
470 }
516 471
517 // Free any unsafe mapped memory. 472 // Free any unsafe mapped memory.
518 if (m_mapped_unsafe_physical_memory) { 473 if (m_mapped_unsafe_physical_memory) {