This commit is contained in:
lizzie 2026-06-05 09:02:58 +00:00
parent 77b8e9c532
commit 331348da3d
17 changed files with 196 additions and 179 deletions

View File

@ -81,7 +81,7 @@ void CpuManager::MultiCoreRunGuestThread() {
while (true) { while (true) {
auto* physical_core = &kernel.CurrentPhysicalCore(); auto* physical_core = &kernel.CurrentPhysicalCore();
while (!physical_core->IsInterrupted()) { while (!physical_core->IsInterrupted()) {
physical_core->RunThread(thread); physical_core->RunThread(kernel, thread);
physical_core = &kernel.CurrentPhysicalCore(); physical_core = &kernel.CurrentPhysicalCore();
} }
@ -119,7 +119,7 @@ void CpuManager::SingleCoreRunGuestThread() {
while (true) { while (true) {
auto* physical_core = &kernel.CurrentPhysicalCore(); auto* physical_core = &kernel.CurrentPhysicalCore();
if (!physical_core->IsInterrupted()) { if (!physical_core->IsInterrupted()) {
physical_core->RunThread(thread); physical_core->RunThread(kernel, thread);
physical_core = &kernel.CurrentPhysicalCore(); physical_core = &kernel.CurrentPhysicalCore();
} }

View File

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -57,7 +60,7 @@ void KCodeMemory::Finalize() {
} }
// Close the page group. // Close the page group.
m_page_group->Close(); m_page_group->Close(m_kernel);
m_page_group->Finalize(); m_page_group->Finalize();
// Close our reference to our owner. // Close our reference to our owner.

View File

@ -106,7 +106,8 @@ public:
} // namespace } // namespace
KConditionVariable::KConditionVariable(Core::System& system) KConditionVariable::KConditionVariable(Core::System& system)
: m_system{system}, m_kernel{system.Kernel()} {} : m_system{system}
{}
KConditionVariable::~KConditionVariable() = default; KConditionVariable::~KConditionVariable() = default;
@ -194,9 +195,9 @@ Result KConditionVariable::WaitForAddress(KernelCore& kernel, Handle handle, KPr
R_RETURN(cur_thread->GetWaitResult()); R_RETURN(cur_thread->GetWaitResult());
} }
void KConditionVariable::SignalImpl(KThread* thread) { void KConditionVariable::SignalImpl(KernelCore& kernel, KThread* thread) {
// Check pre-conditions. // Check pre-conditions.
ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel));
// Update the tag. // Update the tag.
KProcessAddress address = thread->GetAddressKey(); KProcessAddress address = thread->GetAddressKey();
@ -211,8 +212,7 @@ void KConditionVariable::SignalImpl(KThread* thread) {
// TODO(bunnei): We should call CanAccessAtomic(..) here. // TODO(bunnei): We should call CanAccessAtomic(..) here.
can_access = true; can_access = true;
if (can_access) { if (can_access) {
UpdateLockAtomic(m_kernel, std::addressof(prev_tag), address, own_tag, UpdateLockAtomic(kernel, std::addressof(prev_tag), address, own_tag, Svc::HandleWaitMask);
Svc::HandleWaitMask);
} }
} }
@ -222,9 +222,9 @@ void KConditionVariable::SignalImpl(KThread* thread) {
thread->EndWait(ResultSuccess); thread->EndWait(ResultSuccess);
} else { } else {
// Get the previous owner. // Get the previous owner.
KThread* owner_thread = GetCurrentProcess(m_kernel) KThread* owner_thread = GetCurrentProcess(kernel)
.GetHandleTable() .GetHandleTable()
.GetObjectWithoutPseudoHandle<KThread>(m_kernel, Handle(prev_tag & ~Svc::HandleWaitMask)) .GetObjectWithoutPseudoHandle<KThread>(kernel, Handle(prev_tag & ~Svc::HandleWaitMask))
.ReleasePointerUnsafe(); .ReleasePointerUnsafe();
if (owner_thread) { if (owner_thread) {
@ -246,17 +246,16 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) {
// Perform signaling. // Perform signaling.
s32 num_waiters{}; s32 num_waiters{};
{ {
KScopedSchedulerLock sl(m_kernel); KScopedSchedulerLock sl(m_system.Kernel());
auto it = m_tree.nfind_key({cv_key, -1}); auto it = m_tree.nfind_key({cv_key, -1});
while ((it != m_tree.end()) && (count <= 0 || num_waiters < count) && while ((it != m_tree.end()) && (count <= 0 || num_waiters < count) && (it->GetConditionVariableKey() == cv_key)) {
(it->GetConditionVariableKey() == cv_key)) {
KThread* target_thread = std::addressof(*it); KThread* target_thread = std::addressof(*it);
it = m_tree.erase(it); it = m_tree.erase(it);
target_thread->ClearConditionVariable(); target_thread->ClearConditionVariable();
this->SignalImpl(target_thread); this->SignalImpl(m_system.Kernel(), target_thread);
++num_waiters; ++num_waiters;
} }
@ -264,20 +263,20 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) {
// If we have no waiters, clear the has waiter flag. // If we have no waiters, clear the has waiter flag.
if (it == m_tree.end() || it->GetConditionVariableKey() != cv_key) { if (it == m_tree.end() || it->GetConditionVariableKey() != cv_key) {
constexpr u32 HasNoWaiterFlag = 0; constexpr u32 HasNoWaiterFlag = 0;
WriteToUser(m_kernel, cv_key, HasNoWaiterFlag); WriteToUser(m_system.Kernel(), cv_key, HasNoWaiterFlag);
} }
} }
} }
Result KConditionVariable::Wait(KProcessAddress addr, u64 key, u32 value, s64 timeout) { Result KConditionVariable::Wait(KProcessAddress addr, u64 key, u32 value, s64 timeout) {
// Prepare to wait. // Prepare to wait.
KThread* cur_thread = GetCurrentThreadPointer(m_kernel); KThread* cur_thread = GetCurrentThreadPointer(m_system.Kernel());
KHardwareTimer* timer{}; KHardwareTimer* timer{};
ThreadQueueImplForKConditionVariableWaitConditionVariable wait_queue(m_kernel, ThreadQueueImplForKConditionVariableWaitConditionVariable wait_queue(m_system.Kernel(),
std::addressof(m_tree)); std::addressof(m_tree));
{ {
KScopedSchedulerLockAndSleep slp(m_kernel, std::addressof(timer), cur_thread, timeout); KScopedSchedulerLockAndSleep slp(m_system.Kernel(), std::addressof(timer), cur_thread, timeout);
// Check that the thread isn't terminating. // Check that the thread isn't terminating.
if (cur_thread->IsTerminationRequested()) { if (cur_thread->IsTerminationRequested()) {
@ -308,12 +307,12 @@ Result KConditionVariable::Wait(KProcessAddress addr, u64 key, u32 value, s64 ti
// Write to the cv key. // Write to the cv key.
{ {
constexpr u32 HasWaiterFlag = 1; constexpr u32 HasWaiterFlag = 1;
WriteToUser(m_kernel, key, HasWaiterFlag); WriteToUser(m_system.Kernel(), key, HasWaiterFlag);
std::atomic_thread_fence(std::memory_order_seq_cst); std::atomic_thread_fence(std::memory_order_seq_cst);
} }
// Write the value to userspace. // Write the value to userspace.
if (!WriteToUser(m_kernel, addr, next_value)) { if (!WriteToUser(m_system.Kernel(), addr, next_value)) {
slp.CancelSleep(); slp.CancelSleep();
R_THROW(ResultInvalidCurrentMemory); R_THROW(ResultInvalidCurrentMemory);
} }

View File

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -26,19 +29,17 @@ public:
// Arbitration. // Arbitration.
static Result SignalToAddress(KernelCore& kernel, KProcessAddress addr); static Result SignalToAddress(KernelCore& kernel, KProcessAddress addr);
static Result WaitForAddress(KernelCore& kernel, Handle handle, KProcessAddress addr, static Result WaitForAddress(KernelCore& kernel, Handle handle, KProcessAddress addr, u32 value);
u32 value);
// Condition variable. // Condition variable.
void Signal(u64 cv_key, s32 count); void Signal(u64 cv_key, s32 count);
Result Wait(KProcessAddress addr, u64 key, u32 value, s64 timeout); Result Wait(KProcessAddress addr, u64 key, u32 value, s64 timeout);
private: private:
void SignalImpl(KThread* thread); void SignalImpl(KernelCore& kernel, KThread* thread);
private: private:
Core::System& m_system; Core::System& m_system;
KernelCore& m_kernel;
ThreadTree m_tree{}; ThreadTree m_tree{};
}; };

View File

@ -105,7 +105,7 @@ public:
} }
} }
return this->template GetObjectWithoutPseudoHandle<T>(handle); return this->template GetObjectWithoutPseudoHandle<T>(kernel, handle);
} }
KScopedAutoObject<KAutoObject> GetObjectForIpcWithoutPseudoHandle(KernelCore& kernel, Handle handle) const { KScopedAutoObject<KAutoObject> GetObjectForIpcWithoutPseudoHandle(KernelCore& kernel, Handle handle) const {

View File

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -21,8 +24,8 @@ void KPageGroup::Finalize() {
m_last_block = nullptr; m_last_block = nullptr;
} }
void KPageGroup::CloseAndReset() { void KPageGroup::CloseAndReset(KernelCore& kernel) {
auto& mm = m_kernel.MemoryManager(); auto& mm = kernel.MemoryManager();
KBlockInfo* cur = m_first_block; KBlockInfo* cur = m_first_block;
while (cur != nullptr) { while (cur != nullptr) {
@ -76,28 +79,22 @@ Result KPageGroup::AddBlock(KPhysicalAddress addr, size_t num_pages) {
R_SUCCEED(); R_SUCCEED();
} }
void KPageGroup::Open() const { void KPageGroup::Open(KernelCore& kernel) const {
auto& mm = m_kernel.MemoryManager(); auto& mm = kernel.MemoryManager();
for (const auto& it : *this)
for (const auto& it : *this) {
mm.Open(it.GetAddress(), it.GetNumPages()); mm.Open(it.GetAddress(), it.GetNumPages());
}
} }
void KPageGroup::OpenFirst() const { void KPageGroup::OpenFirst(KernelCore& kernel) const {
auto& mm = m_kernel.MemoryManager(); auto& mm = kernel.MemoryManager();
for (const auto& it : *this)
for (const auto& it : *this) {
mm.OpenFirst(it.GetAddress(), it.GetNumPages()); mm.OpenFirst(it.GetAddress(), it.GetNumPages());
}
} }
void KPageGroup::Close() const { void KPageGroup::Close(KernelCore& kernel) const {
auto& mm = m_kernel.MemoryManager(); auto& mm = kernel.MemoryManager();
for (const auto& it : *this)
for (const auto& it : *this) {
mm.Close(it.GetAddress(), it.GetNumPages()); mm.Close(it.GetAddress(), it.GetNumPages());
}
} }
bool KPageGroup::IsEquivalentTo(const KPageGroup& rhs) const { bool KPageGroup::IsEquivalentTo(const KPageGroup& rhs) const {

View File

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -139,12 +142,12 @@ public:
}; };
explicit KPageGroup(KernelCore& kernel, KBlockInfoManager* m) explicit KPageGroup(KernelCore& kernel, KBlockInfoManager* m)
: m_kernel{kernel}, m_manager{m} {} : m_manager{m} {}
~KPageGroup() { ~KPageGroup() {
this->Finalize(); this->Finalize();
} }
void CloseAndReset(); void CloseAndReset(KernelCore& kernel);
void Finalize(); void Finalize();
Iterator begin() const { Iterator begin() const {
@ -158,9 +161,9 @@ public:
} }
Result AddBlock(KPhysicalAddress addr, size_t num_pages); Result AddBlock(KPhysicalAddress addr, size_t num_pages);
void Open() const; void Open(KernelCore& kernel) const;
void OpenFirst() const; void OpenFirst(KernelCore& kernel) const;
void Close() const; void Close(KernelCore& kernel) const;
size_t GetNumPages() const; size_t GetNumPages() const;
@ -175,7 +178,6 @@ public:
} }
private: private:
KernelCore& m_kernel;
KBlockInfo* m_first_block{}; KBlockInfo* m_first_block{};
KBlockInfo* m_last_block{}; KBlockInfo* m_last_block{};
KBlockInfoManager* m_manager{}; KBlockInfoManager* m_manager{};
@ -183,21 +185,24 @@ private:
class KScopedPageGroup { class KScopedPageGroup {
public: public:
explicit KScopedPageGroup(const KPageGroup* gp, bool not_first = true) : m_pg(gp) { explicit KScopedPageGroup(KernelCore& kernel, const KPageGroup* gp, bool not_first = true)
: m_kernel{kernel}
, m_pg{gp}
{
if (m_pg) { if (m_pg) {
if (not_first) { if (not_first) {
m_pg->Open(); m_pg->Open(kernel);
} else { } else {
m_pg->OpenFirst(); m_pg->OpenFirst(kernel);
} }
} }
} }
explicit KScopedPageGroup(const KPageGroup& gp, bool not_first = true) explicit KScopedPageGroup(KernelCore& kernel, const KPageGroup& gp, bool not_first = true)
: KScopedPageGroup(std::addressof(gp), not_first) {} : KScopedPageGroup(kernel, std::addressof(gp), not_first) {}
~KScopedPageGroup() { ~KScopedPageGroup() {
if (m_pg) { if (m_pg)
m_pg->Close(); m_pg->Close(m_kernel);
}
} }
void CancelClose() { void CancelClose() {
@ -205,6 +210,7 @@ public:
} }
private: private:
KernelCore& m_kernel;
const KPageGroup* m_pg{}; const KPageGroup* m_pg{};
}; };

View File

@ -127,22 +127,22 @@ constexpr Common::MemoryPermission ConvertToMemoryPermission(KMemoryPermission p
} // namespace } // namespace
void KPageTableBase::MemoryRange::Open() { void KPageTableBase::MemoryRange::Open(KernelCore& kernel) {
// If the range contains heap pages, open them. // If the range contains heap pages, open them.
if (this->IsHeap()) { if (this->IsHeap()) {
m_kernel.MemoryManager().Open(this->GetAddress(), this->GetSize() / PageSize); kernel.MemoryManager().Open(this->GetAddress(), this->GetSize() / PageSize);
} }
} }
void KPageTableBase::MemoryRange::Close() { void KPageTableBase::MemoryRange::Close(KernelCore& kernel) {
// If the range contains heap pages, close them. // If the range contains heap pages, close them.
if (this->IsHeap()) { if (this->IsHeap()) {
m_kernel.MemoryManager().Close(this->GetAddress(), this->GetSize() / PageSize); kernel.MemoryManager().Close(this->GetAddress(), this->GetSize() / PageSize);
} }
} }
KPageTableBase::KPageTableBase(KernelCore& kernel) KPageTableBase::KPageTableBase(KernelCore& kernel)
: m_kernel(kernel), m_system(kernel.System()), m_general_lock(kernel), : m_system(kernel.System()), m_general_lock(kernel),
m_map_physical_memory_lock(kernel), m_device_map_lock(kernel) {} m_map_physical_memory_lock(kernel), m_device_map_lock(kernel) {}
KPageTableBase::~KPageTableBase() = default; KPageTableBase::~KPageTableBase() = default;
@ -177,9 +177,9 @@ Result KPageTableBase::InitializeForKernel(bool is_64_bit, KVirtualAddress start
m_mapped_ipc_server_memory = 0; m_mapped_ipc_server_memory = 0;
m_memory_block_slab_manager = m_memory_block_slab_manager =
m_kernel.GetSystemSystemResource().GetMemoryBlockSlabManagerPointer(); m_system.Kernel().GetSystemSystemResource().GetMemoryBlockSlabManagerPointer();
m_block_info_manager = m_kernel.GetSystemSystemResource().GetBlockInfoManagerPointer(); m_block_info_manager = m_system.Kernel().GetSystemSystemResource().GetBlockInfoManagerPointer();
m_resource_limit = m_kernel.GetSystemResourceLimit(); m_resource_limit = m_system.Kernel().GetSystemResourceLimit();
m_allocate_option = KMemoryManager::EncodeOption(KMemoryManager::Pool::System, m_allocate_option = KMemoryManager::EncodeOption(KMemoryManager::Pool::System,
KMemoryManager::Direction::FromFront); KMemoryManager::Direction::FromFront);
@ -469,11 +469,11 @@ void KPageTableBase::Finalize() {
} }
// Get physical pages. // Get physical pages.
KPageGroup pg(m_kernel, m_block_info_manager); KPageGroup pg(m_system.Kernel(), m_block_info_manager);
this->MakePageGroup(pg, addr, size / PageSize); this->MakePageGroup(pg, addr, size / PageSize);
// Free the pages. // Free the pages.
pg.CloseAndReset(); pg.CloseAndReset(m_system.Kernel());
}; };
// Finalize memory blocks. // Finalize memory blocks.
@ -490,7 +490,7 @@ void KPageTableBase::Finalize() {
// Release any insecure mapped memory. // Release any insecure mapped memory.
if (m_mapped_insecure_memory) { if (m_mapped_insecure_memory) {
if (auto* const insecure_resource_limit = if (auto* const insecure_resource_limit =
KSystemControl::GetInsecureMemoryResourceLimit(m_kernel); KSystemControl::GetInsecureMemoryResourceLimit(m_system.Kernel());
insecure_resource_limit != nullptr) { insecure_resource_limit != nullptr) {
insecure_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, insecure_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax,
m_mapped_insecure_memory); m_mapped_insecure_memory);
@ -833,7 +833,7 @@ Result KPageTableBase::LockMemoryAndOpen(KPageGroup* out_pg, KPhysicalAddress* o
// If we have an output group, open. // If we have an output group, open.
if (out_pg) { if (out_pg) {
out_pg->Open(); out_pg->Open(m_system.Kernel());
} }
R_SUCCEED(); R_SUCCEED();
@ -1041,7 +1041,7 @@ Result KPageTableBase::MapMemory(KProcessAddress dst_address, KProcessAddress sr
const size_t num_pages = size / PageSize; const size_t num_pages = size / PageSize;
// Create page groups for the memory being unmapped. // Create page groups for the memory being unmapped.
KPageGroup pg(m_kernel, m_block_info_manager); KPageGroup pg(m_system.Kernel(), m_block_info_manager);
// Create the page group representing the source. // Create the page group representing the source.
R_TRY(this->MakePageGroup(pg, src_address, num_pages)); R_TRY(this->MakePageGroup(pg, src_address, num_pages));
@ -1129,7 +1129,7 @@ Result KPageTableBase::UnmapMemory(KProcessAddress dst_address, KProcessAddress
const size_t num_pages = size / PageSize; const size_t num_pages = size / PageSize;
// Create page groups for the memory being unmapped. // Create page groups for the memory being unmapped.
KPageGroup pg(m_kernel, m_block_info_manager); KPageGroup pg(m_system.Kernel(), m_block_info_manager);
// Create the page group representing the destination. // Create the page group representing the destination.
R_TRY(this->MakePageGroup(pg, dst_address, num_pages)); R_TRY(this->MakePageGroup(pg, dst_address, num_pages));
@ -1217,7 +1217,7 @@ Result KPageTableBase::MapCodeMemory(KProcessAddress dst_address, KProcessAddres
const size_t num_pages = size / PageSize; const size_t num_pages = size / PageSize;
// Create page groups for the memory being unmapped. // Create page groups for the memory being unmapped.
KPageGroup pg(m_kernel, m_block_info_manager); KPageGroup pg(m_system.Kernel(), m_block_info_manager);
// Create the page group representing the source. // Create the page group representing the source.
R_TRY(this->MakePageGroup(pg, src_address, num_pages)); R_TRY(this->MakePageGroup(pg, src_address, num_pages));
@ -1312,7 +1312,7 @@ Result KPageTableBase::UnmapCodeMemory(KProcessAddress dst_address, KProcessAddr
bool reprotected_pages = false; bool reprotected_pages = false;
SCOPE_EXIT { SCOPE_EXIT {
if (reprotected_pages && any_code_pages) { if (reprotected_pages && any_code_pages) {
InvalidateInstructionCache(m_kernel, this, dst_address, size); InvalidateInstructionCache(m_system.Kernel(), this, dst_address, size);
} }
}; };
@ -1322,7 +1322,7 @@ Result KPageTableBase::UnmapCodeMemory(KProcessAddress dst_address, KProcessAddr
const size_t num_pages = size / PageSize; const size_t num_pages = size / PageSize;
// Create page groups for the memory being unmapped. // Create page groups for the memory being unmapped.
KPageGroup pg(m_kernel, m_block_info_manager); KPageGroup pg(m_system.Kernel(), m_block_info_manager);
// Create the page group representing the destination. // Create the page group representing the destination.
R_TRY(this->MakePageGroup(pg, dst_address, num_pages)); R_TRY(this->MakePageGroup(pg, dst_address, num_pages));
@ -1383,7 +1383,7 @@ Result KPageTableBase::UnmapCodeMemory(KProcessAddress dst_address, KProcessAddr
Result KPageTableBase::MapInsecureMemory(KProcessAddress address, size_t size) { Result KPageTableBase::MapInsecureMemory(KProcessAddress address, size_t size) {
// Get the insecure memory resource limit and pool. // Get the insecure memory resource limit and pool.
auto* const insecure_resource_limit = KSystemControl::GetInsecureMemoryResourceLimit(m_kernel); auto* const insecure_resource_limit = KSystemControl::GetInsecureMemoryResourceLimit(m_system.Kernel());
const auto insecure_pool = const auto insecure_pool =
static_cast<KMemoryManager::Pool>(KSystemControl::GetInsecureMemoryPool()); static_cast<KMemoryManager::Pool>(KSystemControl::GetInsecureMemoryPool());
@ -1394,8 +1394,8 @@ Result KPageTableBase::MapInsecureMemory(KProcessAddress address, size_t size) {
R_UNLESS(memory_reservation.Succeeded(), ResultOutOfMemory); R_UNLESS(memory_reservation.Succeeded(), ResultOutOfMemory);
// Allocate pages for the insecure memory. // Allocate pages for the insecure memory.
KPageGroup pg(m_kernel, m_block_info_manager); KPageGroup pg(m_system.Kernel(), m_block_info_manager);
R_TRY(m_kernel.MemoryManager().AllocateAndOpen( R_TRY(m_system.Kernel().MemoryManager().AllocateAndOpen(
std::addressof(pg), size / PageSize, std::addressof(pg), size / PageSize,
KMemoryManager::EncodeOption(insecure_pool, KMemoryManager::Direction::FromFront))); KMemoryManager::EncodeOption(insecure_pool, KMemoryManager::Direction::FromFront)));
@ -1403,7 +1403,7 @@ Result KPageTableBase::MapInsecureMemory(KProcessAddress address, size_t size) {
// If the mapping succeeds, each page will gain an extra reference, otherwise they will be freed // If the mapping succeeds, each page will gain an extra reference, otherwise they will be freed
// automatically. // automatically.
SCOPE_EXIT { SCOPE_EXIT {
pg.Close(); pg.Close(m_system.Kernel());
}; };
// Clear all the newly allocated pages. // Clear all the newly allocated pages.
@ -1491,7 +1491,7 @@ Result KPageTableBase::UnmapInsecureMemory(KProcessAddress address, size_t size)
// Release the insecure memory from the insecure limit. // Release the insecure memory from the insecure limit.
if (auto* const insecure_resource_limit = if (auto* const insecure_resource_limit =
KSystemControl::GetInsecureMemoryResourceLimit(m_kernel); KSystemControl::GetInsecureMemoryResourceLimit(m_system.Kernel());
insecure_resource_limit != nullptr) { insecure_resource_limit != nullptr) {
insecure_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, size); insecure_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, size);
} }
@ -1603,15 +1603,15 @@ Result KPageTableBase::AllocateAndMapPagesImpl(PageLinkedList* page_list, KProce
ASSERT(this->IsLockedByCurrentThread()); ASSERT(this->IsLockedByCurrentThread());
// Create a page group to hold the pages we allocate. // Create a page group to hold the pages we allocate.
KPageGroup pg(m_kernel, m_block_info_manager); KPageGroup pg(m_system.Kernel(), m_block_info_manager);
// Allocate the pages. // Allocate the pages.
R_TRY( R_TRY(
m_kernel.MemoryManager().AllocateAndOpen(std::addressof(pg), num_pages, m_allocate_option)); m_system.Kernel().MemoryManager().AllocateAndOpen(std::addressof(pg), num_pages, m_allocate_option));
// Ensure that the page group is closed when we're done working with it. // Ensure that the page group is closed when we're done working with it.
SCOPE_EXIT { SCOPE_EXIT {
pg.Close(); pg.Close(m_system.Kernel());
}; };
// Clear all pages. // Clear all pages.
@ -1992,7 +1992,7 @@ Result KPageTableBase::SetProcessMemoryPermission(KProcessAddress addr, size_t s
KMemoryAttribute::All, KMemoryAttribute::None)); KMemoryAttribute::All, KMemoryAttribute::None));
// Make a new page group for the region. // Make a new page group for the region.
KPageGroup pg(m_kernel, m_block_info_manager); KPageGroup pg(m_system.Kernel(), m_block_info_manager);
// Determine new perm/state. // Determine new perm/state.
const KMemoryPermission new_perm = ConvertToKMemoryPermission(svc_perm); const KMemoryPermission new_perm = ConvertToKMemoryPermission(svc_perm);
@ -2048,9 +2048,9 @@ Result KPageTableBase::SetProcessMemoryPermission(KProcessAddress addr, size_t s
// Ensure cache coherency, if we're setting pages as executable. // Ensure cache coherency, if we're setting pages as executable.
if (is_x) { if (is_x) {
for (const auto& block : pg) { for (const auto& block : pg) {
StoreDataCache(GetHeapVirtualPointer(m_kernel, block.GetAddress()), block.GetSize()); StoreDataCache(GetHeapVirtualPointer(m_system.Kernel(), block.GetAddress()), block.GetSize());
} }
InvalidateInstructionCache(m_kernel, this, addr, size); InvalidateInstructionCache(m_system.Kernel(), this, addr, size);
} }
R_SUCCEED(); R_SUCCEED();
@ -2193,15 +2193,15 @@ Result KPageTableBase::SetHeapSize(KProcessAddress* out, size_t size) {
R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached);
// Allocate pages for the heap extension. // Allocate pages for the heap extension.
KPageGroup pg(m_kernel, m_block_info_manager); KPageGroup pg(m_system.Kernel(), m_block_info_manager);
R_TRY(m_kernel.MemoryManager().AllocateAndOpen(std::addressof(pg), allocation_size / PageSize, R_TRY(m_system.Kernel().MemoryManager().AllocateAndOpen(std::addressof(pg), allocation_size / PageSize,
m_allocate_option)); m_allocate_option));
// Close the opened pages when we're done with them. // Close the opened pages when we're done with them.
// If the mapping succeeds, each page will gain an extra reference, otherwise they will be freed // If the mapping succeeds, each page will gain an extra reference, otherwise they will be freed
// automatically. // automatically.
SCOPE_EXIT { SCOPE_EXIT {
pg.Close(); pg.Close(m_system.Kernel());
}; };
// Clear all the newly allocated pages. // Clear all the newly allocated pages.
@ -2406,7 +2406,7 @@ Result KPageTableBase::MapIoImpl(KProcessAddress* out, PageLinkedList* page_list
ASSERT(this->CanContain(region_start, region_size, state)); ASSERT(this->CanContain(region_start, region_size, state));
// Locate the memory region. // Locate the memory region.
const KMemoryRegion* region = KMemoryLayout::Find(m_kernel.MemoryLayout(), phys_addr); const KMemoryRegion* region = KMemoryLayout::Find(m_system.Kernel().MemoryLayout(), phys_addr);
R_UNLESS(region != nullptr, ResultInvalidAddress); R_UNLESS(region != nullptr, ResultInvalidAddress);
ASSERT(region->Contains(GetInteger(phys_addr))); ASSERT(region->Contains(GetInteger(phys_addr)));
@ -2640,7 +2640,7 @@ Result KPageTableBase::MapStatic(KPhysicalAddress phys_addr, size_t size, KMemor
const size_t region_num_pages = region_size / PageSize; const size_t region_num_pages = region_size / PageSize;
// Locate the memory region. // Locate the memory region.
const KMemoryRegion* region = KMemoryLayout::Find(m_kernel.MemoryLayout(), phys_addr); const KMemoryRegion* region = KMemoryLayout::Find(m_system.Kernel().MemoryLayout(), phys_addr);
R_UNLESS(region != nullptr, ResultInvalidAddress); R_UNLESS(region != nullptr, ResultInvalidAddress);
ASSERT(region->Contains(GetInteger(phys_addr))); ASSERT(region->Contains(GetInteger(phys_addr)));
@ -2707,7 +2707,7 @@ Result KPageTableBase::MapStatic(KPhysicalAddress phys_addr, size_t size, KMemor
Result KPageTableBase::MapRegion(KMemoryRegionType region_type, KMemoryPermission perm) { Result KPageTableBase::MapRegion(KMemoryRegionType region_type, KMemoryPermission perm) {
// Get the memory region. // Get the memory region.
const KMemoryRegion* region = const KMemoryRegion* region =
m_kernel.MemoryLayout().GetPhysicalMemoryRegionTree().FindFirstDerived(region_type); m_system.Kernel().MemoryLayout().GetPhysicalMemoryRegionTree().FindFirstDerived(region_type);
R_UNLESS(region != nullptr, ResultOutOfRange); R_UNLESS(region != nullptr, ResultOutOfRange);
// Check that the region is valid. // Check that the region is valid.
@ -3004,7 +3004,7 @@ Result KPageTableBase::MakeAndOpenPageGroup(KPageGroup* out, KProcessAddress add
R_TRY(this->MakePageGroup(*out, address, num_pages)); R_TRY(this->MakePageGroup(*out, address, num_pages));
// Open a new reference to the pages in the group. // Open a new reference to the pages in the group.
out->Open(); out->Open(m_system.Kernel());
R_SUCCEED(); R_SUCCEED();
} }
@ -3051,7 +3051,7 @@ Result KPageTableBase::InvalidateProcessDataCache(KProcessAddress address, size_
// Invalidate the block. // Invalidate the block.
if (cur_size > 0) { if (cur_size > 0) {
// NOTE: Nintendo does not check the result of invalidation. // NOTE: Nintendo does not check the result of invalidation.
InvalidateDataCache(GetLinearMappedVirtualPointer(m_kernel, cur_addr), cur_size); InvalidateDataCache(GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), cur_size);
} }
// Advance. // Advance.
@ -3075,7 +3075,7 @@ Result KPageTableBase::InvalidateProcessDataCache(KProcessAddress address, size_
// Invalidate the last block. // Invalidate the last block.
if (cur_size > 0) { if (cur_size > 0) {
// NOTE: Nintendo does not check the result of invalidation. // NOTE: Nintendo does not check the result of invalidation.
InvalidateDataCache(GetLinearMappedVirtualPointer(m_kernel, cur_addr), cur_size); InvalidateDataCache(GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), cur_size);
} }
R_SUCCEED(); R_SUCCEED();
@ -3083,7 +3083,7 @@ Result KPageTableBase::InvalidateProcessDataCache(KProcessAddress address, size_
Result KPageTableBase::InvalidateCurrentProcessDataCache(KProcessAddress address, size_t size) { Result KPageTableBase::InvalidateCurrentProcessDataCache(KProcessAddress address, size_t size) {
// Check pre-condition: this is being called on the current process. // Check pre-condition: this is being called on the current process.
ASSERT(this == std::addressof(GetCurrentProcess(m_kernel).GetPageTable().GetBasePageTable())); ASSERT(this == std::addressof(GetCurrentProcess(m_system.Kernel()).GetPageTable().GetBasePageTable()));
// Check that the region is in range. // Check that the region is in range.
R_UNLESS(this->Contains(address, size), ResultInvalidCurrentMemory); R_UNLESS(this->Contains(address, size), ResultInvalidCurrentMemory);
@ -3144,7 +3144,7 @@ Result KPageTableBase::ReadDebugMemory(KProcessAddress dst_address, KProcessAddr
// Copy as much aligned data as we can. // Copy as much aligned data as we can.
if (cur_size >= sizeof(u32)) { if (cur_size >= sizeof(u32)) {
const size_t copy_size = Common::AlignDown(cur_size, sizeof(u32)); const size_t copy_size = Common::AlignDown(cur_size, sizeof(u32));
const void* copy_src = GetLinearMappedVirtualPointer(m_kernel, cur_addr); const void* copy_src = GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr);
FlushDataCache(copy_src, copy_size); FlushDataCache(copy_src, copy_size);
R_UNLESS(dst_memory.WriteBlock(dst_address, copy_src, copy_size), ResultInvalidPointer); R_UNLESS(dst_memory.WriteBlock(dst_address, copy_src, copy_size), ResultInvalidPointer);
@ -3155,7 +3155,7 @@ Result KPageTableBase::ReadDebugMemory(KProcessAddress dst_address, KProcessAddr
// Copy remaining data. // Copy remaining data.
if (cur_size > 0) { if (cur_size > 0) {
const void* copy_src = GetLinearMappedVirtualPointer(m_kernel, cur_addr); const void* copy_src = GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr);
FlushDataCache(copy_src, cur_size); FlushDataCache(copy_src, cur_size);
R_UNLESS(dst_memory.WriteBlock(dst_address, copy_src, cur_size), ResultInvalidPointer); R_UNLESS(dst_memory.WriteBlock(dst_address, copy_src, cur_size), ResultInvalidPointer);
} }
@ -3240,11 +3240,11 @@ Result KPageTableBase::WriteDebugMemory(KProcessAddress dst_address, KProcessAdd
// Copy as much aligned data as we can. // Copy as much aligned data as we can.
if (cur_size >= sizeof(u32)) { if (cur_size >= sizeof(u32)) {
const size_t copy_size = Common::AlignDown(cur_size, sizeof(u32)); const size_t copy_size = Common::AlignDown(cur_size, sizeof(u32));
void* copy_dst = GetLinearMappedVirtualPointer(m_kernel, cur_addr); void* copy_dst = GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr);
R_UNLESS(src_memory.ReadBlock(src_address, copy_dst, copy_size), R_UNLESS(src_memory.ReadBlock(src_address, copy_dst, copy_size),
ResultInvalidCurrentMemory); ResultInvalidCurrentMemory);
StoreDataCache(GetLinearMappedVirtualPointer(m_kernel, cur_addr), copy_size); StoreDataCache(GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), copy_size);
src_address += copy_size; src_address += copy_size;
cur_addr += copy_size; cur_addr += copy_size;
@ -3253,11 +3253,11 @@ Result KPageTableBase::WriteDebugMemory(KProcessAddress dst_address, KProcessAdd
// Copy remaining data. // Copy remaining data.
if (cur_size > 0) { if (cur_size > 0) {
void* copy_dst = GetLinearMappedVirtualPointer(m_kernel, cur_addr); void* copy_dst = GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr);
R_UNLESS(src_memory.ReadBlock(src_address, copy_dst, cur_size), R_UNLESS(src_memory.ReadBlock(src_address, copy_dst, cur_size),
ResultInvalidCurrentMemory); ResultInvalidCurrentMemory);
StoreDataCache(GetLinearMappedVirtualPointer(m_kernel, cur_addr), cur_size); StoreDataCache(GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), cur_size);
} }
R_SUCCEED(); R_SUCCEED();
@ -3295,7 +3295,7 @@ Result KPageTableBase::WriteDebugMemory(KProcessAddress dst_address, KProcessAdd
R_TRY(PerformCopy()); R_TRY(PerformCopy());
// Invalidate the instruction cache, as this svc allows modifying executable pages. // Invalidate the instruction cache, as this svc allows modifying executable pages.
InvalidateInstructionCache(m_kernel, this, dst_address, size); InvalidateInstructionCache(m_system.Kernel(), this, dst_address, size);
R_SUCCEED(); R_SUCCEED();
} }
@ -3311,7 +3311,7 @@ Result KPageTableBase::ReadIoMemoryImpl(KProcessAddress dst_addr, KPhysicalAddre
const size_t map_size = map_end - map_start; const size_t map_size = map_end - map_start;
// Get the memory reference to write into. // Get the memory reference to write into.
auto& dst_memory = GetCurrentMemory(m_kernel); auto& dst_memory = GetCurrentMemory(m_system.Kernel());
// We're going to perform an update, so create a helper. // We're going to perform an update, so create a helper.
KScopedPageTableUpdater updater(this); KScopedPageTableUpdater updater(this);
@ -3347,7 +3347,7 @@ Result KPageTableBase::WriteIoMemoryImpl(KPhysicalAddress phys_addr, KProcessAdd
const size_t map_size = map_end - map_start; const size_t map_size = map_end - map_start;
// Get the memory reference to read from. // Get the memory reference to read from.
auto& src_memory = GetCurrentMemory(m_kernel); auto& src_memory = GetCurrentMemory(m_system.Kernel());
// We're going to perform an update, so create a helper. // We're going to perform an update, so create a helper.
KScopedPageTableUpdater updater(this); KScopedPageTableUpdater updater(this);
@ -3379,7 +3379,7 @@ Result KPageTableBase::ReadDebugIoMemory(KProcessAddress dst_address, KProcessAd
// We need to lock both this table, and the current process's table, so set up some aliases. // We need to lock both this table, and the current process's table, so set up some aliases.
KPageTableBase& src_page_table = *this; KPageTableBase& src_page_table = *this;
KPageTableBase& dst_page_table = GetCurrentProcess(m_kernel).GetPageTable().GetBasePageTable(); KPageTableBase& dst_page_table = GetCurrentProcess(m_system.Kernel()).GetPageTable().GetBasePageTable();
// Acquire the table locks. // Acquire the table locks.
KScopedLightLockPair lk(src_page_table.m_general_lock, dst_page_table.m_general_lock); KScopedLightLockPair lk(src_page_table.m_general_lock, dst_page_table.m_general_lock);
@ -3421,7 +3421,7 @@ Result KPageTableBase::WriteDebugIoMemory(KProcessAddress dst_address, KProcessA
// We need to lock both this table, and the current process's table, so set up some aliases. // We need to lock both this table, and the current process's table, so set up some aliases.
KPageTableBase& src_page_table = *this; KPageTableBase& src_page_table = *this;
KPageTableBase& dst_page_table = GetCurrentProcess(m_kernel).GetPageTable().GetBasePageTable(); KPageTableBase& dst_page_table = GetCurrentProcess(m_system.Kernel()).GetPageTable().GetBasePageTable();
// Acquire the table locks. // Acquire the table locks.
KScopedLightLockPair lk(src_page_table.m_general_lock, dst_page_table.m_general_lock); KScopedLightLockPair lk(src_page_table.m_general_lock, dst_page_table.m_general_lock);
@ -3606,7 +3606,7 @@ Result KPageTableBase::OpenMemoryRangeForMapDeviceAddressSpace(KPageTableBase::M
KMemoryAttribute::IpcLocked | KMemoryAttribute::Locked, KMemoryAttribute::None)); KMemoryAttribute::IpcLocked | KMemoryAttribute::Locked, KMemoryAttribute::None));
// We got the range, so open it. // We got the range, so open it.
out->Open(); out->Open(m_system.Kernel());
R_SUCCEED(); R_SUCCEED();
} }
@ -3624,7 +3624,7 @@ Result KPageTableBase::OpenMemoryRangeForUnmapDeviceAddressSpace(MemoryRange* ou
KMemoryAttribute::DeviceShared | KMemoryAttribute::Locked, KMemoryAttribute::DeviceShared)); KMemoryAttribute::DeviceShared | KMemoryAttribute::Locked, KMemoryAttribute::DeviceShared));
// We got the range, so open it. // We got the range, so open it.
out->Open(); out->Open(m_system.Kernel());
R_SUCCEED(); R_SUCCEED();
} }
@ -3697,7 +3697,7 @@ Result KPageTableBase::OpenMemoryRangeForProcessCacheOperation(MemoryRange* out,
KMemoryAttribute::None)); KMemoryAttribute::None));
// We got the range, so open it. // We got the range, so open it.
out->Open(); out->Open(m_system.Kernel());
R_SUCCEED(); R_SUCCEED();
} }
@ -3710,7 +3710,7 @@ Result KPageTableBase::CopyMemoryFromLinearToUser(
R_UNLESS(this->Contains(src_addr, size), ResultInvalidCurrentMemory); R_UNLESS(this->Contains(src_addr, size), ResultInvalidCurrentMemory);
// Get the destination memory reference. // Get the destination memory reference.
auto& dst_memory = GetCurrentMemory(m_kernel); auto& dst_memory = GetCurrentMemory(m_system.Kernel());
// Copy the memory. // Copy the memory.
{ {
@ -3745,7 +3745,7 @@ Result KPageTableBase::CopyMemoryFromLinearToUser(
if (cur_size >= sizeof(u32)) { if (cur_size >= sizeof(u32)) {
const size_t copy_size = Common::AlignDown(cur_size, sizeof(u32)); const size_t copy_size = Common::AlignDown(cur_size, sizeof(u32));
R_UNLESS(dst_memory.WriteBlock(dst_addr, R_UNLESS(dst_memory.WriteBlock(dst_addr,
GetLinearMappedVirtualPointer(m_kernel, cur_addr), GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr),
copy_size), copy_size),
ResultInvalidCurrentMemory); ResultInvalidCurrentMemory);
@ -3757,7 +3757,7 @@ Result KPageTableBase::CopyMemoryFromLinearToUser(
// Copy remaining data. // Copy remaining data.
if (cur_size > 0) { if (cur_size > 0) {
R_UNLESS(dst_memory.WriteBlock( R_UNLESS(dst_memory.WriteBlock(
dst_addr, GetLinearMappedVirtualPointer(m_kernel, cur_addr), cur_size), dst_addr, GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), cur_size),
ResultInvalidCurrentMemory); ResultInvalidCurrentMemory);
} }
@ -3836,7 +3836,7 @@ Result KPageTableBase::CopyMemoryFromLinearToKernel(
R_UNLESS(IsLinearMappedPhysicalAddress(cur_addr), ResultInvalidCurrentMemory); R_UNLESS(IsLinearMappedPhysicalAddress(cur_addr), ResultInvalidCurrentMemory);
// Copy the data. // Copy the data.
std::memcpy(buffer, GetLinearMappedVirtualPointer(m_kernel, cur_addr), cur_size); std::memcpy(buffer, GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), cur_size);
R_SUCCEED(); R_SUCCEED();
}; };
@ -3884,7 +3884,7 @@ Result KPageTableBase::CopyMemoryFromUserToLinear(
R_UNLESS(this->Contains(dst_addr, size), ResultInvalidCurrentMemory); R_UNLESS(this->Contains(dst_addr, size), ResultInvalidCurrentMemory);
// Get the source memory reference. // Get the source memory reference.
auto& src_memory = GetCurrentMemory(m_kernel); auto& src_memory = GetCurrentMemory(m_system.Kernel());
// Copy the memory. // Copy the memory.
{ {
@ -3919,7 +3919,7 @@ Result KPageTableBase::CopyMemoryFromUserToLinear(
if (cur_size >= sizeof(u32)) { if (cur_size >= sizeof(u32)) {
const size_t copy_size = Common::AlignDown(cur_size, sizeof(u32)); const size_t copy_size = Common::AlignDown(cur_size, sizeof(u32));
R_UNLESS(src_memory.ReadBlock(src_addr, R_UNLESS(src_memory.ReadBlock(src_addr,
GetLinearMappedVirtualPointer(m_kernel, cur_addr), GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr),
copy_size), copy_size),
ResultInvalidCurrentMemory); ResultInvalidCurrentMemory);
src_addr += copy_size; src_addr += copy_size;
@ -3930,7 +3930,7 @@ Result KPageTableBase::CopyMemoryFromUserToLinear(
// Copy remaining data. // Copy remaining data.
if (cur_size > 0) { if (cur_size > 0) {
R_UNLESS(src_memory.ReadBlock( R_UNLESS(src_memory.ReadBlock(
src_addr, GetLinearMappedVirtualPointer(m_kernel, cur_addr), cur_size), src_addr, GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), cur_size),
ResultInvalidCurrentMemory); ResultInvalidCurrentMemory);
} }
@ -4011,7 +4011,7 @@ Result KPageTableBase::CopyMemoryFromKernelToLinear(KProcessAddress dst_addr, si
R_UNLESS(IsLinearMappedPhysicalAddress(cur_addr), ResultInvalidCurrentMemory); R_UNLESS(IsLinearMappedPhysicalAddress(cur_addr), ResultInvalidCurrentMemory);
// Copy the data. // Copy the data.
std::memcpy(GetLinearMappedVirtualPointer(m_kernel, cur_addr), buffer, cur_size); std::memcpy(GetLinearMappedVirtualPointer(m_system.Kernel(), cur_addr), buffer, cur_size);
R_SUCCEED(); R_SUCCEED();
}; };
@ -4162,8 +4162,8 @@ Result KPageTableBase::CopyMemoryFromHeapToHeap(
R_UNLESS(IsHeapPhysicalAddress(cur_dst_addr), ResultInvalidCurrentMemory); R_UNLESS(IsHeapPhysicalAddress(cur_dst_addr), ResultInvalidCurrentMemory);
// Copy the data. // Copy the data.
std::memcpy(GetHeapVirtualPointer(m_kernel, cur_dst_addr), std::memcpy(GetHeapVirtualPointer(m_system.Kernel(), cur_dst_addr),
GetHeapVirtualPointer(m_kernel, cur_src_addr), cur_copy_size); GetHeapVirtualPointer(m_system.Kernel(), cur_src_addr), cur_copy_size);
// Update. // Update.
cur_src_block_addr = src_next_entry.phys_addr; cur_src_block_addr = src_next_entry.phys_addr;
@ -4296,8 +4296,8 @@ Result KPageTableBase::CopyMemoryFromHeapToHeapWithoutCheckDestination(
R_UNLESS(IsHeapPhysicalAddress(cur_dst_addr), ResultInvalidCurrentMemory); R_UNLESS(IsHeapPhysicalAddress(cur_dst_addr), ResultInvalidCurrentMemory);
// Copy the data. // Copy the data.
std::memcpy(GetHeapVirtualPointer(m_kernel, cur_dst_addr), std::memcpy(GetHeapVirtualPointer(m_system.Kernel(), cur_dst_addr),
GetHeapVirtualPointer(m_kernel, cur_src_addr), cur_copy_size); GetHeapVirtualPointer(m_system.Kernel(), cur_src_addr), cur_copy_size);
// Update. // Update.
cur_src_block_addr = src_next_entry.phys_addr; cur_src_block_addr = src_next_entry.phys_addr;
@ -4506,10 +4506,10 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size,
// free on scope exit. // free on scope exit.
SCOPE_EXIT { SCOPE_EXIT {
if (start_partial_page != 0) { if (start_partial_page != 0) {
m_kernel.MemoryManager().Close(start_partial_page, 1); m_system.Kernel().MemoryManager().Close(start_partial_page, 1);
} }
if (end_partial_page != 0) { if (end_partial_page != 0) {
m_kernel.MemoryManager().Close(end_partial_page, 1); m_system.Kernel().MemoryManager().Close(end_partial_page, 1);
} }
}; };
@ -4526,7 +4526,7 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size,
// Allocate the start page as needed. // Allocate the start page as needed.
if (aligned_src_start < mapping_src_start) { if (aligned_src_start < mapping_src_start) {
start_partial_page = start_partial_page =
m_kernel.MemoryManager().AllocateAndOpenContinuous(1, 1, m_allocate_option); m_system.Kernel().MemoryManager().AllocateAndOpenContinuous(1, 1, m_allocate_option);
R_UNLESS(start_partial_page != 0, ResultOutOfMemory); R_UNLESS(start_partial_page != 0, ResultOutOfMemory);
} }
@ -4534,7 +4534,7 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size,
if (mapping_src_end < aligned_src_end && if (mapping_src_end < aligned_src_end &&
(aligned_src_start < mapping_src_end || aligned_src_start == mapping_src_start)) { (aligned_src_start < mapping_src_end || aligned_src_start == mapping_src_start)) {
end_partial_page = end_partial_page =
m_kernel.MemoryManager().AllocateAndOpenContinuous(1, 1, m_allocate_option); m_system.Kernel().MemoryManager().AllocateAndOpenContinuous(1, 1, m_allocate_option);
R_UNLESS(end_partial_page != 0, ResultOutOfMemory); R_UNLESS(end_partial_page != 0, ResultOutOfMemory);
} }
@ -4560,7 +4560,7 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size,
// Map the start page, if we have one. // Map the start page, if we have one.
if (start_partial_page != 0) { if (start_partial_page != 0) {
// Ensure the page holds correct data. // Ensure the page holds correct data.
u8* const start_partial_virt = GetHeapVirtualPointer(m_kernel, start_partial_page); u8* const start_partial_virt = GetHeapVirtualPointer(m_system.Kernel(), start_partial_page);
if (send) { if (send) {
const size_t partial_offset = src_start - aligned_src_start; const size_t partial_offset = src_start - aligned_src_start;
size_t copy_size, clear_size; size_t copy_size, clear_size;
@ -4574,7 +4574,7 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size,
std::memset(start_partial_virt, fill_val, partial_offset); std::memset(start_partial_virt, fill_val, partial_offset);
std::memcpy(start_partial_virt + partial_offset, std::memcpy(start_partial_virt + partial_offset,
GetHeapVirtualPointer(m_kernel, cur_block_addr) + partial_offset, GetHeapVirtualPointer(m_system.Kernel(), cur_block_addr) + partial_offset,
copy_size); copy_size);
if (clear_size > 0) { if (clear_size > 0) {
std::memset(start_partial_virt + partial_offset + copy_size, fill_val, clear_size); std::memset(start_partial_virt + partial_offset + copy_size, fill_val, clear_size);
@ -4663,10 +4663,10 @@ Result KPageTableBase::SetupForIpcServer(KProcessAddress* out_addr, size_t size,
// Map the end page, if we have one. // Map the end page, if we have one.
if (end_partial_page != 0) { if (end_partial_page != 0) {
// Ensure the page holds correct data. // Ensure the page holds correct data.
u8* const end_partial_virt = GetHeapVirtualPointer(m_kernel, end_partial_page); u8* const end_partial_virt = GetHeapVirtualPointer(m_system.Kernel(), end_partial_page);
if (send) { if (send) {
const size_t copy_size = src_end - mapping_src_end; const size_t copy_size = src_end - mapping_src_end;
std::memcpy(end_partial_virt, GetHeapVirtualPointer(m_kernel, cur_block_addr), std::memcpy(end_partial_virt, GetHeapVirtualPointer(m_system.Kernel(), cur_block_addr),
copy_size); copy_size);
std::memset(end_partial_virt + copy_size, fill_val, PageSize - copy_size); std::memset(end_partial_virt + copy_size, fill_val, PageSize - copy_size);
} else { } else {
@ -5173,15 +5173,15 @@ Result KPageTableBase::MapPhysicalMemory(KProcessAddress address, size_t size) {
R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached);
// Allocate pages for the new memory. // Allocate pages for the new memory.
KPageGroup pg(m_kernel, m_block_info_manager); KPageGroup pg(m_system.Kernel(), m_block_info_manager);
R_TRY(m_kernel.MemoryManager().AllocateForProcess( R_TRY(m_system.Kernel().MemoryManager().AllocateForProcess(
std::addressof(pg), (size - mapped_size) / PageSize, m_allocate_option, std::addressof(pg), (size - mapped_size) / PageSize, m_allocate_option,
GetCurrentProcess(m_kernel).GetId(), m_heap_fill_value)); GetCurrentProcess(m_system.Kernel()).GetId(), m_heap_fill_value));
// If we fail in the next bit (or retry), we need to cleanup the pages. // If we fail in the next bit (or retry), we need to cleanup the pages.
auto pg_guard = SCOPE_GUARD { auto pg_guard = SCOPE_GUARD {
pg.OpenFirst(); pg.OpenFirst(m_system.Kernel());
pg.Close(); pg.Close(m_system.Kernel());
}; };
// Map the memory. // Map the memory.
@ -5304,12 +5304,12 @@ Result KPageTableBase::MapPhysicalMemory(KProcessAddress address, size_t size) {
} }
// Release any remaining unmapped memory. // Release any remaining unmapped memory.
m_kernel.MemoryManager().OpenFirst(pg_phys_addr, pg_pages); m_system.Kernel().MemoryManager().OpenFirst(pg_phys_addr, pg_pages);
m_kernel.MemoryManager().Close(pg_phys_addr, pg_pages); m_system.Kernel().MemoryManager().Close(pg_phys_addr, pg_pages);
for (++pg_it; pg_it != pg.end(); ++pg_it) { for (++pg_it; pg_it != pg.end(); ++pg_it) {
m_kernel.MemoryManager().OpenFirst(pg_it->GetAddress(), m_system.Kernel().MemoryManager().OpenFirst(pg_it->GetAddress(),
pg_it->GetNumPages()); pg_it->GetNumPages());
m_kernel.MemoryManager().Close(pg_it->GetAddress(), pg_it->GetNumPages()); m_system.Kernel().MemoryManager().Close(pg_it->GetAddress(), pg_it->GetNumPages());
} }
}; };
@ -5337,11 +5337,11 @@ Result KPageTableBase::MapPhysicalMemory(KProcessAddress address, size_t size) {
// While we have pages to map, map them. // While we have pages to map, map them.
{ {
// Create a page group for the current mapping range. // Create a page group for the current mapping range.
KPageGroup cur_pg(m_kernel, m_block_info_manager); KPageGroup cur_pg(m_system.Kernel(), m_block_info_manager);
{ {
ON_RESULT_FAILURE_2 { ON_RESULT_FAILURE_2 {
cur_pg.OpenFirst(); cur_pg.OpenFirst(m_system.Kernel());
cur_pg.Close(); cur_pg.Close(m_system.Kernel());
}; };
size_t remain_pages = map_pages; size_t remain_pages = map_pages;
@ -5706,9 +5706,9 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a
const bool separate_heap = operation == OperationType::UnmapPhysical; const bool separate_heap = operation == OperationType::UnmapPhysical;
// Ensure that any pages we track are closed on exit. // Ensure that any pages we track are closed on exit.
KPageGroup pages_to_close(m_kernel, this->GetBlockInfoManager()); KPageGroup pages_to_close(m_system.Kernel(), this->GetBlockInfoManager());
SCOPE_EXIT { SCOPE_EXIT {
pages_to_close.CloseAndReset(); pages_to_close.CloseAndReset(m_system.Kernel());
}; };
// Make a page group representing the region to unmap. // Make a page group representing the region to unmap.
@ -5727,7 +5727,7 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a
// Open references to pages, if we should. // Open references to pages, if we should.
if (this->IsHeapPhysicalAddress(phys_addr)) { if (this->IsHeapPhysicalAddress(phys_addr)) {
m_kernel.MemoryManager().Open(phys_addr, num_pages); m_system.Kernel().MemoryManager().Open(phys_addr, num_pages);
} }
R_SUCCEED(); R_SUCCEED();
@ -5767,7 +5767,7 @@ Result KPageTableBase::Operate(PageLinkedList* page_list, KProcessAddress virt_a
const bool separate_heap = operation == OperationType::MapFirstGroupPhysical; const bool separate_heap = operation == OperationType::MapFirstGroupPhysical;
// We want to maintain a new reference to every page in the group. // We want to maintain a new reference to every page in the group.
KScopedPageGroup spg(page_group, operation == OperationType::MapGroup); KScopedPageGroup spg(m_system.Kernel(), page_group, operation == OperationType::MapGroup);
for (const auto& node : page_group) { for (const auto& node : page_group) {
const size_t size{node.GetNumPages() * PageSize}; const size_t size{node.GetNumPages() * PageSize};

View File

@ -61,14 +61,12 @@ public:
class MemoryRange { class MemoryRange {
private: private:
KernelCore& m_kernel; KPhysicalAddress m_address = 0;
KPhysicalAddress m_address; size_t m_size = 0;
size_t m_size; bool m_heap = false;
bool m_heap;
public: public:
explicit MemoryRange(KernelCore& kernel) explicit MemoryRange() : m_address(0), m_size(0), m_heap(false) {}
: m_kernel(kernel), m_address(0), m_size(0), m_heap(false) {}
void Set(KPhysicalAddress address, size_t size, bool heap) { void Set(KPhysicalAddress address, size_t size, bool heap) {
m_address = address; m_address = address;
@ -86,8 +84,8 @@ public:
return m_heap; return m_heap;
} }
void Open(); void Open(KernelCore& kernel);
void Close(); void Close(KernelCore& kernel);
}; };
protected: protected:
@ -189,7 +187,6 @@ private:
}; };
private: private:
KernelCore& m_kernel;
Core::System& m_system; Core::System& m_system;
KProcessAddress m_address_space_start{}; KProcessAddress m_address_space_start{};
KProcessAddress m_address_space_end{}; KProcessAddress m_address_space_end{};
@ -329,35 +326,35 @@ protected:
bool IsLinearMappedPhysicalAddress(KPhysicalAddress phys_addr) { bool IsLinearMappedPhysicalAddress(KPhysicalAddress phys_addr) {
ASSERT(this->IsLockedByCurrentThread()); ASSERT(this->IsLockedByCurrentThread());
return m_kernel.MemoryLayout().IsLinearMappedPhysicalAddress( return m_system.Kernel().MemoryLayout().IsLinearMappedPhysicalAddress(
m_cached_physical_linear_region, phys_addr); m_cached_physical_linear_region, phys_addr);
} }
bool IsLinearMappedPhysicalAddress(KPhysicalAddress phys_addr, size_t size) { bool IsLinearMappedPhysicalAddress(KPhysicalAddress phys_addr, size_t size) {
ASSERT(this->IsLockedByCurrentThread()); ASSERT(this->IsLockedByCurrentThread());
return m_kernel.MemoryLayout().IsLinearMappedPhysicalAddress( return m_system.Kernel().MemoryLayout().IsLinearMappedPhysicalAddress(
m_cached_physical_linear_region, phys_addr, size); m_cached_physical_linear_region, phys_addr, size);
} }
bool IsHeapPhysicalAddress(KPhysicalAddress phys_addr) { bool IsHeapPhysicalAddress(KPhysicalAddress phys_addr) {
ASSERT(this->IsLockedByCurrentThread()); ASSERT(this->IsLockedByCurrentThread());
return m_kernel.MemoryLayout().IsHeapPhysicalAddress(m_cached_physical_heap_region, return m_system.Kernel().MemoryLayout().IsHeapPhysicalAddress(m_cached_physical_heap_region,
phys_addr); phys_addr);
} }
bool IsHeapPhysicalAddress(KPhysicalAddress phys_addr, size_t size) { bool IsHeapPhysicalAddress(KPhysicalAddress phys_addr, size_t size) {
ASSERT(this->IsLockedByCurrentThread()); ASSERT(this->IsLockedByCurrentThread());
return m_kernel.MemoryLayout().IsHeapPhysicalAddress(m_cached_physical_heap_region, return m_system.Kernel().MemoryLayout().IsHeapPhysicalAddress(m_cached_physical_heap_region,
phys_addr, size); phys_addr, size);
} }
bool IsHeapPhysicalAddressForFinalize(KPhysicalAddress phys_addr) { bool IsHeapPhysicalAddressForFinalize(KPhysicalAddress phys_addr) {
ASSERT(!this->IsLockedByCurrentThread()); ASSERT(!this->IsLockedByCurrentThread());
return m_kernel.MemoryLayout().IsHeapPhysicalAddress(m_cached_physical_heap_region, return m_system.Kernel().MemoryLayout().IsHeapPhysicalAddress(m_cached_physical_heap_region,
phys_addr); phys_addr);
} }
@ -744,15 +741,15 @@ public:
// Member heap // Member heap
u8* GetHeapVirtualPointer(KPhysicalAddress addr) { u8* GetHeapVirtualPointer(KPhysicalAddress addr) {
return GetHeapVirtualPointer(m_kernel, addr); return GetHeapVirtualPointer(m_system.Kernel(), addr);
} }
KPhysicalAddress GetHeapPhysicalAddress(KVirtualAddress addr) { KPhysicalAddress GetHeapPhysicalAddress(KVirtualAddress addr) {
return GetHeapPhysicalAddress(m_kernel, addr); return GetHeapPhysicalAddress(m_system.Kernel(), addr);
} }
KVirtualAddress GetHeapVirtualAddress(KPhysicalAddress addr) { KVirtualAddress GetHeapVirtualAddress(KPhysicalAddress addr) {
return GetHeapVirtualAddress(m_kernel, addr); return GetHeapVirtualAddress(m_system.Kernel(), addr);
} }
// TODO: GetPageTableVirtualAddress // TODO: GetPageTableVirtualAddress

View File

@ -993,7 +993,7 @@ Result KProcess::Run(s32 priority, size_t stack_size) {
// Add the thread to our handle table. // Add the thread to our handle table.
Handle thread_handle; Handle thread_handle;
R_TRY(m_handle_table.Add(std::addressof(thread_handle), main_thread)); R_TRY(m_handle_table.Add(m_kernel, std::addressof(thread_handle), main_thread));
// Set the thread arguments. // Set the thread arguments.
main_thread->GetContext().r[0] = 0; main_thread->GetContext().r[0] = 0;

View File

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2014 Citra Emulator Project // SPDX-FileCopyrightText: 2014 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -68,7 +71,7 @@ Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory, KProcess* ow
void KSharedMemory::Finalize() { void KSharedMemory::Finalize() {
// Close and finalize the page group. // Close and finalize the page group.
m_page_group->Close(); m_page_group->Close(m_kernel);
m_page_group->Finalize(); m_page_group->Finalize();
// Release the memory reservation. // Release the memory reservation.

View File

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -53,7 +56,7 @@ void KTransferMemory::Finalize() {
} }
// Close the page group. // Close the page group.
m_page_group->Close(); m_page_group->Close(m_kernel);
m_page_group->Finalize(); m_page_group->Finalize();
} }

View File

@ -259,7 +259,7 @@ struct KernelCore::Impl {
preemption_event = Core::Timing::CreateEvent("PreemptionCallback", [this, &kernel](s64 time, std::chrono::nanoseconds) -> std::optional<std::chrono::nanoseconds> { preemption_event = Core::Timing::CreateEvent("PreemptionCallback", [this, &kernel](s64 time, std::chrono::nanoseconds) -> std::optional<std::chrono::nanoseconds> {
{ {
KScopedSchedulerLock lock(kernel); KScopedSchedulerLock lock(kernel);
global_scheduler_context->PreemptThreads(); global_scheduler_context->PreemptThreads(kernel);
} }
return std::nullopt; return std::nullopt;
}); });

View File

@ -17,14 +17,15 @@
namespace Kernel { namespace Kernel {
PhysicalCore::PhysicalCore(KernelCore& kernel, std::size_t core_index) PhysicalCore::PhysicalCore(KernelCore& kernel, std::size_t core_index)
: m_kernel{kernel}, m_core_index{core_index} { : m_core_index{core_index}
{
m_is_single_core = !kernel.IsMulticore(); m_is_single_core = !kernel.IsMulticore();
} }
PhysicalCore::~PhysicalCore() = default; PhysicalCore::~PhysicalCore() = default;
void PhysicalCore::RunThread(Kernel::KThread* thread) { void PhysicalCore::RunThread(KernelCore& kernel, Kernel::KThread* thread) {
auto* process = thread->GetOwnerProcess(); auto* process = thread->GetOwnerProcess();
auto& system = m_kernel.System(); auto& system = kernel.System();
auto* interface = process->GetArmInterface(m_core_index); auto* interface = process->GetArmInterface(m_core_index);
interface->Initialize(); interface->Initialize();
@ -208,8 +209,8 @@ void PhysicalCore::CloneFpuStatus(KThread* dst) const {
dst->GetContext().fpsr = ctx.fpsr; dst->GetContext().fpsr = ctx.fpsr;
} }
void PhysicalCore::LogBacktrace() { void PhysicalCore::LogBacktrace(KernelCore& kernel) {
auto* process = GetCurrentProcessPointer(m_kernel); auto* process = GetCurrentProcessPointer(kernel);
if (!process) { if (!process) {
return; return;
} }

View File

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -30,7 +33,7 @@ public:
YUZU_NON_MOVEABLE(PhysicalCore); YUZU_NON_MOVEABLE(PhysicalCore);
// Execute guest code running on the given thread. // Execute guest code running on the given thread.
void RunThread(KThread* thread); void RunThread(KernelCore& kernel, KThread* thread);
// Copy context from thread to current core. // Copy context from thread to current core.
void LoadContext(const KThread* thread); void LoadContext(const KThread* thread);
@ -44,7 +47,7 @@ public:
void CloneFpuStatus(KThread* dst) const; void CloneFpuStatus(KThread* dst) const;
// Log backtrace of current processor state. // Log backtrace of current processor state.
void LogBacktrace(); void LogBacktrace(KernelCore& kernel);
// Wait for an interrupt. // Wait for an interrupt.
void Idle(); void Idle();
@ -63,9 +66,7 @@ public:
} }
private: private:
KernelCore& m_kernel;
const std::size_t m_core_index; const std::size_t m_core_index;
std::mutex m_guard; std::mutex m_guard;
std::condition_variable m_on_interrupt; std::condition_variable m_on_interrupt;
Core::ArmInterface* m_arm_interface{}; Core::ArmInterface* m_arm_interface{};

View File

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -103,7 +106,7 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) {
handle_debug_buffer(info1, info2); handle_debug_buffer(info1, info2);
system.CurrentPhysicalCore().LogBacktrace(); system.CurrentPhysicalCore().LogBacktrace(system.Kernel());
} }
const bool is_hbl = GetCurrentProcess(system.Kernel()).IsHbl(); const bool is_hbl = GetCurrentProcess(system.Kernel()).IsHbl();

View File

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -14,8 +17,8 @@ namespace Kernel::Svc {
Result SendSyncRequestLight(Core::System& system, Handle session_handle, u32* args) { Result SendSyncRequestLight(Core::System& system, Handle session_handle, u32* args) {
// Get the light client session from its handle. // Get the light client session from its handle.
KScopedAutoObject session = GetCurrentProcess(system.Kernel()) KScopedAutoObject session = GetCurrentProcess(system.Kernel())
.GetHandleTable() .GetHandleTable()
.GetObject<KLightClientSession>(session_handle); .GetObject<KLightClientSession>(system.Kernel(), session_handle);
R_UNLESS(session.IsNotNull(), ResultInvalidHandle); R_UNLESS(session.IsNotNull(), ResultInvalidHandle);
// Send the request. // Send the request.
@ -27,8 +30,8 @@ Result SendSyncRequestLight(Core::System& system, Handle session_handle, u32* ar
Result ReplyAndReceiveLight(Core::System& system, Handle session_handle, u32* args) { Result ReplyAndReceiveLight(Core::System& system, Handle session_handle, u32* args) {
// Get the light server session from its handle. // Get the light server session from its handle.
KScopedAutoObject session = GetCurrentProcess(system.Kernel()) KScopedAutoObject session = GetCurrentProcess(system.Kernel())
.GetHandleTable() .GetHandleTable()
.GetObject<KLightServerSession>(session_handle); .GetObject<KLightServerSession>(system.Kernel(), session_handle);
R_UNLESS(session.IsNotNull(), ResultInvalidHandle); R_UNLESS(session.IsNotNull(), ResultInvalidHandle);
// Handle the request. // Handle the request.