kernel/process: Replace process resource limit instance with the kernel's resource limit
This commit addresses the inaccurate behavior of kernel processes creating their own resource limit, rather than utilizing the kernel's system-wide resource limit instance.
This commit is contained in:
		| @@ -67,8 +67,13 @@ struct KernelCore::Impl { | ||||
|         is_phantom_mode_for_singlecore = false; | ||||
|  | ||||
|         InitializePhysicalCores(); | ||||
|         InitializeSystemResourceLimit(kernel, system); | ||||
|         InitializeMemoryLayout(); | ||||
|  | ||||
|         // Derive the initial memory layout from the emulated board | ||||
|         KMemoryLayout memory_layout; | ||||
|         DeriveInitialMemoryLayout(memory_layout); | ||||
|         InitializeMemoryLayout(memory_layout); | ||||
|         InitializeSystemResourceLimit(kernel, system, memory_layout); | ||||
|         InitializeSlabHeaps(); | ||||
|         InitializeSchedulers(); | ||||
|         InitializeSuspendThreads(); | ||||
|         InitializePreemption(kernel); | ||||
| @@ -137,27 +142,32 @@ struct KernelCore::Impl { | ||||
|     } | ||||
|  | ||||
|     // Creates the default system resource limit | ||||
|     void InitializeSystemResourceLimit(KernelCore& kernel, Core::System& system) { | ||||
|     void InitializeSystemResourceLimit(KernelCore& kernel, Core::System& system, | ||||
|                                        const KMemoryLayout& memory_layout) { | ||||
|         system_resource_limit = std::make_shared<KResourceLimit>(kernel, system); | ||||
|         const auto [total_size, kernel_size] = memory_layout.GetTotalAndKernelMemorySizes(); | ||||
|  | ||||
|         // If setting the default system values fails, then something seriously wrong has occurred. | ||||
|         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, 0x100000000) | ||||
|         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, total_size) | ||||
|                    .IsSuccess()); | ||||
|         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess()); | ||||
|         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 900).IsSuccess()); | ||||
|         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200) | ||||
|                    .IsSuccess()); | ||||
|         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 1133).IsSuccess()); | ||||
|         system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size); | ||||
|  | ||||
|         // Derived from recent software updates. The kernel reserves 27MB | ||||
|         constexpr u64 kernel_size{0x1b00000}; | ||||
|         if (!system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size)) { | ||||
|             UNREACHABLE(); | ||||
|         } | ||||
|         // Reserve secure applet memory, introduced in firmware 5.0.0 | ||||
|         constexpr u64 secure_applet_memory_size{0x400000}; | ||||
|         constexpr u64 secure_applet_memory_size{Common::Size_4_MB}; | ||||
|         ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory, | ||||
|                                               secure_applet_memory_size)); | ||||
|  | ||||
|         // This memory seems to be reserved on hardware, but is not reserved/used by yuzu. | ||||
|         // Likely Horizon OS reserved memory | ||||
|         // TODO(ameerj): Derive the memory rather than hardcode it. | ||||
|         constexpr u64 unknown_reserved_memory{0x2f896000}; | ||||
|         ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory, | ||||
|                                               unknown_reserved_memory)); | ||||
|     } | ||||
|  | ||||
|     void InitializePreemption(KernelCore& kernel) { | ||||
| @@ -531,11 +541,7 @@ struct KernelCore::Impl { | ||||
|                                                         linear_region_start); | ||||
|     } | ||||
|  | ||||
|     void InitializeMemoryLayout() { | ||||
|         // Derive the initial memory layout from the emulated board | ||||
|         KMemoryLayout memory_layout; | ||||
|         DeriveInitialMemoryLayout(memory_layout); | ||||
|  | ||||
|     void InitializeMemoryLayout(const KMemoryLayout& memory_layout) { | ||||
|         const auto system_pool = memory_layout.GetKernelSystemPoolRegionPhysicalExtents(); | ||||
|         const auto applet_pool = memory_layout.GetKernelAppletPoolRegionPhysicalExtents(); | ||||
|         const auto application_pool = memory_layout.GetKernelApplicationPoolRegionPhysicalExtents(); | ||||
| @@ -578,11 +584,14 @@ struct KernelCore::Impl { | ||||
|             system.Kernel(), system.DeviceMemory(), nullptr, {time_phys_addr, time_size / PageSize}, | ||||
|             KMemoryPermission::None, KMemoryPermission::Read, time_phys_addr, time_size, | ||||
|             "Time:SharedMemory"); | ||||
|     } | ||||
|  | ||||
|     void InitializeSlabHeaps() { | ||||
|         // Allocate slab heaps | ||||
|         user_slab_heap_pages = std::make_unique<KSlabHeap<Page>>(); | ||||
|  | ||||
|         constexpr u64 user_slab_heap_size{0x1ef000}; | ||||
|         // TODO(ameerj): This should be derived, not hardcoded within the kernel | ||||
|         constexpr u64 user_slab_heap_size{0x3de000}; | ||||
|         // Reserve slab heaps | ||||
|         ASSERT( | ||||
|             system_resource_limit->Reserve(LimitableResource::PhysicalMemory, user_slab_heap_size)); | ||||
|   | ||||
| @@ -120,9 +120,7 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name, | ||||
|     std::shared_ptr<Process> process = std::make_shared<Process>(system); | ||||
|     process->name = std::move(name); | ||||
|  | ||||
|     // TODO: This is inaccurate | ||||
|     // The process should hold a reference to the kernel-wide resource limit. | ||||
|     process->resource_limit = std::make_shared<KResourceLimit>(kernel, system); | ||||
|     process->resource_limit = kernel.GetSystemResourceLimit(); | ||||
|     process->status = ProcessStatus::Created; | ||||
|     process->program_id = 0; | ||||
|     process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID() | ||||
| @@ -160,17 +158,13 @@ void Process::DecrementThreadCount() { | ||||
| } | ||||
|  | ||||
| u64 Process::GetTotalPhysicalMemoryAvailable() const { | ||||
|     // TODO: This is expected to always return the application memory pool size after accurately | ||||
|     // reserving kernel resources. The current workaround uses a process-local resource limit of | ||||
|     // application memory pool size, which is inaccurate. | ||||
|     const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) + | ||||
|                        page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size + | ||||
|                        main_thread_stack_size}; | ||||
|  | ||||
|     ASSERT(capacity == kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application)); | ||||
|     if (capacity < memory_usage_capacity) { | ||||
|         return capacity; | ||||
|     } | ||||
|  | ||||
|     return memory_usage_capacity; | ||||
| } | ||||
|  | ||||
| @@ -272,10 +266,6 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, | ||||
|     system_resource_size = metadata.GetSystemResourceSize(); | ||||
|     image_size = code_size; | ||||
|  | ||||
|     // Set initial resource limits | ||||
|     resource_limit->SetLimitValue( | ||||
|         LimitableResource::PhysicalMemory, | ||||
|         kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application)); | ||||
|     KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory, | ||||
|                                                   code_size + system_resource_size); | ||||
|     if (!memory_reservation.Succeeded()) { | ||||
| @@ -324,16 +314,6 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, | ||||
|         UNREACHABLE(); | ||||
|     } | ||||
|  | ||||
|     // Set initial resource limits | ||||
|     resource_limit->SetLimitValue( | ||||
|         LimitableResource::PhysicalMemory, | ||||
|         kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application)); | ||||
|  | ||||
|     resource_limit->SetLimitValue(LimitableResource::Threads, 608); | ||||
|     resource_limit->SetLimitValue(LimitableResource::Events, 700); | ||||
|     resource_limit->SetLimitValue(LimitableResource::TransferMemory, 128); | ||||
|     resource_limit->SetLimitValue(LimitableResource::Sessions, 894); | ||||
|  | ||||
|     // Create TLS region | ||||
|     tls_region_address = CreateTLSRegion(); | ||||
|     memory_reservation.Commit(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 ameerj
					ameerj