svc: Implement SetResourceLimitLimitValues
* Also correct existing name and add missing error codes
This commit is contained in:
@ -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,
|
||||||
};
|
};
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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"},
|
||||||
|
@ -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);
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user