svc: Implement SetResourceLimitLimitValues

* Also correct existing name and add missing error codes
This commit is contained in:
GPUCode
2023-11-30 13:02:15 +02:00
parent a8d869c347
commit 8f054c47f6
12 changed files with 77 additions and 22 deletions

View File

@ -9,6 +9,12 @@
namespace Kernel { namespace Kernel {
namespace ErrCodes { namespace ErrCodes {
enum { enum {
OutOfSharedMems = 11,
OutOfThreads = 12,
OutOfMutexes = 13,
OutOfSemaphores = 14,
OutOfEvents = 15,
OutOfTimers = 16,
OutOfHandles = 19, OutOfHandles = 19,
SessionClosedByRemote = 26, SessionClosedByRemote = 26,
PortNameTooLong = 30, PortNameTooLong = 30,
@ -16,6 +22,7 @@ enum {
NoPendingSessions = 35, NoPendingSessions = 35,
WrongPermission = 46, WrongPermission = 46,
InvalidBufferDescriptor = 48, InvalidBufferDescriptor = 48,
OutOfAddressArbiters = 51,
MaxConnectionsReached = 52, MaxConnectionsReached = 52,
CommandTooLarge = 54, CommandTooLarge = 54,
}; };

View File

@ -8,12 +8,11 @@
#include <boost/serialization/export.hpp> #include <boost/serialization/export.hpp>
#include <boost/serialization/string.hpp> #include <boost/serialization/string.hpp>
#include "core/hle/kernel/object.h" #include "core/hle/kernel/object.h"
#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/wait_object.h" #include "core/hle/kernel/wait_object.h"
namespace Kernel { namespace Kernel {
class ResourceLimit;
class Event final : public WaitObject { class Event final : public WaitObject {
public: public:
explicit Event(KernelSystem& kernel); explicit Event(KernelSystem& kernel);

View File

@ -137,6 +137,10 @@ const SharedPage::Handler& KernelSystem::GetSharedPageHandler() const {
return *shared_page_handler; return *shared_page_handler;
} }
ConfigMem::Handler& KernelSystem::GetConfigMemHandler() {
return *config_mem_handler;
}
IPCDebugger::Recorder& KernelSystem::GetIPCRecorder() { IPCDebugger::Recorder& KernelSystem::GetIPCRecorder() {
return *ipc_recorder; return *ipc_recorder;
} }

View File

@ -295,6 +295,8 @@ public:
SharedPage::Handler& GetSharedPageHandler(); SharedPage::Handler& GetSharedPageHandler();
const SharedPage::Handler& GetSharedPageHandler() const; const SharedPage::Handler& GetSharedPageHandler() const;
ConfigMem::Handler& GetConfigMemHandler();
IPCDebugger::Recorder& GetIPCRecorder(); IPCDebugger::Recorder& GetIPCRecorder();
const IPCDebugger::Recorder& GetIPCRecorder() const; const IPCDebugger::Recorder& GetIPCRecorder() const;

View File

@ -12,6 +12,7 @@
#include <boost/serialization/string.hpp> #include <boost/serialization/string.hpp>
#include "common/common_types.h" #include "common/common_types.h"
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/wait_object.h" #include "core/hle/kernel/wait_object.h"
#include "core/hle/result.h" #include "core/hle/result.h"
@ -19,8 +20,6 @@ namespace Kernel {
class Thread; class Thread;
class ResourceLimit;
class Mutex final : public WaitObject { class Mutex final : public WaitObject {
public: public:
explicit Mutex(KernelSystem& kernel); explicit Mutex(KernelSystem& kernel);

View File

@ -38,8 +38,8 @@ void ResourceLimit::SetLimitValue(ResourceLimitType type, s32 value) {
bool ResourceLimit::Reserve(ResourceLimitType type, s32 amount) { bool ResourceLimit::Reserve(ResourceLimitType type, s32 amount) {
const auto index = static_cast<size_t>(type); const auto index = static_cast<size_t>(type);
const u32 limit = m_limit_values[index]; const s32 limit = m_limit_values[index];
const u32 new_value = m_current_values[index] + amount; const s32 new_value = m_current_values[index] + amount;
if (new_value > limit) { if (new_value > limit) {
LOG_ERROR(Kernel, "New value {} exceeds limit {} for resource type {}", new_value, limit, LOG_ERROR(Kernel, "New value {} exceeds limit {} for resource type {}", new_value, limit,
type); type);
@ -51,7 +51,7 @@ bool ResourceLimit::Reserve(ResourceLimitType type, s32 amount) {
bool ResourceLimit::Release(ResourceLimitType type, s32 amount) { bool ResourceLimit::Release(ResourceLimitType type, s32 amount) {
const auto index = static_cast<size_t>(type); const auto index = static_cast<size_t>(type);
const u32 value = m_current_values[index]; const s32 value = m_current_values[index];
if (amount > value) { if (amount > value) {
LOG_ERROR(Kernel, "Amount {} exceeds current value {} for resource type {}", amount, value, LOG_ERROR(Kernel, "Amount {} exceeds current value {} for resource type {}", amount, value,
type); type);

View File

@ -16,6 +16,7 @@
#include "core/hle/kernel/address_arbiter.h" #include "core/hle/kernel/address_arbiter.h"
#include "core/hle/kernel/client_port.h" #include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h" #include "core/hle/kernel/client_session.h"
#include "core/hle/kernel/config_mem.h"
#include "core/hle/kernel/errors.h" #include "core/hle/kernel/errors.h"
#include "core/hle/kernel/event.h" #include "core/hle/kernel/event.h"
#include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/handle_table.h"
@ -390,6 +391,8 @@ private:
VAddr names, u32 name_count); VAddr names, u32 name_count);
ResultCode GetResourceLimitLimitValues(VAddr values, Handle resource_limit_handle, VAddr names, ResultCode GetResourceLimitLimitValues(VAddr values, Handle resource_limit_handle, VAddr names,
u32 name_count); u32 name_count);
ResultCode SetResourceLimitLimitValues(Handle res_limit, VAddr names, VAddr resource_list,
u32 name_count);
ResultCode CreateThread(Handle* out_handle, u32 entry_point, u32 arg, VAddr stack_top, ResultCode CreateThread(Handle* out_handle, u32 entry_point, u32 arg, VAddr stack_top,
u32 priority, s32 processor_id); u32 priority, s32 processor_id);
void ExitThread(); void ExitThread();
@ -1074,7 +1077,8 @@ ResultCode SVC::CreateAddressArbiter(Handle* out_handle) {
const auto current_process = kernel.GetCurrentProcess(); const auto current_process = kernel.GetCurrentProcess();
const auto& resource_limit = current_process->resource_limit; const auto& resource_limit = current_process->resource_limit;
if (!resource_limit->Reserve(ResourceLimitType::AddressArbiter, 1)) { if (!resource_limit->Reserve(ResourceLimitType::AddressArbiter, 1)) {
return ResultCode{0xC8601833}; return ResultCode(ErrCodes::OutOfAddressArbiters, ErrorModule::OS,
ErrorSummary::OutOfResource, ErrorLevel::Status);
} }
// Create address arbiter. // Create address arbiter.
@ -1197,14 +1201,48 @@ ResultCode SVC::GetResourceLimitLimitValues(VAddr values, Handle resource_limit_
} }
for (u32 i = 0; i < name_count; ++i) { for (u32 i = 0; i < name_count; ++i) {
const u32 name = memory.Read32(names + i * sizeof(u32)); const auto name = static_cast<ResourceLimitType>(memory.Read32(names + i * sizeof(u32)));
const s64 value = resource_limit->GetLimitValue(static_cast<ResourceLimitType>(name)); if (name >= ResourceLimitType::Max) {
return ERR_INVALID_ENUM_VALUE;
}
const s64 value = resource_limit->GetLimitValue(name);
memory.Write64(values + i * sizeof(u64), value); memory.Write64(values + i * sizeof(u64), value);
} }
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
ResultCode SVC::SetResourceLimitLimitValues(Handle res_limit, VAddr names, VAddr resource_list,
u32 name_count) {
LOG_TRACE(Kernel_SVC, "called resource_limit={:08X}, names={:08X}, name_count={}", res_limit,
names, name_count);
const auto resource_limit =
kernel.GetCurrentProcess()->handle_table.Get<ResourceLimit>(res_limit);
if (!resource_limit) {
return ERR_INVALID_HANDLE;
}
for (u32 i = 0; i < name_count; ++i) {
const auto name = static_cast<ResourceLimitType>(memory.Read32(names + i * sizeof(u32)));
if (name >= ResourceLimitType::Max) {
return ERR_INVALID_ENUM_VALUE;
}
const s64 value = memory.Read64(resource_list + i * sizeof(u64));
const s32 value_high = value >> 32;
if (value_high < 0) {
return ERR_OUT_OF_RANGE_KERNEL;
}
if (name == ResourceLimitType::Commit && value_high != 0) {
auto& config_mem = kernel.GetConfigMemHandler().GetConfigMem();
config_mem.app_mem_alloc = value_high;
}
resource_limit->SetLimitValue(name, static_cast<s32>(value));
}
return RESULT_SUCCESS;
}
/// Creates a new thread /// Creates a new thread
ResultCode SVC::CreateThread(Handle* out_handle, u32 entry_point, u32 arg, VAddr stack_top, ResultCode SVC::CreateThread(Handle* out_handle, u32 entry_point, u32 arg, VAddr stack_top,
u32 priority, s32 processor_id) { u32 priority, s32 processor_id) {
@ -1250,9 +1288,9 @@ ResultCode SVC::CreateThread(Handle* out_handle, u32 entry_point, u32 arg, VAddr
} }
// Update thread count in resource limit. // Update thread count in resource limit.
const auto& resource_limit = current_process->resource_limit;
if (!resource_limit->Reserve(ResourceLimitType::Thread, 1)) { if (!resource_limit->Reserve(ResourceLimitType::Thread, 1)) {
return ResultCode{0xC860180C}; return ResultCode(ErrCodes::OutOfThreads, ErrorModule::OS, ErrorSummary::OutOfResource,
ErrorLevel::Status);
} }
// Create thread. // Create thread.
@ -1331,7 +1369,8 @@ ResultCode SVC::CreateMutex(Handle* out_handle, u32 initial_locked) {
const auto current_process = kernel.GetCurrentProcess(); const auto current_process = kernel.GetCurrentProcess();
const auto& resource_limit = current_process->resource_limit; const auto& resource_limit = current_process->resource_limit;
if (!resource_limit->Reserve(ResourceLimitType::Mutex, 1)) { if (!resource_limit->Reserve(ResourceLimitType::Mutex, 1)) {
return ResultCode{0xC860180D}; return ResultCode(ErrCodes::OutOfMutexes, ErrorModule::OS, ErrorSummary::OutOfResource,
ErrorLevel::Status);
} }
// Create mutex. // Create mutex.
@ -1405,7 +1444,8 @@ ResultCode SVC::CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max_c
const auto current_process = kernel.GetCurrentProcess(); const auto current_process = kernel.GetCurrentProcess();
const auto& resource_limit = current_process->resource_limit; const auto& resource_limit = current_process->resource_limit;
if (!resource_limit->Reserve(ResourceLimitType::Semaphore, 1)) { if (!resource_limit->Reserve(ResourceLimitType::Semaphore, 1)) {
return ResultCode{0xC860180E}; return ResultCode(ErrCodes::OutOfSemaphores, ErrorModule::OS, ErrorSummary::OutOfResource,
ErrorLevel::Status);
} }
// Create semaphore // Create semaphore
@ -1501,7 +1541,8 @@ ResultCode SVC::CreateEvent(Handle* out_handle, u32 reset_type) {
const auto current_process = kernel.GetCurrentProcess(); const auto current_process = kernel.GetCurrentProcess();
const auto& resource_limit = current_process->resource_limit; const auto& resource_limit = current_process->resource_limit;
if (!resource_limit->Reserve(ResourceLimitType::Event, 1)) { if (!resource_limit->Reserve(ResourceLimitType::Event, 1)) {
return ResultCode{0xC860180F}; return ResultCode(ErrCodes::OutOfEvents, ErrorModule::OS, ErrorSummary::OutOfResource,
ErrorLevel::Status);
} }
// Create event. // Create event.
@ -1553,7 +1594,8 @@ ResultCode SVC::CreateTimer(Handle* out_handle, u32 reset_type) {
const auto current_process = kernel.GetCurrentProcess(); const auto current_process = kernel.GetCurrentProcess();
const auto& resource_limit = current_process->resource_limit; const auto& resource_limit = current_process->resource_limit;
if (!resource_limit->Reserve(ResourceLimitType::Timer, 1)) { if (!resource_limit->Reserve(ResourceLimitType::Timer, 1)) {
return ResultCode{0xC8601810}; return ResultCode(ErrCodes::OutOfTimers, ErrorModule::OS, ErrorSummary::OutOfResource,
ErrorLevel::Status);
} }
// Create timer. // Create timer.
@ -1711,7 +1753,8 @@ ResultCode SVC::CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my
const auto current_process = kernel.GetCurrentProcess(); const auto current_process = kernel.GetCurrentProcess();
const auto& resource_limit = current_process->resource_limit; const auto& resource_limit = current_process->resource_limit;
if (!resource_limit->Reserve(ResourceLimitType::SharedMemory, 1)) { if (!resource_limit->Reserve(ResourceLimitType::SharedMemory, 1)) {
return ResultCode{0xC860180B}; return ResultCode(ErrCodes::OutOfSharedMems, ErrorModule::OS, ErrorSummary::OutOfResource,
ErrorLevel::Status);
} }
// When trying to create a memory block with address = 0, // When trying to create a memory block with address = 0,
@ -2282,7 +2325,7 @@ const std::array<SVC::FunctionDef, 180> SVC::SVC_Table{{
{0x76, &SVC::Wrap<&SVC::TerminateProcess>, "TerminateProcess"}, {0x76, &SVC::Wrap<&SVC::TerminateProcess>, "TerminateProcess"},
{0x77, nullptr, "SetProcessResourceLimits"}, {0x77, nullptr, "SetProcessResourceLimits"},
{0x78, nullptr, "CreateResourceLimit"}, {0x78, nullptr, "CreateResourceLimit"},
{0x79, nullptr, "SetResourceLimitValues"}, {0x79, &SVC::Wrap<&SVC::SetResourceLimitLimitValues>, "SetResourceLimitLimitValues"},
{0x7A, nullptr, "AddCodeSegment"}, {0x7A, nullptr, "AddCodeSegment"},
{0x7B, nullptr, "Backdoor"}, {0x7B, nullptr, "Backdoor"},
{0x7C, &SVC::Wrap<&SVC::KernelSetState>, "KernelSetState"}, {0x7C, &SVC::Wrap<&SVC::KernelSetState>, "KernelSetState"},

View File

@ -30,7 +30,6 @@ Timer::~Timer() {
std::shared_ptr<Timer> KernelSystem::CreateTimer(ResetType reset_type, std::string name) { std::shared_ptr<Timer> KernelSystem::CreateTimer(ResetType reset_type, std::string name) {
auto timer = std::make_shared<Timer>(*this); auto timer = std::make_shared<Timer>(*this);
timer->resource_limit = resource_limit;
timer->reset_type = reset_type; timer->reset_type = reset_type;
timer->signaled = false; timer->signaled = false;
timer->name = std::move(name); timer->name = std::move(name);

View File

@ -12,6 +12,7 @@
#include "core/hle/ipc_helpers.h" #include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h" #include "core/hle/kernel/event.h"
#include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/resource_limit.h"
#include "core/hle/result.h" #include "core/hle/result.h"
#include "core/hle/service/ac/ac.h" #include "core/hle/service/ac/ac.h"
#include "core/hle/service/ac/ac_i.h" #include "core/hle/service/ac/ac_i.h"

View File

@ -19,7 +19,6 @@
#include "core/file_sys/file_backend.h" #include "core/file_sys/file_backend.h"
#include "core/global.h" #include "core/global.h"
#include "core/hle/kernel/mutex.h" #include "core/hle/kernel/mutex.h"
#include "core/hle/kernel/resource_limit.h"
#include "core/hle/result.h" #include "core/hle/result.h"
#include "core/hle/service/service.h" #include "core/hle/service/service.h"

View File

@ -8,6 +8,7 @@
#include <boost/serialization/shared_ptr.hpp> #include <boost/serialization/shared_ptr.hpp>
#include "core/global.h" #include "core/global.h"
#include "core/hle/kernel/event.h" #include "core/hle/kernel/event.h"
#include "core/hle/kernel/resource_limit.h"
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
namespace Core { namespace Core {

View File

@ -166,7 +166,7 @@ ResultStatus AppLoader_NCCH::LoadExec(std::shared_ptr<Kernel::Process>& process)
const bool is_new_3ds = Settings::values.is_new_3ds.GetValue(); const bool is_new_3ds = Settings::values.is_new_3ds.GetValue();
if (is_new_3ds && n3ds_mode == Kernel::New3dsMemoryMode::Legacy && if (is_new_3ds && n3ds_mode == Kernel::New3dsMemoryMode::Legacy &&
category == Kernel::ResourceLimitCategory::Application) { category == Kernel::ResourceLimitCategory::Application) {
s32 new_limit = 0; u64 new_limit = 0;
switch (o3ds_mode) { switch (o3ds_mode) {
case Kernel::MemoryMode::Prod: case Kernel::MemoryMode::Prod:
new_limit = 64_MiB; new_limit = 64_MiB;
@ -180,7 +180,8 @@ ResultStatus AppLoader_NCCH::LoadExec(std::shared_ptr<Kernel::Process>& process)
default: default:
break; break;
} }
process->resource_limit->SetLimitValue(Kernel::ResourceLimitType::Commit, new_limit); process->resource_limit->SetLimitValue(Kernel::ResourceLimitType::Commit,
static_cast<s32>(new_limit));
} }
// Set the default CPU core for this process // Set the default CPU core for this process