k_system_resource.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "core/core.h"
  4. #include "core/hle/kernel/k_scoped_resource_reservation.h"
  5. #include "core/hle/kernel/k_system_resource.h"
  6. namespace Kernel {
  7. Result KSecureSystemResource::Initialize(size_t size, KResourceLimit* resource_limit,
  8. KMemoryManager::Pool pool) {
  9. // Set members.
  10. m_resource_limit = resource_limit;
  11. m_resource_size = size;
  12. m_resource_pool = pool;
  13. // Determine required size for our secure resource.
  14. const size_t secure_size = this->CalculateRequiredSecureMemorySize();
  15. // Reserve memory for our secure resource.
  16. KScopedResourceReservation memory_reservation(
  17. m_resource_limit, Svc::LimitableResource::PhysicalMemoryMax, secure_size);
  18. R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached);
  19. // Allocate secure memory.
  20. R_TRY(KSystemControl::AllocateSecureMemory(m_kernel, std::addressof(m_resource_address),
  21. m_resource_size, static_cast<u32>(m_resource_pool)));
  22. ASSERT(m_resource_address != 0);
  23. // Ensure we clean up the secure memory, if we fail past this point.
  24. ON_RESULT_FAILURE {
  25. KSystemControl::FreeSecureMemory(m_kernel, m_resource_address, m_resource_size,
  26. static_cast<u32>(m_resource_pool));
  27. };
  28. // Check that our allocation is bigger than the reference counts needed for it.
  29. const size_t rc_size =
  30. Common::AlignUp(KPageTableSlabHeap::CalculateReferenceCountSize(m_resource_size), PageSize);
  31. R_UNLESS(m_resource_size > rc_size, ResultOutOfMemory);
  32. // Get resource pointer.
  33. KPhysicalAddress resource_paddr =
  34. KPageTable::GetHeapPhysicalAddress(m_kernel, m_resource_address);
  35. auto* resource =
  36. m_kernel.System().DeviceMemory().GetPointer<KPageTableManager::RefCount>(resource_paddr);
  37. // Initialize slab heaps.
  38. m_dynamic_page_manager.Initialize(m_resource_address + rc_size, m_resource_size - rc_size,
  39. PageSize);
  40. m_page_table_heap.Initialize(std::addressof(m_dynamic_page_manager), 0, resource);
  41. m_memory_block_heap.Initialize(std::addressof(m_dynamic_page_manager), 0);
  42. m_block_info_heap.Initialize(std::addressof(m_dynamic_page_manager), 0);
  43. // Initialize managers.
  44. m_page_table_manager.Initialize(std::addressof(m_dynamic_page_manager),
  45. std::addressof(m_page_table_heap));
  46. m_memory_block_slab_manager.Initialize(std::addressof(m_dynamic_page_manager),
  47. std::addressof(m_memory_block_heap));
  48. m_block_info_manager.Initialize(std::addressof(m_dynamic_page_manager),
  49. std::addressof(m_block_info_heap));
  50. // Set our managers.
  51. this->SetManagers(m_memory_block_slab_manager, m_block_info_manager, m_page_table_manager);
  52. // Commit the memory reservation.
  53. memory_reservation.Commit();
  54. // Open reference to our resource limit.
  55. m_resource_limit->Open();
  56. // Set ourselves as initialized.
  57. m_is_initialized = true;
  58. R_SUCCEED();
  59. }
  60. void KSecureSystemResource::Finalize() {
  61. // Check that we have no outstanding allocations.
  62. ASSERT(m_memory_block_slab_manager.GetUsed() == 0);
  63. ASSERT(m_block_info_manager.GetUsed() == 0);
  64. ASSERT(m_page_table_manager.GetUsed() == 0);
  65. // Free our secure memory.
  66. KSystemControl::FreeSecureMemory(m_kernel, m_resource_address, m_resource_size,
  67. static_cast<u32>(m_resource_pool));
  68. // Release the memory reservation.
  69. m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax,
  70. this->CalculateRequiredSecureMemorySize());
  71. // Close reference to our resource limit.
  72. m_resource_limit->Close();
  73. }
  74. size_t KSecureSystemResource::CalculateRequiredSecureMemorySize(size_t size,
  75. KMemoryManager::Pool pool) {
  76. return KSystemControl::CalculateRequiredSecureMemorySize(size, static_cast<u32>(pool));
  77. }
  78. } // namespace Kernel