diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/hle/kernel/init/init_slab_setup.cpp | 6 | ||||
-rw-r--r-- | src/core/hle/kernel/k_resource_limit.cpp | 14 | ||||
-rw-r--r-- | src/core/hle/kernel/k_resource_limit.h | 20 | ||||
-rw-r--r-- | src/core/hle/kernel/k_scoped_resource_reservation.h | 8 | ||||
-rw-r--r-- | src/core/hle/kernel/k_shared_memory.cpp | 28 | ||||
-rw-r--r-- | src/core/hle/kernel/k_shared_memory.h | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/k_transfer_memory.h | 5 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.cpp | 24 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.h | 38 | ||||
-rw-r--r-- | src/core/hle/kernel/process.cpp | 20 | ||||
-rw-r--r-- | src/core/hle/kernel/process.h | 8 | ||||
-rw-r--r-- | src/core/hle/kernel/svc.cpp | 127 | ||||
-rw-r--r-- | src/core/hle/kernel/svc_wrap.h | 19 |
13 files changed, 197 insertions, 122 deletions
diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp index ce7a24c40..a5ddd7344 100644 --- a/src/core/hle/kernel/init/init_slab_setup.cpp +++ b/src/core/hle/kernel/init/init_slab_setup.cpp @@ -12,11 +12,12 @@ #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_memory_layout.h" #include "core/hle/kernel/k_memory_manager.h" +#include "core/hle/kernel/k_resource_limit.h" #include "core/hle/kernel/k_session.h" #include "core/hle/kernel/k_shared_memory.h" -#include "core/hle/kernel/k_transfer_memory.h" #include "core/hle/kernel/k_system_control.h" #include "core/hle/kernel/k_thread.h" +#include "core/hle/kernel/k_transfer_memory.h" #include "core/hle/kernel/memory_types.h" #include "core/hle/kernel/process.h" #include "core/memory.h" @@ -31,7 +32,8 @@ namespace Kernel::Init { HANDLER(KEvent, (SLAB_COUNT(KEvent)), ##__VA_ARGS__) \ HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ##__VA_ARGS__) \ HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ##__VA_ARGS__) \ - HANDLER(KSession, (SLAB_COUNT(KSession)), ##__VA_ARGS__) + HANDLER(KSession, (SLAB_COUNT(KSession)), ##__VA_ARGS__) \ + HANDLER(KResourceLimit, (SLAB_COUNT(KResourceLimit)), ##__VA_ARGS__) namespace { diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp index d05b34ea3..ad5095bfd 100644 --- a/src/core/hle/kernel/k_resource_limit.cpp +++ b/src/core/hle/kernel/k_resource_limit.cpp @@ -10,10 +10,16 @@ namespace Kernel { constexpr s64 DefaultTimeout = 10000000000; // 10 seconds -KResourceLimit::KResourceLimit(KernelCore& kernel, const Core::Timing::CoreTiming& core_timing_) - : Object{kernel}, lock{kernel}, cond_var{kernel}, core_timing(core_timing_) {} +KResourceLimit::KResourceLimit(KernelCore& kernel) + : KAutoObjectWithSlabHeapAndContainer{kernel}, lock{kernel}, cond_var{kernel} {} KResourceLimit::~KResourceLimit() = default; +void KResourceLimit::Initialize(const Core::Timing::CoreTiming* core_timing_) { + core_timing = core_timing_; +} + +void KResourceLimit::Finalize() {} + s64 KResourceLimit::GetLimitValue(LimitableResource which) const { const auto index = static_cast<std::size_t>(which); s64 value{}; @@ -78,7 +84,7 @@ ResultCode KResourceLimit::SetLimitValue(LimitableResource which, s64 value) { } bool KResourceLimit::Reserve(LimitableResource which, s64 value) { - return Reserve(which, value, core_timing.GetGlobalTimeNs().count() + DefaultTimeout); + return Reserve(which, value, core_timing->GetGlobalTimeNs().count() + DefaultTimeout); } bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { @@ -109,7 +115,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { } if (current_hints[index] + value <= limit_values[index] && - (timeout < 0 || core_timing.GetGlobalTimeNs().count() < timeout)) { + (timeout < 0 || core_timing->GetGlobalTimeNs().count() < timeout)) { waiter_count++; cond_var.Wait(&lock, timeout); waiter_count--; diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h index 4542317d0..483c66c33 100644 --- a/src/core/hle/kernel/k_resource_limit.h +++ b/src/core/hle/kernel/k_resource_limit.h @@ -32,10 +32,16 @@ constexpr bool IsValidResourceType(LimitableResource type) { return type < LimitableResource::Count; } -class KResourceLimit final : public Object { +class KResourceLimit final + : public KAutoObjectWithSlabHeapAndContainer<KResourceLimit, KAutoObjectWithList> { + KERNEL_AUTOOBJECT_TRAITS(KResourceLimit, KAutoObject); + public: - explicit KResourceLimit(KernelCore& kernel, const Core::Timing::CoreTiming& core_timing_); - ~KResourceLimit(); + explicit KResourceLimit(KernelCore& kernel); + virtual ~KResourceLimit(); + + void Initialize(const Core::Timing::CoreTiming* core_timing_); + virtual void Finalize() override; s64 GetLimitValue(LimitableResource which) const; s64 GetCurrentValue(LimitableResource which) const; @@ -49,6 +55,10 @@ public: void Release(LimitableResource which, s64 value); void Release(LimitableResource which, s64 value, s64 hint); + static void PostDestroy([[maybe_unused]] uintptr_t arg) {} + + // DEPRECATED + std::string GetTypeName() const override { return "KResourceLimit"; } @@ -61,8 +71,6 @@ public: return HANDLE_TYPE; } - virtual void Finalize() override {} - private: using ResourceArray = std::array<s64, static_cast<std::size_t>(LimitableResource::Count)>; ResourceArray limit_values{}; @@ -72,6 +80,6 @@ private: mutable KLightLock lock; s32 waiter_count{}; KLightConditionVariable cond_var; - const Core::Timing::CoreTiming& core_timing; + const Core::Timing::CoreTiming* core_timing{}; }; } // namespace Kernel diff --git a/src/core/hle/kernel/k_scoped_resource_reservation.h b/src/core/hle/kernel/k_scoped_resource_reservation.h index c5deca00b..b160587c5 100644 --- a/src/core/hle/kernel/k_scoped_resource_reservation.h +++ b/src/core/hle/kernel/k_scoped_resource_reservation.h @@ -15,8 +15,7 @@ namespace Kernel { class KScopedResourceReservation { public: - explicit KScopedResourceReservation(std::shared_ptr<KResourceLimit> l, LimitableResource r, - s64 v, s64 timeout) + explicit KScopedResourceReservation(KResourceLimit* l, LimitableResource r, s64 v, s64 timeout) : resource_limit(std::move(l)), value(v), resource(r) { if (resource_limit && value) { success = resource_limit->Reserve(resource, value, timeout); @@ -25,8 +24,7 @@ public: } } - explicit KScopedResourceReservation(std::shared_ptr<KResourceLimit> l, LimitableResource r, - s64 v = 1) + explicit KScopedResourceReservation(KResourceLimit* l, LimitableResource r, s64 v = 1) : resource_limit(std::move(l)), value(v), resource(r) { if (resource_limit && value) { success = resource_limit->Reserve(resource, value); @@ -58,7 +56,7 @@ public: } private: - std::shared_ptr<KResourceLimit> resource_limit; + KResourceLimit* resource_limit{}; s64 value; LimitableResource resource; bool success; diff --git a/src/core/hle/kernel/k_shared_memory.cpp b/src/core/hle/kernel/k_shared_memory.cpp index 9e20c2350..e91bc94bd 100644 --- a/src/core/hle/kernel/k_shared_memory.cpp +++ b/src/core/hle/kernel/k_shared_memory.cpp @@ -8,6 +8,7 @@ #include "core/hle/kernel/k_scoped_resource_reservation.h" #include "core/hle/kernel/k_shared_memory.h" #include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/svc_results.h" namespace Kernel { @@ -22,12 +23,7 @@ ResultCode KSharedMemory::Initialize(KernelCore& kernel_, Core::DeviceMemory& de KMemoryPermission owner_permission_, KMemoryPermission user_permission_, PAddr physical_address_, std::size_t size_, std::string name_) { - - resource_limit = kernel_.GetSystemResourceLimit(); - KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory, - size_); - ASSERT(memory_reservation.Succeeded()); - + // Set members. owner_process = owner_process_; device_memory = &device_memory_; page_list = std::move(page_list_); @@ -36,10 +32,28 @@ ResultCode KSharedMemory::Initialize(KernelCore& kernel_, Core::DeviceMemory& de physical_address = physical_address_; size = size_; name = name_; - is_initialized = true; + // Get the resource limit. + KResourceLimit* reslimit = kernel.GetSystemResourceLimit(); + + // Reserve memory for ourselves. + KScopedResourceReservation memory_reservation(reslimit, LimitableResource::PhysicalMemory, + size_); + R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); + + // Commit our reservation. memory_reservation.Commit(); + // Set our resource limit. + resource_limit = reslimit; + resource_limit->Open(); + + // Mark initialized. + is_initialized = true; + + // Clear all pages in the memory. + std::memset(device_memory_.GetPointer(physical_address_), 0, size_); + return RESULT_SUCCESS; } diff --git a/src/core/hle/kernel/k_shared_memory.h b/src/core/hle/kernel/k_shared_memory.h index aaa773bfc..93153ab20 100644 --- a/src/core/hle/kernel/k_shared_memory.h +++ b/src/core/hle/kernel/k_shared_memory.h @@ -88,7 +88,7 @@ private: KMemoryPermission user_permission{}; PAddr physical_address{}; std::size_t size{}; - std::shared_ptr<KResourceLimit> resource_limit; + KResourceLimit* resource_limit{}; bool is_initialized{}; }; diff --git a/src/core/hle/kernel/k_transfer_memory.h b/src/core/hle/kernel/k_transfer_memory.h index f43725c7f..3c3fa401b 100644 --- a/src/core/hle/kernel/k_transfer_memory.h +++ b/src/core/hle/kernel/k_transfer_memory.h @@ -27,9 +27,7 @@ class KTransferMemory final public: explicit KTransferMemory(KernelCore& kernel); - ~KTransferMemory() override; - - static constexpr HandleType HANDLE_TYPE = HandleType::TransferMemory; + virtual ~KTransferMemory() override; ResultCode Initialize(VAddr address_, std::size_t size_, Svc::MemoryPermission owner_perm_); @@ -67,6 +65,7 @@ public: return GetTypeName(); } + static constexpr HandleType HANDLE_TYPE = HandleType::TransferMemory; HandleType GetHandleType() const override { return HANDLE_TYPE; } diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 472c71cf1..ada993f46 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -74,8 +74,8 @@ struct KernelCore::Impl { Init::InitializeSlabHeaps(system, memory_layout); // Initialize kernel memory and resources. - InitializeMemoryLayout(memory_layout); InitializeSystemResourceLimit(kernel, system.CoreTiming(), memory_layout); + InitializeMemoryLayout(memory_layout); InitializePageSlab(); InitializeSchedulers(); InitializeSuspendThreads(); @@ -126,11 +126,19 @@ struct KernelCore::Impl { exclusive_monitor.reset(); + hid_shared_mem->Close(); hid_shared_mem = nullptr; + + font_shared_mem->Close(); font_shared_mem = nullptr; + + irs_shared_mem->Close(); irs_shared_mem = nullptr; + + time_shared_mem->Close(); time_shared_mem = nullptr; + system_resource_limit->Close(); system_resource_limit = nullptr; // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others @@ -156,7 +164,9 @@ struct KernelCore::Impl { void InitializeSystemResourceLimit(KernelCore& kernel, const Core::Timing::CoreTiming& core_timing, const KMemoryLayout& memory_layout) { - system_resource_limit = std::make_shared<KResourceLimit>(kernel, core_timing); + system_resource_limit = KResourceLimit::Create(system.Kernel()); + system_resource_limit->Initialize(&core_timing); + const auto [total_size, kernel_size] = memory_layout.GetTotalAndKernelMemorySizes(); // If setting the default system values fails, then something seriously wrong has occurred. @@ -627,11 +637,11 @@ struct KernelCore::Impl { // Lists all processes that exist in the current session. std::vector<Process*> process_list; - Process* current_process = nullptr; + Process* current_process{}; std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context; Kernel::TimeManager time_manager; - std::shared_ptr<KResourceLimit> system_resource_limit; + KResourceLimit* system_resource_limit{}; std::shared_ptr<Core::Timing::EventType> preemption_event; @@ -704,7 +714,11 @@ void KernelCore::Shutdown() { impl->Shutdown(); } -std::shared_ptr<KResourceLimit> KernelCore::GetSystemResourceLimit() const { +const KResourceLimit* KernelCore::GetSystemResourceLimit() const { + return impl->system_resource_limit; +} + +KResourceLimit* KernelCore::GetSystemResourceLimit() { return impl->system_resource_limit; } diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index f07f0276e..43e49603b 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -92,7 +92,10 @@ public: void Shutdown(); /// Retrieves a shared pointer to the system resource limit instance. - std::shared_ptr<KResourceLimit> GetSystemResourceLimit() const; + const KResourceLimit* GetSystemResourceLimit() const; + + /// Retrieves a shared pointer to the system resource limit instance. + KResourceLimit* GetSystemResourceLimit(); /// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table. KScopedAutoObject<KThread> RetrieveThreadFromGlobalHandleTable(Handle handle) const; @@ -263,24 +266,26 @@ public: /// Gets the slab heap for the specified kernel object type. template <typename T> KSlabHeap<T>& SlabHeap() { - if constexpr (std::is_same_v<T, Process>) { - return slab_heap_container->process; - } else if constexpr (std::is_same_v<T, KThread>) { - return slab_heap_container->thread; + if constexpr (std::is_same_v<T, KClientSession>) { + return slab_heap_container->client_session; } else if constexpr (std::is_same_v<T, KEvent>) { return slab_heap_container->event; - } else if constexpr (std::is_same_v<T, KSharedMemory>) { - return slab_heap_container->shared_memory; } else if constexpr (std::is_same_v<T, KLinkedListNode>) { return slab_heap_container->linked_list_node; - } else if constexpr (std::is_same_v<T, KWritableEvent>) { - return slab_heap_container->writeable_event; - } else if constexpr (std::is_same_v<T, KClientSession>) { - return slab_heap_container->client_session; + } else if constexpr (std::is_same_v<T, Process>) { + return slab_heap_container->process; + } else if constexpr (std::is_same_v<T, KResourceLimit>) { + return slab_heap_container->resource_limit; } else if constexpr (std::is_same_v<T, KSession>) { return slab_heap_container->session; + } else if constexpr (std::is_same_v<T, KSharedMemory>) { + return slab_heap_container->shared_memory; + } else if constexpr (std::is_same_v<T, KThread>) { + return slab_heap_container->thread; } else if constexpr (std::is_same_v<T, KTransferMemory>) { return slab_heap_container->transfer_memory; + } else if constexpr (std::is_same_v<T, KWritableEvent>) { + return slab_heap_container->writeable_event; } } @@ -315,15 +320,16 @@ private: private: /// Helper to encapsulate all slab heaps in a single heap allocated container struct SlabHeapContainer { - KSlabHeap<Process> process; - KSlabHeap<KThread> thread; + KSlabHeap<KClientSession> client_session; KSlabHeap<KEvent> event; - KSlabHeap<KSharedMemory> shared_memory; KSlabHeap<KLinkedListNode> linked_list_node; - KSlabHeap<KWritableEvent> writeable_event; - KSlabHeap<KClientSession> client_session; + KSlabHeap<Process> process; + KSlabHeap<KResourceLimit> resource_limit; KSlabHeap<KSession> session; + KSlabHeap<KSharedMemory> shared_memory; + KSlabHeap<KThread> thread; KSlabHeap<KTransferMemory> transfer_memory; + KSlabHeap<KWritableEvent> writeable_event; }; std::unique_ptr<SlabHeapContainer> slab_heap_container; diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 678037923..315640bea 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -138,10 +138,13 @@ ResultCode Process::Initialize(Process* process, Core::System& system, std::stri kernel.AppendNewProcess(process); + // Open a reference to the resource limit. + process->resource_limit->Open(); + return RESULT_SUCCESS; } -std::shared_ptr<KResourceLimit> Process::GetResourceLimit() const { +KResourceLimit* Process::GetResourceLimit() const { return resource_limit; } @@ -166,7 +169,10 @@ u64 Process::GetTotalPhysicalMemoryAvailable() const { 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 (const auto pool_size = kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application); + capacity != pool_size) { + LOG_WARNING(Kernel, "capacity {} != application pool size {}", capacity, pool_size); + } if (capacity < memory_usage_capacity) { return capacity; } @@ -371,6 +377,16 @@ void Process::PrepareForTermination() { ChangeStatus(ProcessStatus::Exited); } +void Process::Finalize() { + // Release memory to the resource limit. + if (resource_limit != nullptr) { + resource_limit->Close(); + } + + // Perform inherited finalization. + KAutoObjectWithSlabHeapAndContainer<Process, KSynchronizationObject>::Finalize(); +} + /** * Attempts to find a TLS page that contains a free slot for * use by a thread. diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index df3c7997d..35fe16433 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h @@ -171,7 +171,7 @@ public: } /// Gets the resource limit descriptor for this process - std::shared_ptr<KResourceLimit> GetResourceLimit() const; + KResourceLimit* GetResourceLimit() const; /// Gets the ideal CPU core ID for this process u8 GetIdealCoreId() const { @@ -348,9 +348,7 @@ public: static void PostDestroy([[maybe_unused]] uintptr_t arg) {} - virtual void Finalize() override { - UNIMPLEMENTED(); - } + virtual void Finalize(); virtual u64 GetId() const override final { return GetProcessID(); @@ -415,7 +413,7 @@ private: u32 system_resource_size = 0; /// Resource limit descriptor for this process - std::shared_ptr<KResourceLimit> resource_limit; + KResourceLimit* resource_limit{}; /// The ideal CPU core for this process, threads are scheduled on this core by default. u8 ideal_core = 0; diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 9e8184758..a78bfd1da 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -153,9 +153,9 @@ ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_ const auto* const current_process = system.Kernel().CurrentProcess(); ASSERT(current_process != nullptr); - const auto resource_limit_object = - current_process->GetHandleTable().Get<KResourceLimit>(resource_limit); - if (!resource_limit_object) { + auto resource_limit_object = + current_process->GetHandleTable().GetObject<KResourceLimit>(resource_limit); + if (resource_limit_object.IsNull()) { LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}", resource_limit); return ResultInvalidHandle; @@ -843,12 +843,10 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle return RESULT_SUCCESS; } - const auto table_result = handle_table.Create(resource_limit.get()); - if (table_result.Failed()) { - return table_result.Code(); - } + Handle handle{}; + R_TRY(handle_table.Add(&handle, resource_limit)); - *result = *table_result; + *result = handle; return RESULT_SUCCESS; } @@ -2093,83 +2091,86 @@ static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_ } static ResultCode CreateResourceLimit(Core::System& system, Handle* out_handle) { - std::lock_guard lock{HLE::g_hle_lock}; LOG_DEBUG(Kernel_SVC, "called"); + // Create a new resource limit. auto& kernel = system.Kernel(); - auto resource_limit = std::make_shared<KResourceLimit>(kernel, system.CoreTiming()); + KResourceLimit* resource_limit = KResourceLimit::Create(kernel); + R_UNLESS(resource_limit != nullptr, ResultOutOfResource); - auto* const current_process = kernel.CurrentProcess(); - ASSERT(current_process != nullptr); + // Ensure we don't leak a reference to the limit. + SCOPE_EXIT({ resource_limit->Close(); }); - const auto handle = current_process->GetHandleTable().Create(resource_limit.get()); - if (handle.Failed()) { - return handle.Code(); - } + // Initialize the resource limit. + resource_limit->Initialize(&system.CoreTiming()); + + // Register the limit. + KResourceLimit::Register(kernel, resource_limit); + + // Add the limit to the handle table. + R_TRY(kernel.CurrentProcess()->GetHandleTable().Add(out_handle, resource_limit)); - *out_handle = *handle; return RESULT_SUCCESS; } -static ResultCode GetResourceLimitLimitValue(Core::System& system, u64* out_value, - Handle resource_limit, u32 resource_type) { - LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}", resource_limit, resource_type); +static ResultCode GetResourceLimitLimitValue(Core::System& system, u64* out_limit_value, + Handle resource_limit_handle, + LimitableResource which) { + LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}", resource_limit_handle, + which); - const auto limit_value = RetrieveResourceLimitValue(system, resource_limit, resource_type, - ResourceLimitValueType::LimitValue); - if (limit_value.Failed()) { - return limit_value.Code(); - } + // Validate the resource. + R_UNLESS(IsValidResourceType(which), ResultInvalidEnumValue); + + // Get the resource limit. + auto& kernel = system.Kernel(); + KScopedAutoObject resource_limit = + kernel.CurrentProcess()->GetHandleTable().GetObject<KResourceLimit>(resource_limit_handle); + R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle); + + // Get the limit value. + *out_limit_value = resource_limit->GetLimitValue(which); - *out_value = static_cast<u64>(*limit_value); return RESULT_SUCCESS; } -static ResultCode GetResourceLimitCurrentValue(Core::System& system, u64* out_value, - Handle resource_limit, u32 resource_type) { - LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}", resource_limit, resource_type); +static ResultCode GetResourceLimitCurrentValue(Core::System& system, u64* out_current_value, + Handle resource_limit_handle, + LimitableResource which) { + LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}", resource_limit_handle, + which); - const auto current_value = RetrieveResourceLimitValue(system, resource_limit, resource_type, - ResourceLimitValueType::CurrentValue); - if (current_value.Failed()) { - return current_value.Code(); - } + // Validate the resource. + R_UNLESS(IsValidResourceType(which), ResultInvalidEnumValue); + + // Get the resource limit. + auto& kernel = system.Kernel(); + KScopedAutoObject resource_limit = + kernel.CurrentProcess()->GetHandleTable().GetObject<KResourceLimit>(resource_limit_handle); + R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle); + + // Get the current value. + *out_current_value = resource_limit->GetCurrentValue(which); - *out_value = static_cast<u64>(*current_value); return RESULT_SUCCESS; } -static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resource_limit, - u32 resource_type, u64 value) { - LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}, Value={}", resource_limit, - resource_type, value); +static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resource_limit_handle, + LimitableResource which, u64 limit_value) { + LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}, limit_value={}", + resource_limit_handle, which, limit_value); - const auto type = static_cast<LimitableResource>(resource_type); - if (!IsValidResourceType(type)) { - LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type); - return ResultInvalidEnumValue; - } - - auto* const current_process = system.Kernel().CurrentProcess(); - ASSERT(current_process != nullptr); + // Validate the resource. + R_UNLESS(IsValidResourceType(which), ResultInvalidEnumValue); - auto resource_limit_object = - current_process->GetHandleTable().Get<KResourceLimit>(resource_limit); - if (!resource_limit_object) { - LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}", - resource_limit); - return ResultInvalidHandle; - } + // Get the resource limit. + auto& kernel = system.Kernel(); + KScopedAutoObject resource_limit = + kernel.CurrentProcess()->GetHandleTable().GetObject<KResourceLimit>(resource_limit_handle); + R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle); - const auto set_result = resource_limit_object->SetLimitValue(type, static_cast<s64>(value)); - if (set_result.IsError()) { - LOG_ERROR(Kernel_SVC, - "Attempted to lower resource limit ({}) for category '{}' below its current " - "value ({})", - resource_limit_object->GetLimitValue(type), resource_type, - resource_limit_object->GetCurrentValue(type)); - return set_result; - } + // Set the limit value. + R_TRY(resource_limit->SetLimitValue(which, limit_value)); return RESULT_SUCCESS; } diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h index 61986bb52..d3df25d0f 100644 --- a/src/core/hle/kernel/svc_wrap.h +++ b/src/core/hle/kernel/svc_wrap.h @@ -154,15 +154,28 @@ void SvcWrap64(Core::System& system) { FuncReturn(system, retval); } +// Used by GetResourceLimitLimitValue. +template <ResultCode func(Core::System&, u64*, Handle, LimitableResource)> +void SvcWrap64(Core::System& system) { + u64 param_1 = 0; + const u32 retval = func(system, ¶m_1, static_cast<Handle>(Param(system, 1)), + static_cast<LimitableResource>(Param(system, 2))) + .raw; + + system.CurrentArmInterface().SetReg(1, param_1); + FuncReturn(system, retval); +} + template <ResultCode func(Core::System&, u32, u64)> void SvcWrap64(Core::System& system) { FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1)).raw); } -template <ResultCode func(Core::System&, u32, u32, u64)> +// Used by SetResourceLimitLimitValue +template <ResultCode func(Core::System&, Handle, LimitableResource, u64)> void SvcWrap64(Core::System& system) { - FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), - static_cast<u32>(Param(system, 1)), Param(system, 2)) + FuncReturn(system, func(system, static_cast<Handle>(Param(system, 0)), + static_cast<LimitableResource>(Param(system, 1)), Param(system, 2)) .raw); } |