diff options
Diffstat (limited to 'src/core/hle/svc.cpp')
-rw-r--r-- | src/core/hle/svc.cpp | 131 |
1 files changed, 116 insertions, 15 deletions
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index bbb4eb9cd..9bf886256 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -4,6 +4,8 @@ #include <map> +#include "common/logging/log.h" +#include "common/profiler.h" #include "common/string_util.h" #include "common/symbols.h" @@ -14,6 +16,7 @@ #include "core/hle/kernel/address_arbiter.h" #include "core/hle/kernel/event.h" #include "core/hle/kernel/mutex.h" +#include "core/hle/kernel/process.h" #include "core/hle/kernel/semaphore.h" #include "core/hle/kernel/shared_memory.h" #include "core/hle/kernel/thread.h" @@ -283,8 +286,13 @@ static ResultCode ArbitrateAddress(Handle handle, u32 address, u32 type, u32 val if (arbiter == nullptr) return ERR_INVALID_HANDLE; - return arbiter->ArbitrateAddress(static_cast<Kernel::ArbitrationType>(type), - address, value, nanoseconds); + auto res = arbiter->ArbitrateAddress(static_cast<Kernel::ArbitrationType>(type), + address, value, nanoseconds); + + if (res == RESULT_SUCCESS) + HLE::Reschedule(__func__); + + return res; } /// Used to output a message on a debug hardware unit - does nothing on a retail unit @@ -305,14 +313,14 @@ static ResultCode GetResourceLimit(Handle* resource_limit, Handle process) { /// Get resource limit current values static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* names, s32 name_count) { - LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called resource_limit=%08X, names=%s, name_count=%d", + LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called resource_limit=%08X, names=%p, name_count=%d", resource_limit, names, name_count); - Memory::Write32(Core::g_app_core->GetReg(0), 0); // Normmatt: Set used memory to 0 for now + values[0] = 0; // Normmatt: Set used memory to 0 for now return RESULT_SUCCESS; } /// Creates a new thread -static ResultCode CreateThread(u32* out_handle, u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 processor_id) { +static ResultCode CreateThread(Handle* out_handle, s32 priority, u32 entry_point, u32 arg, u32 stack_top, s32 processor_id) { using Kernel::Thread; std::string name; @@ -323,6 +331,27 @@ static ResultCode CreateThread(u32* out_handle, u32 priority, u32 entry_point, u name = Common::StringFromFormat("unknown-%08x", entry_point); } + // TODO(bunnei): Implement resource limits to return an error code instead of the below assert. + // The error code should be: Description::NotAuthorized, Module::OS, Summary::WrongArgument, + // Level::Permanent + ASSERT_MSG(priority >= THREADPRIO_USERLAND_MAX, "Unexpected thread priority!"); + + if (priority > THREADPRIO_LOWEST) { + return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, + ErrorSummary::InvalidArgument, ErrorLevel::Usage); + } + + switch (processor_id) { + case THREADPROCESSORID_DEFAULT: + case THREADPROCESSORID_0: + case THREADPROCESSORID_1: + break; + default: + // TODO(bunnei): Implement support for other processor IDs + ASSERT_MSG(false, "Unsupported thread processor ID: %d", processor_id); + break; + } + CASCADE_RESULT(SharedPtr<Thread> thread, Kernel::Thread::Create( name, entry_point, priority, arg, processor_id, stack_top)); CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(thread))); @@ -331,10 +360,7 @@ static ResultCode CreateThread(u32* out_handle, u32 priority, u32 entry_point, u "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point, name.c_str(), arg, stack_top, priority, processor_id, *out_handle); - if (THREADPROCESSORID_1 == processor_id) { - LOG_WARNING(Kernel_SVC, - "thread designated for system CPU core (UNIMPLEMENTED) will be run with app core scheduling"); - } + HLE::Reschedule(__func__); return RESULT_SUCCESS; } @@ -374,8 +400,11 @@ static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) { SharedPtr<Mutex> mutex = Mutex::Create(initial_locked != 0); CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex))); + HLE::Reschedule(__func__); + LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X", initial_locked ? "true" : "false", *out_handle); + return RESULT_SUCCESS; } @@ -390,6 +419,37 @@ static ResultCode ReleaseMutex(Handle handle) { return ERR_INVALID_HANDLE; mutex->Release(); + + HLE::Reschedule(__func__); + + return RESULT_SUCCESS; +} + +/// Get the ID of the specified process +static ResultCode GetProcessId(u32* process_id, Handle process_handle) { + LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle); + + const SharedPtr<Kernel::Process> process = Kernel::g_handle_table.Get<Kernel::Process>(process_handle); + if (process == nullptr) + return ERR_INVALID_HANDLE; + + *process_id = process->process_id; + return RESULT_SUCCESS; +} + +/// Get the ID of the process that owns the specified thread +static ResultCode GetProcessIdOfThread(u32* process_id, Handle thread_handle) { + LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle); + + const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(thread_handle); + if (thread == nullptr) + return ERR_INVALID_HANDLE; + + const SharedPtr<Kernel::Process> process = thread->owner_process; + + ASSERT_MSG(process != nullptr, "Invalid parent process for thread=0x%08X", thread_handle); + + *process_id = process->process_id; return RESULT_SUCCESS; } @@ -428,6 +488,9 @@ static ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) return ERR_INVALID_HANDLE; CASCADE_RESULT(*count, semaphore->Release(release_count)); + + HLE::Reschedule(__func__); + return RESULT_SUCCESS; } @@ -520,6 +583,9 @@ static ResultCode SetTimer(Handle handle, s64 initial, s64 interval) { return ERR_INVALID_HANDLE; timer->Set(initial, interval); + + HLE::Reschedule(__func__); + return RESULT_SUCCESS; } @@ -534,6 +600,9 @@ static ResultCode CancelTimer(Handle handle) { return ERR_INVALID_HANDLE; timer->Cancel(); + + HLE::Reschedule(__func__); + return RESULT_SUCCESS; } @@ -561,14 +630,26 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 using Kernel::SharedMemory; // TODO(Subv): Implement this function - SharedPtr<SharedMemory> shared_memory = SharedMemory::Create(); + using Kernel::MemoryPermission; + SharedPtr<SharedMemory> shared_memory = SharedMemory::Create(size, + (MemoryPermission)my_permission, (MemoryPermission)other_permission); CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory))); LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x%08X", addr); return RESULT_SUCCESS; } -const HLE::FunctionDef SVC_Table[] = { +namespace { + struct FunctionDef { + using Func = void(); + + u32 id; + Func* func; + const char* name; + }; +} + +static const FunctionDef SVC_Table[] = { {0x00, nullptr, "Unknown"}, {0x01, HLE::Wrap<ControlMemory>, "ControlMemory"}, {0x02, HLE::Wrap<QueryMemory>, "QueryMemory"}, @@ -622,8 +703,8 @@ const HLE::FunctionDef SVC_Table[] = { {0x32, HLE::Wrap<SendSyncRequest>, "SendSyncRequest"}, {0x33, nullptr, "OpenProcess"}, {0x34, nullptr, "OpenThread"}, - {0x35, nullptr, "GetProcessId"}, - {0x36, nullptr, "GetProcessIdOfThread"}, + {0x35, HLE::Wrap<GetProcessId>, "GetProcessId"}, + {0x36, HLE::Wrap<GetProcessIdOfThread>, "GetProcessIdOfThread"}, {0x37, HLE::Wrap<GetThreadId>, "GetThreadId"}, {0x38, HLE::Wrap<GetResourceLimit>, "GetResourceLimit"}, {0x39, nullptr, "GetResourceLimitLimitValues"}, @@ -697,8 +778,28 @@ const HLE::FunctionDef SVC_Table[] = { {0x7D, nullptr, "QueryProcessMemory"}, }; -void Register() { - HLE::RegisterModule("SVC_Table", ARRAY_SIZE(SVC_Table), SVC_Table); +Common::Profiling::TimingCategory profiler_svc("SVC Calls"); + +static const FunctionDef* GetSVCInfo(u32 opcode) { + u32 func_num = opcode & 0xFFFFFF; // 8 bits + if (func_num >= ARRAY_SIZE(SVC_Table)) { + LOG_ERROR(Kernel_SVC, "unknown svc=0x%02X", func_num); + return nullptr; + } + return &SVC_Table[func_num]; +} + +void CallSVC(u32 opcode) { + Common::Profiling::ScopeTimer timer_svc(profiler_svc); + + const FunctionDef *info = GetSVCInfo(opcode); + if (info) { + if (info->func) { + info->func(); + } else { + LOG_ERROR(Kernel_SVC, "unimplemented SVC function %s(..)", info->name); + } + } } } // namespace |