summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/k_system_resource.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/k_system_resource.cpp')
-rw-r--r--src/core/hle/kernel/k_system_resource.cpp87
1 files changed, 81 insertions, 6 deletions
diff --git a/src/core/hle/kernel/k_system_resource.cpp b/src/core/hle/kernel/k_system_resource.cpp
index e6c8d589a..07e92aa80 100644
--- a/src/core/hle/kernel/k_system_resource.cpp
+++ b/src/core/hle/kernel/k_system_resource.cpp
@@ -1,25 +1,100 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#include "core/core.h"
+#include "core/hle/kernel/k_scoped_resource_reservation.h"
#include "core/hle/kernel/k_system_resource.h"
namespace Kernel {
Result KSecureSystemResource::Initialize(size_t size, KResourceLimit* resource_limit,
KMemoryManager::Pool pool) {
- // Unimplemented
- UNREACHABLE();
+ // Set members.
+ m_resource_limit = resource_limit;
+ m_resource_size = size;
+ m_resource_pool = pool;
+
+ // Determine required size for our secure resource.
+ const size_t secure_size = this->CalculateRequiredSecureMemorySize();
+
+ // Reserve memory for our secure resource.
+ KScopedResourceReservation memory_reservation(
+ m_resource_limit, Svc::LimitableResource::PhysicalMemoryMax, secure_size);
+ R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached);
+
+ // Allocate secure memory.
+ R_TRY(KSystemControl::AllocateSecureMemory(m_kernel, std::addressof(m_resource_address),
+ m_resource_size, static_cast<u32>(m_resource_pool)));
+ ASSERT(m_resource_address != 0);
+
+ // Ensure we clean up the secure memory, if we fail past this point.
+ ON_RESULT_FAILURE {
+ KSystemControl::FreeSecureMemory(m_kernel, m_resource_address, m_resource_size,
+ static_cast<u32>(m_resource_pool));
+ };
+
+ // Check that our allocation is bigger than the reference counts needed for it.
+ const size_t rc_size =
+ Common::AlignUp(KPageTableSlabHeap::CalculateReferenceCountSize(m_resource_size), PageSize);
+ R_UNLESS(m_resource_size > rc_size, ResultOutOfMemory);
+
+ // Get resource pointer.
+ KPhysicalAddress resource_paddr =
+ KPageTable::GetHeapPhysicalAddress(m_kernel.MemoryLayout(), m_resource_address);
+ auto* resource =
+ m_kernel.System().DeviceMemory().GetPointer<KPageTableManager::RefCount>(resource_paddr);
+
+ // Initialize slab heaps.
+ m_dynamic_page_manager.Initialize(m_resource_address + rc_size, m_resource_size - rc_size,
+ PageSize);
+ m_page_table_heap.Initialize(std::addressof(m_dynamic_page_manager), 0, resource);
+ m_memory_block_heap.Initialize(std::addressof(m_dynamic_page_manager), 0);
+ m_block_info_heap.Initialize(std::addressof(m_dynamic_page_manager), 0);
+
+ // Initialize managers.
+ m_page_table_manager.Initialize(std::addressof(m_dynamic_page_manager),
+ std::addressof(m_page_table_heap));
+ m_memory_block_slab_manager.Initialize(std::addressof(m_dynamic_page_manager),
+ std::addressof(m_memory_block_heap));
+ m_block_info_manager.Initialize(std::addressof(m_dynamic_page_manager),
+ std::addressof(m_block_info_heap));
+
+ // Set our managers.
+ this->SetManagers(m_memory_block_slab_manager, m_block_info_manager, m_page_table_manager);
+
+ // Commit the memory reservation.
+ memory_reservation.Commit();
+
+ // Open reference to our resource limit.
+ m_resource_limit->Open();
+
+ // Set ourselves as initialized.
+ m_is_initialized = true;
+
+ R_SUCCEED();
}
void KSecureSystemResource::Finalize() {
- // Unimplemented
- UNREACHABLE();
+ // Check that we have no outstanding allocations.
+ ASSERT(m_memory_block_slab_manager.GetUsed() == 0);
+ ASSERT(m_block_info_manager.GetUsed() == 0);
+ ASSERT(m_page_table_manager.GetUsed() == 0);
+
+ // Free our secure memory.
+ KSystemControl::FreeSecureMemory(m_kernel, m_resource_address, m_resource_size,
+ static_cast<u32>(m_resource_pool));
+
+ // Release the memory reservation.
+ m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax,
+ this->CalculateRequiredSecureMemorySize());
+
+ // Close reference to our resource limit.
+ m_resource_limit->Close();
}
size_t KSecureSystemResource::CalculateRequiredSecureMemorySize(size_t size,
KMemoryManager::Pool pool) {
- // Unimplemented
- UNREACHABLE();
+ return KSystemControl::CalculateRequiredSecureMemorySize(size, static_cast<u32>(pool));
}
} // namespace Kernel