forked from eden-emu/eden
		
	kernel: More accurately reserve and release resources
This commit is contained in:
		
							parent
							
								
									48b09cc56d
								
							
						
					
					
						commit
						faae6b5595
					
				
					 6 changed files with 42 additions and 14 deletions
				
			
		|  | @ -141,11 +141,17 @@ struct KernelCore::Impl { | ||||||
|         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 700).IsSuccess()); |         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 700).IsSuccess()); | ||||||
|         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200) |         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200) | ||||||
|                    .IsSuccess()); |                    .IsSuccess()); | ||||||
|         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 900).IsSuccess()); |         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 933).IsSuccess()); | ||||||
| 
 | 
 | ||||||
|         if (!system_resource_limit->Reserve(LimitableResource::PhysicalMemory, 0x60000)) { |         // Derived from recent software updates. The kernel reserves 27MB
 | ||||||
|  |         constexpr u64 kernel_size{0x1b00000}; | ||||||
|  |         if (!system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size)) { | ||||||
|             UNREACHABLE(); |             UNREACHABLE(); | ||||||
|         } |         } | ||||||
|  |         // Reserve secure applet memory, introduced in firmware 5.0.0
 | ||||||
|  |         constexpr u64 secure_applet_memory_size{0x400000}; | ||||||
|  |         ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory, | ||||||
|  |                                               secure_applet_memory_size)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void InitializePreemption(KernelCore& kernel) { |     void InitializePreemption(KernelCore& kernel) { | ||||||
|  | @ -302,8 +308,11 @@ struct KernelCore::Impl { | ||||||
|         // Allocate slab heaps
 |         // Allocate slab heaps
 | ||||||
|         user_slab_heap_pages = std::make_unique<Memory::SlabHeap<Memory::Page>>(); |         user_slab_heap_pages = std::make_unique<Memory::SlabHeap<Memory::Page>>(); | ||||||
| 
 | 
 | ||||||
|  |         constexpr u64 user_slab_heap_size{0x1ef000}; | ||||||
|  |         // Reserve slab heaps
 | ||||||
|  |         ASSERT( | ||||||
|  |             system_resource_limit->Reserve(LimitableResource::PhysicalMemory, user_slab_heap_size)); | ||||||
|         // Initialize slab heaps
 |         // Initialize slab heaps
 | ||||||
|         constexpr u64 user_slab_heap_size{0x3de000}; |  | ||||||
|         user_slab_heap_pages->Initialize( |         user_slab_heap_pages->Initialize( | ||||||
|             system.DeviceMemory().GetPointer(Core::DramMemoryMap::SlabHeapBase), |             system.DeviceMemory().GetPointer(Core::DramMemoryMap::SlabHeapBase), | ||||||
|             user_slab_heap_size); |             user_slab_heap_size); | ||||||
|  |  | ||||||
|  | @ -39,6 +39,7 @@ namespace { | ||||||
|  */ |  */ | ||||||
| void SetupMainThread(Core::System& system, Process& owner_process, u32 priority, VAddr stack_top) { | void SetupMainThread(Core::System& system, Process& owner_process, u32 priority, VAddr stack_top) { | ||||||
|     const VAddr entry_point = owner_process.PageTable().GetCodeRegionStart(); |     const VAddr entry_point = owner_process.PageTable().GetCodeRegionStart(); | ||||||
|  |     ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::Threads, 1)); | ||||||
|     auto thread_res = KThread::Create(system, ThreadType::User, "main", entry_point, priority, 0, |     auto thread_res = KThread::Create(system, ThreadType::User, "main", entry_point, priority, 0, | ||||||
|                                       owner_process.GetIdealCoreId(), stack_top, &owner_process); |                                       owner_process.GetIdealCoreId(), stack_top, &owner_process); | ||||||
| 
 | 
 | ||||||
|  | @ -279,7 +280,7 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, | ||||||
|     if (!memory_reservation.Succeeded()) { |     if (!memory_reservation.Succeeded()) { | ||||||
|         LOG_ERROR(Kernel, "Could not reserve process memory requirements of size {:X} bytes", |         LOG_ERROR(Kernel, "Could not reserve process memory requirements of size {:X} bytes", | ||||||
|                   code_size + system_resource_size); |                   code_size + system_resource_size); | ||||||
|         return ERR_RESOURCE_LIMIT_EXCEEDED; |         return ResultResourceLimitedExceeded; | ||||||
|     } |     } | ||||||
|     // Initialize proces address space
 |     // Initialize proces address space
 | ||||||
|     if (const ResultCode result{ |     if (const ResultCode result{ | ||||||
|  |  | ||||||
|  | @ -4,15 +4,23 @@ | ||||||
| 
 | 
 | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
| #include "core/hle/kernel/client_session.h" | #include "core/hle/kernel/client_session.h" | ||||||
|  | #include "core/hle/kernel/k_scoped_resource_reservation.h" | ||||||
| #include "core/hle/kernel/server_session.h" | #include "core/hle/kernel/server_session.h" | ||||||
| #include "core/hle/kernel/session.h" | #include "core/hle/kernel/session.h" | ||||||
| 
 | 
 | ||||||
| namespace Kernel { | namespace Kernel { | ||||||
| 
 | 
 | ||||||
| Session::Session(KernelCore& kernel) : KSynchronizationObject{kernel} {} | Session::Session(KernelCore& kernel) : KSynchronizationObject{kernel} {} | ||||||
| Session::~Session() = default; | Session::~Session() { | ||||||
|  |     // Release reserved resource when the Session pair was created.
 | ||||||
|  |     kernel.GetSystemResourceLimit()->Release(LimitableResource::Sessions, 1); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| Session::SessionPair Session::Create(KernelCore& kernel, std::string name) { | Session::SessionPair Session::Create(KernelCore& kernel, std::string name) { | ||||||
|  |     // Reserve a new session from the resource limit.
 | ||||||
|  |     KScopedResourceReservation session_reservation(kernel.GetSystemResourceLimit(), | ||||||
|  |                                                    LimitableResource::Sessions); | ||||||
|  |     ASSERT(session_reservation.Succeeded()); | ||||||
|     auto session{std::make_shared<Session>(kernel)}; |     auto session{std::make_shared<Session>(kernel)}; | ||||||
|     auto client_session{Kernel::ClientSession::Create(kernel, session, name + "_Client").Unwrap()}; |     auto client_session{Kernel::ClientSession::Create(kernel, session, name + "_Client").Unwrap()}; | ||||||
|     auto server_session{Kernel::ServerSession::Create(kernel, session, name + "_Server").Unwrap()}; |     auto server_session{Kernel::ServerSession::Create(kernel, session, name + "_Server").Unwrap()}; | ||||||
|  | @ -21,6 +29,7 @@ Session::SessionPair Session::Create(KernelCore& kernel, std::string name) { | ||||||
|     session->client = client_session; |     session->client = client_session; | ||||||
|     session->server = server_session; |     session->server = server_session; | ||||||
| 
 | 
 | ||||||
|  |     session_reservation.Commit(); | ||||||
|     return std::make_pair(std::move(client_session), std::move(server_session)); |     return std::make_pair(std::move(client_session), std::move(server_session)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -14,7 +14,9 @@ namespace Kernel { | ||||||
| SharedMemory::SharedMemory(KernelCore& kernel, Core::DeviceMemory& device_memory) | SharedMemory::SharedMemory(KernelCore& kernel, Core::DeviceMemory& device_memory) | ||||||
|     : Object{kernel}, device_memory{device_memory} {} |     : Object{kernel}, device_memory{device_memory} {} | ||||||
| 
 | 
 | ||||||
| SharedMemory::~SharedMemory() = default; | SharedMemory::~SharedMemory() { | ||||||
|  |     kernel.GetSystemResourceLimit()->Release(LimitableResource::PhysicalMemory, size); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| std::shared_ptr<SharedMemory> SharedMemory::Create( | std::shared_ptr<SharedMemory> SharedMemory::Create( | ||||||
|     KernelCore& kernel, Core::DeviceMemory& device_memory, Process* owner_process, |     KernelCore& kernel, Core::DeviceMemory& device_memory, Process* owner_process, | ||||||
|  |  | ||||||
|  | @ -138,6 +138,7 @@ ResultCode MapUnmapMemorySanityChecks(const Memory::PageTable& manager, VAddr ds | ||||||
| enum class ResourceLimitValueType { | enum class ResourceLimitValueType { | ||||||
|     CurrentValue, |     CurrentValue, | ||||||
|     LimitValue, |     LimitValue, | ||||||
|  |     PeakValue, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_limit, | ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_limit, | ||||||
|  | @ -160,11 +161,17 @@ ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_ | ||||||
|         return ResultInvalidHandle; |         return ResultInvalidHandle; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (value_type == ResourceLimitValueType::CurrentValue) { |     switch (value_type) { | ||||||
|  |     case ResourceLimitValueType::CurrentValue: | ||||||
|         return MakeResult(resource_limit_object->GetCurrentValue(type)); |         return MakeResult(resource_limit_object->GetCurrentValue(type)); | ||||||
|     } |     case ResourceLimitValueType::LimitValue: | ||||||
| 
 |  | ||||||
|         return MakeResult(resource_limit_object->GetLimitValue(type)); |         return MakeResult(resource_limit_object->GetLimitValue(type)); | ||||||
|  |     case ResourceLimitValueType::PeakValue: | ||||||
|  |         return MakeResult(resource_limit_object->GetPeakValue(type)); | ||||||
|  |     default: | ||||||
|  |         LOG_ERROR(Kernel_SVC, "Invalid resource value_type: '{}'", value_type); | ||||||
|  |         return ResultInvalidEnumValue; | ||||||
|  |     } | ||||||
| } | } | ||||||
| } // Anonymous namespace
 | } // Anonymous namespace
 | ||||||
| 
 | 
 | ||||||
|  | @ -314,8 +321,6 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle, | ||||||
|         return ResultNotFound; |         return ResultNotFound; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(LimitableResource::Sessions, 1)); |  | ||||||
| 
 |  | ||||||
|     auto client_port = it->second; |     auto client_port = it->second; | ||||||
| 
 | 
 | ||||||
|     std::shared_ptr<ClientSession> client_session; |     std::shared_ptr<ClientSession> client_session; | ||||||
|  | @ -1522,7 +1527,7 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e | ||||||
|         system.CoreTiming().GetGlobalTimeNs().count() + 100000000); |         system.CoreTiming().GetGlobalTimeNs().count() + 100000000); | ||||||
|     if (!thread_reservation.Succeeded()) { |     if (!thread_reservation.Succeeded()) { | ||||||
|         LOG_ERROR(Kernel_SVC, "Could not reserve a new thread"); |         LOG_ERROR(Kernel_SVC, "Could not reserve a new thread"); | ||||||
|         return ERR_RESOURCE_LIMIT_EXCEEDED; |         return ResultResourceLimitedExceeded; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::shared_ptr<KThread> thread; |     std::shared_ptr<KThread> thread; | ||||||
|  | @ -1896,7 +1901,7 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd | ||||||
|                                                  LimitableResource::TransferMemory); |                                                  LimitableResource::TransferMemory); | ||||||
|     if (!trmem_reservation.Succeeded()) { |     if (!trmem_reservation.Succeeded()) { | ||||||
|         LOG_ERROR(Kernel_SVC, "Could not reserve a new transfer memory"); |         LOG_ERROR(Kernel_SVC, "Could not reserve a new transfer memory"); | ||||||
|         return ERR_RESOURCE_LIMIT_EXCEEDED; |         return ResultResourceLimitedExceeded; | ||||||
|     } |     } | ||||||
|     auto transfer_mem_handle = TransferMemory::Create(kernel, system.Memory(), addr, size, perms); |     auto transfer_mem_handle = TransferMemory::Create(kernel, system.Memory(), addr, size, perms); | ||||||
| 
 | 
 | ||||||
|  | @ -2026,7 +2031,7 @@ static ResultCode SignalEvent(Core::System& system, Handle event_handle) { | ||||||
|                                                  LimitableResource::Events); |                                                  LimitableResource::Events); | ||||||
|     if (!event_reservation.Succeeded()) { |     if (!event_reservation.Succeeded()) { | ||||||
|         LOG_ERROR(Kernel, "Could not reserve a new event"); |         LOG_ERROR(Kernel, "Could not reserve a new event"); | ||||||
|         return ERR_RESOURCE_LIMIT_EXCEEDED; |         return ResultResourceLimitedExceeded; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Get the writable event.
 |     // Get the writable event.
 | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
| // Licensed under GPLv2 or any later version
 | // Licensed under GPLv2 or any later version
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
|  | #include "core/hle/kernel/k_resource_limit.h" | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
| #include "core/hle/kernel/memory/page_table.h" | #include "core/hle/kernel/memory/page_table.h" | ||||||
| #include "core/hle/kernel/process.h" | #include "core/hle/kernel/process.h" | ||||||
|  | @ -17,6 +18,7 @@ TransferMemory::TransferMemory(KernelCore& kernel, Core::Memory::Memory& memory) | ||||||
| TransferMemory::~TransferMemory() { | TransferMemory::~TransferMemory() { | ||||||
|     // Release memory region when transfer memory is destroyed
 |     // Release memory region when transfer memory is destroyed
 | ||||||
|     Reset(); |     Reset(); | ||||||
|  |     owner_process->GetResourceLimit()->Release(LimitableResource::TransferMemory, 1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::shared_ptr<TransferMemory> TransferMemory::Create(KernelCore& kernel, | std::shared_ptr<TransferMemory> TransferMemory::Create(KernelCore& kernel, | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 ameerj
						ameerj