mirror of
https://git.h3cjp.net/H3cJP/citra.git
synced 2024-11-27 14:33:00 +00:00
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:
parent
ddbd1387aa
commit
5e85bc3d23
|
@ -67,8 +67,13 @@ struct KernelCore::Impl {
|
||||||
is_phantom_mode_for_singlecore = false;
|
is_phantom_mode_for_singlecore = false;
|
||||||
|
|
||||||
InitializePhysicalCores();
|
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();
|
InitializeSchedulers();
|
||||||
InitializeSuspendThreads();
|
InitializeSuspendThreads();
|
||||||
InitializePreemption(kernel);
|
InitializePreemption(kernel);
|
||||||
|
@ -137,27 +142,32 @@ struct KernelCore::Impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates the default system resource limit
|
// 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);
|
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.
|
// 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());
|
.IsSuccess());
|
||||||
ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Threads, 800).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::Events, 900).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, 1133).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
|
// 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,
|
ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory,
|
||||||
secure_applet_memory_size));
|
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) {
|
void InitializePreemption(KernelCore& kernel) {
|
||||||
|
@ -531,11 +541,7 @@ struct KernelCore::Impl {
|
||||||
linear_region_start);
|
linear_region_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitializeMemoryLayout() {
|
void InitializeMemoryLayout(const KMemoryLayout& memory_layout) {
|
||||||
// Derive the initial memory layout from the emulated board
|
|
||||||
KMemoryLayout memory_layout;
|
|
||||||
DeriveInitialMemoryLayout(memory_layout);
|
|
||||||
|
|
||||||
const auto system_pool = memory_layout.GetKernelSystemPoolRegionPhysicalExtents();
|
const auto system_pool = memory_layout.GetKernelSystemPoolRegionPhysicalExtents();
|
||||||
const auto applet_pool = memory_layout.GetKernelAppletPoolRegionPhysicalExtents();
|
const auto applet_pool = memory_layout.GetKernelAppletPoolRegionPhysicalExtents();
|
||||||
const auto application_pool = memory_layout.GetKernelApplicationPoolRegionPhysicalExtents();
|
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},
|
system.Kernel(), system.DeviceMemory(), nullptr, {time_phys_addr, time_size / PageSize},
|
||||||
KMemoryPermission::None, KMemoryPermission::Read, time_phys_addr, time_size,
|
KMemoryPermission::None, KMemoryPermission::Read, time_phys_addr, time_size,
|
||||||
"Time:SharedMemory");
|
"Time:SharedMemory");
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitializeSlabHeaps() {
|
||||||
// Allocate slab heaps
|
// Allocate slab heaps
|
||||||
user_slab_heap_pages = std::make_unique<KSlabHeap<Page>>();
|
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
|
// Reserve slab heaps
|
||||||
ASSERT(
|
ASSERT(
|
||||||
system_resource_limit->Reserve(LimitableResource::PhysicalMemory, user_slab_heap_size));
|
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);
|
std::shared_ptr<Process> process = std::make_shared<Process>(system);
|
||||||
process->name = std::move(name);
|
process->name = std::move(name);
|
||||||
|
|
||||||
// TODO: This is inaccurate
|
process->resource_limit = kernel.GetSystemResourceLimit();
|
||||||
// The process should hold a reference to the kernel-wide resource limit.
|
|
||||||
process->resource_limit = std::make_shared<KResourceLimit>(kernel, system);
|
|
||||||
process->status = ProcessStatus::Created;
|
process->status = ProcessStatus::Created;
|
||||||
process->program_id = 0;
|
process->program_id = 0;
|
||||||
process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID()
|
process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID()
|
||||||
|
@ -160,17 +158,13 @@ void Process::DecrementThreadCount() {
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 Process::GetTotalPhysicalMemoryAvailable() const {
|
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) +
|
const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) +
|
||||||
page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size +
|
page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size +
|
||||||
main_thread_stack_size};
|
main_thread_stack_size};
|
||||||
|
ASSERT(capacity == kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application));
|
||||||
if (capacity < memory_usage_capacity) {
|
if (capacity < memory_usage_capacity) {
|
||||||
return capacity;
|
return capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
return memory_usage_capacity;
|
return memory_usage_capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,10 +266,6 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
|
||||||
system_resource_size = metadata.GetSystemResourceSize();
|
system_resource_size = metadata.GetSystemResourceSize();
|
||||||
image_size = code_size;
|
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,
|
KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory,
|
||||||
code_size + system_resource_size);
|
code_size + system_resource_size);
|
||||||
if (!memory_reservation.Succeeded()) {
|
if (!memory_reservation.Succeeded()) {
|
||||||
|
@ -324,16 +314,6 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
|
||||||
UNREACHABLE();
|
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
|
// Create TLS region
|
||||||
tls_region_address = CreateTLSRegion();
|
tls_region_address = CreateTLSRegion();
|
||||||
memory_reservation.Commit();
|
memory_reservation.Commit();
|
||||||
|
|
Loading…
Reference in a new issue