summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/hle/function_wrappers.h4
-rw-r--r--src/core/hle/kernel/kernel.cpp3
-rw-r--r--src/core/hle/kernel/kernel.h3
-rw-r--r--src/core/hle/kernel/process.cpp1
-rw-r--r--src/core/hle/kernel/process.h4
-rw-r--r--src/core/hle/kernel/resource_limit.cpp157
-rw-r--r--src/core/hle/kernel/resource_limit.h119
-rw-r--r--src/core/hle/svc.cpp49
-rw-r--r--src/core/loader/3dsx.cpp4
-rw-r--r--src/core/loader/elf.cpp4
-rw-r--r--src/core/loader/ncch.cpp5
12 files changed, 341 insertions, 14 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index e8d8c96d7..5caaee474 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -30,6 +30,7 @@ set(SRCS
hle/kernel/kernel.cpp
hle/kernel/mutex.cpp
hle/kernel/process.cpp
+ hle/kernel/resource_limit.cpp
hle/kernel/semaphore.cpp
hle/kernel/session.cpp
hle/kernel/shared_memory.cpp
@@ -141,6 +142,7 @@ set(HEADERS
hle/kernel/kernel.h
hle/kernel/mutex.h
hle/kernel/process.h
+ hle/kernel/resource_limit.h
hle/kernel/semaphore.h
hle/kernel/session.h
hle/kernel/shared_memory.h
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h
index eb52c8fb1..0e5ae29ae 100644
--- a/src/core/hle/function_wrappers.h
+++ b/src/core/hle/function_wrappers.h
@@ -102,8 +102,8 @@ template<ResultCode func(u32)> void Wrap() {
FuncReturn(func(PARAM(0)).raw);
}
-template<ResultCode func(s64*, u32, void*, s32)> void Wrap(){
- FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), Memory::GetPointer(PARAM(2)),
+template<ResultCode func(s64*, u32, u32*, s32)> void Wrap(){
+ FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), (u32*)Memory::GetPointer(PARAM(2)),
(s32)PARAM(3)).raw);
}
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index b5c98b249..726e4d2ff 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -10,6 +10,7 @@
#include "core/arm/arm_interface.h"
#include "core/core.h"
#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/timer.h"
@@ -134,6 +135,7 @@ void HandleTable::Clear() {
/// Initialize the kernel
void Init() {
+ Kernel::ResourceLimitsInit();
Kernel::ThreadingInit();
Kernel::TimersInit();
@@ -147,6 +149,7 @@ void Init() {
void Shutdown() {
Kernel::ThreadingShutdown();
Kernel::TimersShutdown();
+ Kernel::ResourceLimitsShutdown();
g_handle_table.Clear(); // Free all kernel objects
g_current_process = nullptr;
}
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 7c106d37c..28748c8f5 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -46,7 +46,8 @@ enum class HandleType : u32 {
Process = 8,
AddressArbiter = 9,
Semaphore = 10,
- Timer = 11
+ Timer = 11,
+ ResourceLimit = 12,
};
enum {
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 0cdfa58d7..b5c87e883 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -7,6 +7,7 @@
#include "common/logging/log.h"
#include "core/hle/kernel/process.h"
+#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/thread.h"
#include "core/memory.h"
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 90881054c..7b8a68610 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -45,6 +45,8 @@ union ProcessFlags {
BitField<12, 1, u16> loaded_high; ///< Application loaded high (not at 0x00100000).
};
+class ResourceLimit;
+
class Process final : public Object {
public:
static SharedPtr<Process> Create(std::string name, u64 program_id);
@@ -61,6 +63,8 @@ public:
std::string name;
/// Title ID corresponding to the process
u64 program_id;
+ /// Resource limit descriptor for this process
+ SharedPtr<ResourceLimit> resource_limit;
/// The process may only call SVCs which have the corresponding bit set.
std::bitset<0x80> svc_access_mask;
diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp
new file mode 100644
index 000000000..94b3e3298
--- /dev/null
+++ b/src/core/hle/kernel/resource_limit.cpp
@@ -0,0 +1,157 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <cstring>
+
+#include "common/logging/log.h"
+
+#include "core/mem_map.h"
+#include "core/hle/kernel/resource_limit.h"
+
+namespace Kernel {
+
+static SharedPtr<ResourceLimit> resource_limits[4];
+
+ResourceLimit::ResourceLimit() {}
+ResourceLimit::~ResourceLimit() {}
+
+SharedPtr<ResourceLimit> ResourceLimit::Create(std::string name) {
+ SharedPtr<ResourceLimit> resource_limit(new ResourceLimit);
+
+ resource_limit->name = std::move(name);
+ return resource_limit;
+}
+
+SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory category) {
+ switch (category)
+ {
+ case ResourceLimitCategory::APPLICATION:
+ case ResourceLimitCategory::SYS_APPLET:
+ case ResourceLimitCategory::LIB_APPLET:
+ case ResourceLimitCategory::OTHER:
+ return resource_limits[static_cast<u8>(category)];
+ default:
+ LOG_CRITICAL(Kernel, "Unknown resource limit category");
+ UNREACHABLE();
+ }
+}
+
+s32 ResourceLimit::GetCurrentResourceValue(u32 resource) const {
+ switch (resource) {
+ case COMMIT:
+ return current_commit;
+ case THREAD:
+ return current_threads;
+ case EVENT:
+ return current_events;
+ case MUTEX:
+ return current_mutexes;
+ case SEMAPHORE:
+ return current_semaphores;
+ case TIMER:
+ return current_timers;
+ case SHARED_MEMORY:
+ return current_shared_mems;
+ case ADDRESS_ARBITER:
+ return current_address_arbiters;
+ case CPU_TIME:
+ return current_cpu_time;
+ default:
+ LOG_ERROR(Kernel, "Unknown resource type=%08X", resource);
+ UNIMPLEMENTED();
+ return 0;
+ }
+}
+
+s32 ResourceLimit::GetMaxResourceValue(u32 resource) const {
+ switch (resource) {
+ case COMMIT:
+ return max_commit;
+ case THREAD:
+ return max_threads;
+ case EVENT:
+ return max_events;
+ case MUTEX:
+ return max_mutexes;
+ case SEMAPHORE:
+ return max_semaphores;
+ case TIMER:
+ return max_timers;
+ case SHARED_MEMORY:
+ return max_shared_mems;
+ case ADDRESS_ARBITER:
+ return max_address_arbiters;
+ case CPU_TIME:
+ return max_cpu_time;
+ default:
+ LOG_ERROR(Kernel, "Unknown resource type=%08X", resource);
+ UNIMPLEMENTED();
+ return 0;
+ }
+}
+
+void ResourceLimitsInit() {
+ // Create the four resource limits that the system uses
+ // Create the APPLICATION resource limit
+ SharedPtr<ResourceLimit> resource_limit = ResourceLimit::Create("Applications");
+ resource_limit->max_priority = 0x18;
+ resource_limit->max_commit = 0x4000000;
+ resource_limit->max_threads = 0x20;
+ resource_limit->max_events = 0x20;
+ resource_limit->max_mutexes = 0x20;
+ resource_limit->max_semaphores = 0x8;
+ resource_limit->max_timers = 0x8;
+ resource_limit->max_shared_mems = 0x10;
+ resource_limit->max_address_arbiters = 0x2;
+ resource_limit->max_cpu_time = 0x1E;
+ resource_limits[static_cast<u8>(ResourceLimitCategory::APPLICATION)] = resource_limit;
+
+ // Create the SYS_APPLET resource limit
+ resource_limit = ResourceLimit::Create("System Applets");
+ resource_limit->max_priority = 0x4;
+ resource_limit->max_commit = 0x5E00000;
+ resource_limit->max_threads = 0x1D;
+ resource_limit->max_events = 0xB;
+ resource_limit->max_mutexes = 0x8;
+ resource_limit->max_semaphores = 0x4;
+ resource_limit->max_timers = 0x4;
+ resource_limit->max_shared_mems = 0x8;
+ resource_limit->max_address_arbiters = 0x3;
+ resource_limit->max_cpu_time = 0x2710;
+ resource_limits[static_cast<u8>(ResourceLimitCategory::SYS_APPLET)] = resource_limit;
+
+ // Create the LIB_APPLET resource limit
+ resource_limit = ResourceLimit::Create("Library Applets");
+ resource_limit->max_priority = 0x4;
+ resource_limit->max_commit = 0x600000;
+ resource_limit->max_threads = 0xE;
+ resource_limit->max_events = 0x8;
+ resource_limit->max_mutexes = 0x8;
+ resource_limit->max_semaphores = 0x4;
+ resource_limit->max_timers = 0x4;
+ resource_limit->max_shared_mems = 0x8;
+ resource_limit->max_address_arbiters = 0x1;
+ resource_limit->max_cpu_time = 0x2710;
+ resource_limits[static_cast<u8>(ResourceLimitCategory::LIB_APPLET)] = resource_limit;
+
+ // Create the OTHER resource limit
+ resource_limit = ResourceLimit::Create("Others");
+ resource_limit->max_priority = 0x4;
+ resource_limit->max_commit = 0x2180000;
+ resource_limit->max_threads = 0xE1;
+ resource_limit->max_events = 0x108;
+ resource_limit->max_mutexes = 0x25;
+ resource_limit->max_semaphores = 0x43;
+ resource_limit->max_timers = 0x2C;
+ resource_limit->max_shared_mems = 0x1F;
+ resource_limit->max_address_arbiters = 0x2D;
+ resource_limit->max_cpu_time = 0x3E8;
+ resource_limits[static_cast<u8>(ResourceLimitCategory::OTHER)] = resource_limit;
+}
+
+void ResourceLimitsShutdown() {
+
+}
+
+} // namespace
diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h
new file mode 100644
index 000000000..201ec0db9
--- /dev/null
+++ b/src/core/hle/kernel/resource_limit.h
@@ -0,0 +1,119 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "common/common_types.h"
+
+#include "core/hle/kernel/kernel.h"
+
+namespace Kernel {
+
+enum class ResourceLimitCategory : u8 {
+ APPLICATION = 0,
+ SYS_APPLET = 1,
+ LIB_APPLET = 2,
+ OTHER = 3
+};
+
+enum ResourceTypes {
+ PRIORITY = 0,
+ COMMIT = 1,
+ THREAD = 2,
+ EVENT = 3,
+ MUTEX = 4,
+ SEMAPHORE = 5,
+ TIMER = 6,
+ SHARED_MEMORY = 7,
+ ADDRESS_ARBITER = 8,
+ CPU_TIME = 9,
+};
+
+class ResourceLimit final : public Object {
+public:
+ /**
+ * Creates a resource limit object.
+ */
+ static SharedPtr<ResourceLimit> Create(std::string name = "Unknown");
+
+ /**
+ * Retrieves the resource limit associated with the specified resource limit category.
+ * @param category The resource limit category
+ * @returns The resource limit associated with the category
+ */
+ static SharedPtr<ResourceLimit> GetForCategory(ResourceLimitCategory category);
+
+ std::string GetTypeName() const override { return "ResourceLimit"; }
+ std::string GetName() const override { return name; }
+
+ static const HandleType HANDLE_TYPE = HandleType::ResourceLimit;
+ HandleType GetHandleType() const override { return HANDLE_TYPE; }
+
+ /**
+ * Gets the current value for the specified resource.
+ * @param resource Requested resource type
+ * @returns The current value of the resource type
+ */
+ s32 GetCurrentResourceValue(u32 resource) const;
+
+ /**
+ * Gets the max value for the specified resource.
+ * @param resource Requested resource type
+ * @returns The max value of the resource type
+ */
+ s32 GetMaxResourceValue(u32 resource) const;
+
+ /// Name of resource limit object.
+ std::string name;
+
+ /// Max thread priority that a process in this category can create
+ s32 max_priority = 0;
+
+ /// Max memory that processes in this category can use
+ s32 max_commit = 0;
+
+ ///< Max number of objects that can be collectively created by the processes in this category
+ s32 max_threads = 0;
+ s32 max_events = 0;
+ s32 max_mutexes = 0;
+ s32 max_semaphores = 0;
+ s32 max_timers = 0;
+ s32 max_shared_mems = 0;
+ s32 max_address_arbiters = 0;
+
+ /// Max CPU time that the processes in this category can utilize
+ s32 max_cpu_time = 0;
+
+ // TODO(Subv): Increment these in their respective Kernel::T::Create functions, keeping in mind that
+ // APPLICATION resource limits should not be affected by the objects created by service modules.
+ // Currently we have no way of distinguishing if a Create was called by the running application,
+ // or by a service module. Approach this once we have separated the service modules into their own processes
+
+ /// Current memory that the processes in this category are using
+ s32 current_commit = 0;
+
+ ///< Current number of objects among all processes in this category
+ s32 current_threads = 0;
+ s32 current_events = 0;
+ s32 current_mutexes = 0;
+ s32 current_semaphores = 0;
+ s32 current_timers = 0;
+ s32 current_shared_mems = 0;
+ s32 current_address_arbiters = 0;
+
+ /// Current CPU time that the processes in this category are utilizing
+ s32 current_cpu_time = 0;
+
+private:
+ ResourceLimit();
+ ~ResourceLimit() override;
+};
+
+/// Initializes the resource limits
+void ResourceLimitsInit();
+
+// Destroys the resource limits
+void ResourceLimitsShutdown();
+
+} // namespace
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 9bf886256..654ee2bf6 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -17,6 +17,7 @@
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/mutex.h"
#include "core/hle/kernel/process.h"
+#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/semaphore.h"
#include "core/hle/kernel/shared_memory.h"
#include "core/hle/kernel/thread.h"
@@ -301,21 +302,47 @@ static void OutputDebugString(const char* string) {
}
/// Get resource limit
-static ResultCode GetResourceLimit(Handle* resource_limit, Handle process) {
- // With regards to proceess values:
- // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for
- // the current KThread.
- *resource_limit = 0xDEADBEEF;
- LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called process=0x%08X", process);
+static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle) {
+ LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle);
+
+ SharedPtr<Kernel::Process> process = Kernel::g_handle_table.Get<Kernel::Process>(process_handle);
+ if (process == nullptr)
+ return ERR_INVALID_HANDLE;
+
+ CASCADE_RESULT(*resource_limit, Kernel::g_handle_table.Create(process->resource_limit));
+
return RESULT_SUCCESS;
}
/// Get resource limit current values
-static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* names,
+static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit_handle, u32* names,
+ s32 name_count) {
+ LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d",
+ resource_limit_handle, names, name_count);
+
+ SharedPtr<Kernel::ResourceLimit> resource_limit = Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle);
+ if (resource_limit == nullptr)
+ return ERR_INVALID_HANDLE;
+
+ for (unsigned int i = 0; i < name_count; ++i)
+ values[i] = resource_limit->GetCurrentResourceValue(names[i]);
+
+ return RESULT_SUCCESS;
+}
+
+/// Get resource limit max values
+static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit_handle, u32* names,
s32 name_count) {
- LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called resource_limit=%08X, names=%p, name_count=%d",
- resource_limit, names, name_count);
- values[0] = 0; // Normmatt: Set used memory to 0 for now
+ LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d",
+ resource_limit_handle, names, name_count);
+
+ SharedPtr<Kernel::ResourceLimit> resource_limit = Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle);
+ if (resource_limit == nullptr)
+ return ERR_INVALID_HANDLE;
+
+ for (unsigned int i = 0; i < name_count; ++i)
+ values[i] = resource_limit->GetMaxResourceValue(names[i]);
+
return RESULT_SUCCESS;
}
@@ -707,7 +734,7 @@ static const FunctionDef SVC_Table[] = {
{0x36, HLE::Wrap<GetProcessIdOfThread>, "GetProcessIdOfThread"},
{0x37, HLE::Wrap<GetThreadId>, "GetThreadId"},
{0x38, HLE::Wrap<GetResourceLimit>, "GetResourceLimit"},
- {0x39, nullptr, "GetResourceLimitLimitValues"},
+ {0x39, HLE::Wrap<GetResourceLimitLimitValues>, "GetResourceLimitLimitValues"},
{0x3A, HLE::Wrap<GetResourceLimitCurrentValues>, "GetResourceLimitCurrentValues"},
{0x3B, nullptr, "GetThreadContext"},
{0x3C, nullptr, "Break"},
diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp
index 84b13ee52..ad5e929ce 100644
--- a/src/core/loader/3dsx.cpp
+++ b/src/core/loader/3dsx.cpp
@@ -9,6 +9,7 @@
#include "core/file_sys/archive_romfs.h"
#include "core/hle/kernel/process.h"
+#include "core/hle/kernel/resource_limit.h"
#include "core/hle/service/fs/archive.h"
#include "core/loader/elf.h"
#include "core/loader/ncch.h"
@@ -233,6 +234,9 @@ ResultStatus AppLoader_THREEDSX::Load() {
Kernel::g_current_process = Kernel::Process::Create(filename, 0);
Kernel::g_current_process->svc_access_mask.set();
Kernel::g_current_process->address_mappings = default_address_mappings;
+
+ // Attach the default resource limit (APPLICATION) to the process
+ Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
Load3DSXFile(*file, Memory::PROCESS_IMAGE_VADDR);
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp
index a951bc80f..f00753a79 100644
--- a/src/core/loader/elf.cpp
+++ b/src/core/loader/elf.cpp
@@ -11,6 +11,7 @@
#include "common/symbols.h"
#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/resource_limit.h"
#include "core/loader/elf.h"
#include "core/memory.h"
@@ -354,6 +355,9 @@ ResultStatus AppLoader_ELF::Load() {
Kernel::g_current_process->svc_access_mask.set();
Kernel::g_current_process->address_mappings = default_address_mappings;
+ // Attach the default resource limit (APPLICATION) to the process
+ Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
+
ElfReader elf_reader(&buffer[0]);
elf_reader.LoadInto(Memory::PROCESS_IMAGE_VADDR);
// TODO: Fill application title
diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp
index 36e341fd4..08993c4fa 100644
--- a/src/core/loader/ncch.cpp
+++ b/src/core/loader/ncch.cpp
@@ -11,6 +11,7 @@
#include "common/swap.h"
#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/resource_limit.h"
#include "core/loader/ncch.h"
#include "core/memory.h"
@@ -126,6 +127,10 @@ ResultStatus AppLoader_NCCH::LoadExec() const {
u64 program_id = *reinterpret_cast<u64_le const*>(&ncch_header.program_id[0]);
Kernel::g_current_process = Kernel::Process::Create(process_name, program_id);
+ // Attach a resource limit to the process based on the resource limit category
+ Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(
+ static_cast<Kernel::ResourceLimitCategory>(exheader_header.arm11_system_local_caps.resource_limit_category));
+
// Copy data while converting endianess
std::array<u32, ARRAY_SIZE(exheader_header.arm11_kernel_caps.descriptors)> kernel_caps;
std::copy_n(exheader_header.arm11_kernel_caps.descriptors, kernel_caps.size(), begin(kernel_caps));