kernel: More accurately reserve and release resources
This commit is contained in:
parent
5fa6b15215
commit
ec9b6641b1
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));
|
||||||
|
case ResourceLimitValueType::PeakValue:
|
||||||
|
return MakeResult(resource_limit_object->GetPeakValue(type));
|
||||||
|
default:
|
||||||
|
LOG_ERROR(Kernel_SVC, "Invalid resource value_type: '{}'", value_type);
|
||||||
|
return ResultInvalidEnumValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return MakeResult(resource_limit_object->GetLimitValue(type));
|
|
||||||
}
|
}
|
||||||
} // 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…
Reference in a new issue