aboutsummaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/k_memory_block.h14
-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.cpp46
-rw-r--r--src/core/hle/kernel/k_page_table_base.h1
-rw-r--r--src/core/hle/kernel/k_process.cpp10
-rw-r--r--src/core/hle/kernel/k_transfer_memory.cpp8
-rw-r--r--src/core/hle/kernel/kernel.cpp31
-rw-r--r--src/core/hle/kernel/kernel.h6
-rw-r--r--src/core/hle/kernel/svc/svc_process.cpp8
-rw-r--r--src/core/hle/kernel/svc/svc_transfer_memory.cpp4
-rw-r--r--src/core/hle/kernel/svc_types.h4
12 files changed, 102 insertions, 38 deletions
diff --git a/src/core/hle/kernel/k_memory_block.h b/src/core/hle/kernel/k_memory_block.h
index ef3f61321..d2b7e9a66 100644
--- a/src/core/hle/kernel/k_memory_block.h
+++ b/src/core/hle/kernel/k_memory_block.h
@@ -81,12 +81,12 @@ enum class KMemoryState : u32 {
ThreadLocal = static_cast<u32>(Svc::MemoryState::ThreadLocal) | FlagLinearMapped,
- Transfered = static_cast<u32>(Svc::MemoryState::Transfered) | FlagsMisc |
- FlagCanAlignedDeviceMap | FlagCanChangeAttribute | FlagCanUseIpc |
- FlagCanUseNonSecureIpc | FlagCanUseNonDeviceIpc,
+ Transferred = static_cast<u32>(Svc::MemoryState::Transferred) | FlagsMisc |
+ FlagCanAlignedDeviceMap | FlagCanChangeAttribute | FlagCanUseIpc |
+ FlagCanUseNonSecureIpc | FlagCanUseNonDeviceIpc,
- SharedTransfered = static_cast<u32>(Svc::MemoryState::SharedTransfered) | FlagsMisc |
- FlagCanAlignedDeviceMap | FlagCanUseNonSecureIpc | FlagCanUseNonDeviceIpc,
+ SharedTransferred = static_cast<u32>(Svc::MemoryState::SharedTransferred) | FlagsMisc |
+ FlagCanAlignedDeviceMap | FlagCanUseNonSecureIpc | FlagCanUseNonDeviceIpc,
SharedCode = static_cast<u32>(Svc::MemoryState::SharedCode) | FlagMapped |
FlagReferenceCounted | FlagLinearMapped | FlagCanUseNonSecureIpc |
@@ -130,8 +130,8 @@ static_assert(static_cast<u32>(KMemoryState::AliasCodeData) == 0x0FFFBD09);
static_assert(static_cast<u32>(KMemoryState::Ipc) == 0x045C3C0A);
static_assert(static_cast<u32>(KMemoryState::Stack) == 0x045C3C0B);
static_assert(static_cast<u32>(KMemoryState::ThreadLocal) == 0x0400000C);
-static_assert(static_cast<u32>(KMemoryState::Transfered) == 0x055C3C0D);
-static_assert(static_cast<u32>(KMemoryState::SharedTransfered) == 0x045C380E);
+static_assert(static_cast<u32>(KMemoryState::Transferred) == 0x055C3C0D);
+static_assert(static_cast<u32>(KMemoryState::SharedTransferred) == 0x045C380E);
static_assert(static_cast<u32>(KMemoryState::SharedCode) == 0x0440380F);
static_assert(static_cast<u32>(KMemoryState::Inaccessible) == 0x00000010);
static_assert(static_cast<u32>(KMemoryState::NonSecureIpc) == 0x045C3811);
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,
}
void KMemoryBlockManager::Finalize(KMemoryBlockSlabManager* slab_manager,
- HostUnmapCallback&& host_unmap_callback) {
+ BlockCallback&& block_callback) {
// Erase every block until we have none left.
auto it = m_memory_block_tree.begin();
while (it != m_memory_block_tree.end()) {
KMemoryBlock* block = std::addressof(*it);
it = m_memory_block_tree.erase(it);
+ block_callback(block->GetAddress(), block->GetSize());
slab_manager->Free(block);
- host_unmap_callback(block->GetAddress(), block->GetSize());
}
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:
public:
KMemoryBlockManager();
- using HostUnmapCallback = std::function<void(Common::ProcessAddress, u64)>;
+ using BlockCallback = std::function<void(Common::ProcessAddress, u64)>;
Result Initialize(KProcessAddress st, KProcessAddress nd,
KMemoryBlockSlabManager* slab_manager);
- void Finalize(KMemoryBlockSlabManager* slab_manager, HostUnmapCallback&& host_unmap_callback);
+ void Finalize(KMemoryBlockSlabManager* slab_manager, BlockCallback&& block_callback);
iterator end() {
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 8c1549559..3f0a39d33 100644
--- a/src/core/hle/kernel/k_page_table_base.cpp
+++ b/src/core/hle/kernel/k_page_table_base.cpp
@@ -431,15 +431,43 @@ Result KPageTableBase::InitializeForProcess(Svc::CreateProcessFlag as_type, bool
m_memory_block_slab_manager));
}
+Result KPageTableBase::FinalizeProcess() {
+ // Only process tables should be finalized.
+ ASSERT(!this->IsKernel());
+
+ // NOTE: Here Nintendo calls an unknown OnFinalize function.
+ // this->OnFinalize();
+
+ // NOTE: Here Nintendo calls a second unknown OnFinalize function.
+ // this->OnFinalize2();
+
+ // NOTE: Here Nintendo does a page table walk to discover heap pages to free.
+ // We will use the block manager finalization below to free them.
+
+ R_SUCCEED();
+}
+
void KPageTableBase::Finalize() {
- auto HostUnmapCallback = [&](KProcessAddress addr, u64 size) {
- if (Settings::IsFastmemEnabled()) {
+ this->FinalizeProcess();
+
+ auto BlockCallback = [&](KProcessAddress addr, u64 size) {
+ if (m_impl->fastmem_arena) {
m_system.DeviceMemory().buffer.Unmap(GetInteger(addr), size, false);
}
+
+ // Get physical pages.
+ KPageGroup pg(m_kernel, m_block_info_manager);
+ this->MakePageGroup(pg, addr, size / PageSize);
+
+ // Free the pages.
+ pg.CloseAndReset();
};
// Finalize memory blocks.
- m_memory_block_manager.Finalize(m_memory_block_slab_manager, std::move(HostUnmapCallback));
+ {
+ KScopedLightLock lk(m_general_lock);
+ m_memory_block_manager.Finalize(m_memory_block_slab_manager, std::move(BlockCallback));
+ }
// Free any unsafe mapped memory.
if (m_mapped_unsafe_physical_memory) {
@@ -486,8 +514,8 @@ KProcessAddress KPageTableBase::GetRegionAddress(Svc::MemoryState state) const {
case Svc::MemoryState::Shared:
case Svc::MemoryState::AliasCode:
case Svc::MemoryState::AliasCodeData:
- case Svc::MemoryState::Transfered:
- case Svc::MemoryState::SharedTransfered:
+ case Svc::MemoryState::Transferred:
+ case Svc::MemoryState::SharedTransferred:
case Svc::MemoryState::SharedCode:
case Svc::MemoryState::GeneratedCode:
case Svc::MemoryState::CodeOut:
@@ -522,8 +550,8 @@ size_t KPageTableBase::GetRegionSize(Svc::MemoryState state) const {
case Svc::MemoryState::Shared:
case Svc::MemoryState::AliasCode:
case Svc::MemoryState::AliasCodeData:
- case Svc::MemoryState::Transfered:
- case Svc::MemoryState::SharedTransfered:
+ case Svc::MemoryState::Transferred:
+ case Svc::MemoryState::SharedTransferred:
case Svc::MemoryState::SharedCode:
case Svc::MemoryState::GeneratedCode:
case Svc::MemoryState::CodeOut:
@@ -564,8 +592,8 @@ bool KPageTableBase::CanContain(KProcessAddress addr, size_t size, Svc::MemorySt
case Svc::MemoryState::AliasCodeData:
case Svc::MemoryState::Stack:
case Svc::MemoryState::ThreadLocal:
- case Svc::MemoryState::Transfered:
- case Svc::MemoryState::SharedTransfered:
+ case Svc::MemoryState::Transferred:
+ case Svc::MemoryState::SharedTransferred:
case Svc::MemoryState::SharedCode:
case Svc::MemoryState::GeneratedCode:
case Svc::MemoryState::CodeOut:
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:
KResourceLimit* resource_limit, Core::Memory::Memory& memory,
KProcessAddress aslr_space_start);
+ Result FinalizeProcess();
void Finalize();
bool IsKernel() const {
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index 068e71dff..53735a225 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -171,6 +171,12 @@ void KProcess::Finalize() {
m_resource_limit->Close();
}
+ // Clear expensive resources, as the destructor is not called for guest objects.
+ for (auto& interface : m_arm_interfaces) {
+ interface.reset();
+ }
+ m_exclusive_monitor.reset();
+
// Perform inherited finalization.
KSynchronizationObject::Finalize();
}
@@ -1233,10 +1239,10 @@ void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) {
ReprotectSegment(code_set.DataSegment(), Svc::MemoryPermission::ReadWrite);
#ifdef HAS_NCE
- if (this->IsApplication() && Settings::IsNceEnabled()) {
+ const auto& patch = code_set.PatchSegment();
+ if (this->IsApplication() && Settings::IsNceEnabled() && patch.size != 0) {
auto& buffer = m_kernel.System().DeviceMemory().buffer;
const auto& code = code_set.CodeSegment();
- const auto& patch = code_set.PatchSegment();
buffer.Protect(GetInteger(base_addr + code.addr), code.size,
Common::MemoryPermission::Read | Common::MemoryPermission::Execute);
buffer.Protect(GetInteger(base_addr + patch.addr), patch.size,
diff --git a/src/core/hle/kernel/k_transfer_memory.cpp b/src/core/hle/kernel/k_transfer_memory.cpp
index 0e2e11743..cbb1b02bb 100644
--- a/src/core/hle/kernel/k_transfer_memory.cpp
+++ b/src/core/hle/kernel/k_transfer_memory.cpp
@@ -76,8 +76,8 @@ Result KTransferMemory::Map(KProcessAddress address, size_t size, Svc::MemoryPer
// Map the memory.
const KMemoryState state = (m_owner_perm == Svc::MemoryPermission::None)
- ? KMemoryState::Transfered
- : KMemoryState::SharedTransfered;
+ ? KMemoryState::Transferred
+ : KMemoryState::SharedTransferred;
R_TRY(GetCurrentProcess(m_kernel).GetPageTable().MapPageGroup(
address, *m_page_group, state, KMemoryPermission::UserReadWrite));
@@ -96,8 +96,8 @@ Result KTransferMemory::Unmap(KProcessAddress address, size_t size) {
// Unmap the memory.
const KMemoryState state = (m_owner_perm == Svc::MemoryPermission::None)
- ? KMemoryState::Transfered
- : KMemoryState::SharedTransfered;
+ ? KMemoryState::Transferred
+ : KMemoryState::SharedTransferred;
R_TRY(GetCurrentProcess(m_kernel).GetPageTable().UnmapPageGroup(address, *m_page_group, state));
// Mark ourselves as unmapped.
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 1030f0c12..f3683cdcc 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -112,7 +112,14 @@ struct KernelCore::Impl {
old_process->Close();
}
- process_list.clear();
+ {
+ std::scoped_lock lk{process_list_lock};
+ for (auto* const process : process_list) {
+ process->Terminate();
+ process->Close();
+ }
+ process_list.clear();
+ }
next_object_id = 0;
next_kernel_process_id = KProcess::InitialProcessIdMin;
@@ -770,6 +777,7 @@ struct KernelCore::Impl {
std::atomic<u64> next_thread_id{1};
// Lists all processes that exist in the current session.
+ std::mutex process_list_lock;
std::vector<KProcess*> process_list;
std::atomic<KProcess*> application_process{};
std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context;
@@ -869,9 +877,19 @@ KResourceLimit* KernelCore::GetSystemResourceLimit() {
}
void KernelCore::AppendNewProcess(KProcess* process) {
+ process->Open();
+
+ std::scoped_lock lk{impl->process_list_lock};
impl->process_list.push_back(process);
}
+void KernelCore::RemoveProcess(KProcess* process) {
+ std::scoped_lock lk{impl->process_list_lock};
+ if (std::erase(impl->process_list, process)) {
+ process->Close();
+ }
+}
+
void KernelCore::MakeApplicationProcess(KProcess* process) {
impl->MakeApplicationProcess(process);
}
@@ -884,8 +902,15 @@ const KProcess* KernelCore::ApplicationProcess() const {
return impl->application_process;
}
-const std::vector<KProcess*>& KernelCore::GetProcessList() const {
- return impl->process_list;
+std::list<KScopedAutoObject<KProcess>> KernelCore::GetProcessList() {
+ std::list<KScopedAutoObject<KProcess>> processes;
+ std::scoped_lock lk{impl->process_list_lock};
+
+ for (auto* const process : impl->process_list) {
+ processes.emplace_back(process);
+ }
+
+ return processes;
}
Kernel::GlobalSchedulerContext& KernelCore::GlobalSchedulerContext() {
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 5d4102145..8ea5bed1c 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -5,6 +5,7 @@
#include <array>
#include <functional>
+#include <list>
#include <memory>
#include <string>
#include <unordered_map>
@@ -116,8 +117,9 @@ public:
/// Retrieves a shared pointer to the system resource limit instance.
KResourceLimit* GetSystemResourceLimit();
- /// Adds the given shared pointer to an internal list of active processes.
+ /// Adds/removes the given pointer to an internal list of active processes.
void AppendNewProcess(KProcess* process);
+ void RemoveProcess(KProcess* process);
/// Makes the given process the new application process.
void MakeApplicationProcess(KProcess* process);
@@ -129,7 +131,7 @@ public:
const KProcess* ApplicationProcess() const;
/// Retrieves the list of processes.
- const std::vector<KProcess*>& GetProcessList() const;
+ std::list<KScopedAutoObject<KProcess>> GetProcessList();
/// Gets the sole instance of the global scheduler
Kernel::GlobalSchedulerContext& GlobalSchedulerContext();
diff --git a/src/core/hle/kernel/svc/svc_process.cpp b/src/core/hle/kernel/svc/svc_process.cpp
index caa8bee9a..5c3e8829f 100644
--- a/src/core/hle/kernel/svc/svc_process.cpp
+++ b/src/core/hle/kernel/svc/svc_process.cpp
@@ -74,13 +74,15 @@ Result GetProcessList(Core::System& system, s32* out_num_processes, u64 out_proc
}
auto& memory = GetCurrentMemory(kernel);
- const auto& process_list = kernel.GetProcessList();
+ auto process_list = kernel.GetProcessList();
+ auto it = process_list.begin();
+
const auto num_processes = process_list.size();
const auto copy_amount =
std::min(static_cast<std::size_t>(out_process_ids_size), num_processes);
- for (std::size_t i = 0; i < copy_amount; ++i) {
- memory.Write64(out_process_ids, process_list[i]->GetProcessId());
+ for (std::size_t i = 0; i < copy_amount && it != process_list.end(); ++i, ++it) {
+ memory.Write64(out_process_ids, (*it)->GetProcessId());
out_process_ids += sizeof(u64);
}
diff --git a/src/core/hle/kernel/svc/svc_transfer_memory.cpp b/src/core/hle/kernel/svc/svc_transfer_memory.cpp
index 1f97121b3..671bca23f 100644
--- a/src/core/hle/kernel/svc/svc_transfer_memory.cpp
+++ b/src/core/hle/kernel/svc/svc_transfer_memory.cpp
@@ -90,7 +90,7 @@ Result MapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t add
// Verify that the mapping is in range.
R_UNLESS(GetCurrentProcess(system.Kernel())
.GetPageTable()
- .CanContain(address, size, KMemoryState::Transfered),
+ .CanContain(address, size, KMemoryState::Transferred),
ResultInvalidMemoryRegion);
// Map the transfer memory.
@@ -117,7 +117,7 @@ Result UnmapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t a
// Verify that the mapping is in range.
R_UNLESS(GetCurrentProcess(system.Kernel())
.GetPageTable()
- .CanContain(address, size, KMemoryState::Transfered),
+ .CanContain(address, size, KMemoryState::Transferred),
ResultInvalidMemoryRegion);
// Unmap the transfer memory.
diff --git a/src/core/hle/kernel/svc_types.h b/src/core/hle/kernel/svc_types.h
index 50de02e36..ab432ea78 100644
--- a/src/core/hle/kernel/svc_types.h
+++ b/src/core/hle/kernel/svc_types.h
@@ -27,8 +27,8 @@ enum class MemoryState : u32 {
Ipc = 0x0A,
Stack = 0x0B,
ThreadLocal = 0x0C,
- Transfered = 0x0D,
- SharedTransfered = 0x0E,
+ Transferred = 0x0D,
+ SharedTransferred = 0x0E,
SharedCode = 0x0F,
Inaccessible = 0x10,
NonSecureIpc = 0x11,