From e5c501e5b66fbeeb57cbc03856582ad470084aca Mon Sep 17 00:00:00 2001 From: SciresM Date: Sat, 18 Jan 2020 12:39:05 -0800 Subject: [PATCH] svc: Add all missing SVC stubs (#364) --- nx/include/switch/kernel/svc.h | 242 ++++++++++++++++++++++++++++++++- nx/source/kernel/svc.s | 111 +++++++++++++++ 2 files changed, 350 insertions(+), 3 deletions(-) diff --git a/nx/include/switch/kernel/svc.h b/nx/include/switch/kernel/svc.h index 1dd1c142..21a8cc92 100644 --- a/nx/include/switch/kernel/svc.h +++ b/nx/include/switch/kernel/svc.h @@ -205,6 +205,35 @@ typedef enum { PhysicalMemoryInfo_SystemUnsafe = 3, ///< Memory allocated for unsafe system usage (accessible to devices). } PhysicalMemoryInfo; +/// SleepThread yield types. +typedef enum { + YieldType_WithoutCoreMigration = 0l, ///< Yields to another thread on the same core. + YieldType_WithCoreMigration = -1l, ///< Yields to another thread (possibly on a different core). + YieldType_ToAnyThread = -2l, ///< Yields and performs forced load-balancing. +} YieldType; + +/// SignalToAddress behaviors. +typedef enum { + SignalType_Signal = 0, ///< Signals the address. + SignalType_SignalAndIncrementIfEqual = 1, ///< Signals the address and increments its value if equal to argument. + SignalType_SignalAndModifyBasedOnWaitingThreadCountIfEqual = 2, ///< Signals the address and updates its value if equal to argument. +} SignalType; + +/// WaitForAddress behaviors. +typedef enum { + ArbitrationType_WaitIfLessThan = 0, ///< Wait if the value is less than argument. + ArbitrationType_DecrementAndWaitIfLessThan = 1, ///< Decrement the value and wait if it is less than argument. + ArbitrationType_WaitIfEqual = 2, ///< Wait if the value is equal to argument. +} ArbitrationType; + +/// Context of a scheduled thread. +typedef struct { + u64 fp; ///< Frame Pointer for the thread. + u64 sp; ///< Stack Pointer for the thread. + u64 lr; ///< Link Register for the thread. + u64 pc; ///< Program Counter for the thread. +} LastThreadContext; + ///@name Memory management ///@{ @@ -306,7 +335,7 @@ void NORETURN svcExitThread(void); /** * @brief Sleeps the current thread for the specified amount of time. - * @param[in] nano Number of nanoseconds to sleep, or 0, -1, -2 for yield. + * @param[in] nano Number of nanoseconds to sleep, or \ref YieldType for yield. * @note Syscall number 0x0B. */ void svcSleepThread(s64 nano); @@ -500,6 +529,13 @@ u64 svcGetSystemTick(void); */ Result svcConnectToNamedPort(Handle* session, const char* name); +/** + * @brief Sends a light IPC synchronization request to a session. + * @return Result code. + * @note Syscall number 0x20. + */ +Result svcSendSyncRequestLight(Handle session); + /** * @brief Sends an IPC synchronization request to a session. * @return Result code. @@ -597,6 +633,28 @@ Result svcGetInfo(u64* out, u32 id0, Handle handle, u64 id1); ///@} +///@name Cache Management +///@{ + +/** + * @brief Flushes the entire data cache (by set/way). + * @note Syscall number 0x2A. + * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. + * @warning This syscall is dangerous, and should not be used. + */ +void svcFlushEntireDataCache(void); + +/** + * @brief Flushes data cache for a virtual address range. + * @param[in] address Address of region to flush. + * @param[in] size Size of region to flush. + * @remark armDCacheFlush should be used instead of this syscall whenever possible. + * @note Syscall number 0x2B. + */ +Result svcFlushDataCache(void *address, size_t size); + +///@} + ///@name Memory management ///@{ @@ -604,7 +662,6 @@ Result svcGetInfo(u64* out, u32 id0, Handle handle, u64 id1); * @brief Maps new heap memory at the desired address. [3.0.0+] * @return Result code. * @note Syscall number 0x2C. - * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. */ Result svcMapPhysicalMemory(void *address, u64 size); @@ -612,12 +669,38 @@ Result svcMapPhysicalMemory(void *address, u64 size); * @brief Undoes the effects of \ref svcMapPhysicalMemory. [3.0.0+] * @return Result code. * @note Syscall number 0x2D. - * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. */ Result svcUnmapPhysicalMemory(void *address, u64 size); ///@} +///@name Process and thread management +///@{ + +/** + * @brief Gets information about a thread that will be scheduled in the future. [5.0.0+] + * @param[out] out_context Output \ref LastThreadContext for the thread that will be scheduled. + * @param[out] out_thread_id Output thread id for the thread that will be scheduled. + * @param[in] debug Debug handle. + * @param[in] ns Nanoseconds in the future to get scheduled thread at. + * @return Result code. + * @note Syscall number 0x2E. + * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. + */ +Result svcGetDebugFutureThreadInfo(LastThreadContext *out_context, u64 *out_thread_id, Handle debug, s64 ns); + +/** + * @brief Gets information about the previously-scheduled thread. + * @param[out] out_context Output \ref LastThreadContext for the previously scheduled thread. + * @param[out] out_tls_address Output tls address for the previously scheduled thread. + * @param[out] out_flags Output flags for the previously scheduled thread. + * @return Result code. + * @note Syscall number 0x2F. + */ +Result svcGetLastThreadInfo(LastThreadContext *out_context, u64 *out_tls_address, u32 *out_flags); + +///@} + ///@name Resource Limit Management ///@{ @@ -661,6 +744,76 @@ Result svcGetThreadContext3(ThreadContext* ctx, Handle thread); ///@} +///@name Synchronization +///@{ + +/** + * @brief Arbitrates an address depending on type and value. [4.0.0+] + * @param[in] address Address to arbitrate. + * @param[in] arb_type \ref ArbitrationType to use. + * @param[in] value Value to arbitrate on. + * @param[in] timeout Maximum time in nanoseconds to wait. + * @return Result code. + * @note Syscall number 0x34. + */ +Result svcWaitForAddress(void *address, u32 arb_type, s32 value, s64 timeout); + +/** + * @brief Signals (and updates) an address depending on type and value. [4.0.0+] + * @param[in] address Address to arbitrate. + * @param[in] signal_type \ref SignalType to use. + * @param[in] value Value to arbitrate on. + * @param[in] count Number of waiting threads to signal. + * @return Result code. + * @note Syscall number 0x35. + */ +Result svcSignalToAddress(void *address, u32 signal_type, s32 value, s32 count); + +///@} + +///@name Miscellaneous +///@{ + +/** + * @brief Sets thread preemption state (used during abort/panic). [8.0.0+] + * @note Syscall number 0x36. + */ +void svcSynchronizePreemptionState(void); + +///@} + +///@name Debugging +///@{ +/** + * @brief Causes the kernel to dump debug information. [1.0.0-3.0.2] + * @param[in] dump_info_type Type of information to dump. + * @param[in] arg0 Argument to the debugging operation. + * @note Syscall number 0x3C. + * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. + */ +void svcDumpInfo(u32 dump_info_type, u64 arg0); + +/** + * @brief Performs a debugging operation on the kernel. [4.0.0+] + * @param[in] kern_debug_type Type of debugging operation to perform. + * @param[in] arg0 First argument to the debugging operation. + * @param[in] arg1 Second argument to the debugging operation. + * @param[in] arg2 Third argument to the debugging operation. + * @note Syscall number 0x3C. + * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. + */ +void svcKernelDebug(u32 kern_debug_type, u64 arg0, u64 arg1, u64 arg2); + +/** + * @brief Performs a debugging operation on the kernel. [4.0.0+] + * @param[in] kern_trace_state Type of tracing the kernel should perform. + * @note Syscall number 0x3D. + * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. + */ +void svcChangeKernelTraceState(u32 kern_trace_state); + +///@} + \ ///@name Inter-process communication (IPC) ///@{ @@ -680,6 +833,15 @@ Result svcCreateSession(Handle *server_handle, Handle *client_handle, u32 unk0, */ Result svcAcceptSession(Handle *session_handle, Handle port_handle); +/** + * @brief Performs light IPC input/output. + * @return Result code. + * @param[in] handle Server or port handle to act on. + * @note Syscall number 0x42. + * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. + */ +Result svcReplyAndReceiveLight(Handle handle); + /** * @brief Performs IPC input/output. * @return Result code. @@ -762,6 +924,18 @@ Result svcControlCodeMemory(Handle code_handle, CodeMapOperation op, void* dst_a ///@} +///@name Power Management +///@{ + +/** + * @brief Causes the system to enter deep sleep. + * @note Syscall number 0x4D. + * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. + */ +void svcSleepSystem(void); + +///@} + ///@name Device memory-mapped I/O (MMIO) ///@{ @@ -775,6 +949,19 @@ Result svcReadWriteRegister(u32* outVal, u64 regAddr, u32 rwMask, u32 inVal); ///@} +///@name Process and thread management +///@{ + +/** + * @brief Configures the pause/unpause status of a process. + * @return Result code. + * @note Syscall number 0x4F. + * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. + */ +Result svcSetProcessActivity(Handle process, bool paused); + +///@} + ///@name Inter-process memory sharing ///@{ @@ -878,6 +1065,15 @@ Result svcMapDeviceAddressSpaceByForce(Handle handle, Handle proc_handle, u64 ma */ Result svcMapDeviceAddressSpaceAligned(Handle handle, Handle proc_handle, u64 map_addr, u64 dev_size, u64 dev_addr, u32 perm); +/** + * @brief Maps an attached device address space to an userspace address. + * @return Result code. + * @remark The userspace destination address must have the \ref MemState_MapDeviceAlignedAllowed bit set. + * @note Syscall number 0x5B. + * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. + */ +Result svcMapDeviceAddressSpace(u64 *out_mapped_size, Handle handle, Handle proc_handle, u64 map_addr, u64 dev_size, u64 dev_addr, u32 perm); + /** * @brief Unmaps an attached device address space from an userspace address. * @return Result code. @@ -888,6 +1084,38 @@ Result svcUnmapDeviceAddressSpace(Handle handle, Handle proc_handle, u64 map_add ///@} +///@name Cache Management +///@{ + +/** + * @brief Invalidates data cache for a virtual address range within a process. + * @param[in] address Address of region to invalidate. + * @param[in] size Size of region to invalidate. + * @note Syscall number 0x5D. + * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. + */ +Result svcInvalidateProcessDataCache(Handle process, uintptr_t address, size_t size); + +/** + * @brief Stores data cache for a virtual address range within a process. + * @param[in] address Address of region to store. + * @param[in] size Size of region to store. + * @note Syscall number 0x5E. + * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. + */ +Result svcStoreProcessDataCache(Handle process, uintptr_t address, size_t size); + +/** + * @brief Flushes data cache for a virtual address range within a process. + * @param[in] address Address of region to flush. + * @param[in] size Size of region to flush. + * @note Syscall number 0x5F. + * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. + */ +Result svcFlushProcessDataCache(Handle process, uintptr_t address, size_t size); + +///@} + ///@name Debugging ///@{ @@ -1017,6 +1245,14 @@ Result svcReadDebugProcessMemory(void* buffer, Handle debug, u64 addr, u64 size) */ Result svcWriteDebugProcessMemory(Handle debug, const void* buffer, u64 addr, u64 size); +/** + * @brief Sets one of the hardware breakpoints. + * @return Result code. + * @note Syscall number 0x6C. + * @warning This is a privileged syscall. Use \ref envIsSyscallHinted to check if it is available. + */ +Result svcSetHardwareBreakPoint(u32 which, u64 flags, u64 value); + /** * @brief Gets parameters from a thread in a debugging session. * @return Result code. diff --git a/nx/source/kernel/svc.s b/nx/source/kernel/svc.s index 047cebf5..3fc62974 100644 --- a/nx/source/kernel/svc.s +++ b/nx/source/kernel/svc.s @@ -191,6 +191,11 @@ SVC_BEGIN svcConnectToNamedPort ret SVC_END +SVC_BEGIN svcSendSyncRequestLight + svc 0x20 + ret +SVC_END + SVC_BEGIN svcSendSyncRequest svc 0x21 ret @@ -248,6 +253,16 @@ SVC_BEGIN svcGetInfo ret SVC_END +SVC_BEGIN svcFlushEntireDataCache + svc 0x2A + ret +SVC_END + +SVC_BEGIN svcFlushDataCache + svc 0x2B + ret +SVC_END + SVC_BEGIN svcMapPhysicalMemory svc 0x2C ret @@ -258,6 +273,29 @@ SVC_BEGIN svcUnmapPhysicalMemory ret SVC_END +SVC_BEGIN svcGetDebugFutureThreadInfo + stp x0, x1, [sp, #-16]! + svc 0x2E + ldp x6, x7, [sp], #16 + stp x1, x2, [x6] + stp x3, x4, [x6, #16] + str x5, [x7] + ret +SVC_END + +SVC_BEGIN svcGetLastThreadInfo + stp x1, x2, [sp, #-16]! + str x0, [sp, #-16]! + svc 0x2F + ldr x7, [sp], #16 + stp x1, x2, [x7] + stp x3, x4, [x7, #16] + ldp x1, x2, [sp], #16 + str x5, [x1] + str w6, [x2] + ret +SVC_END + SVC_BEGIN svcGetResourceLimitLimitValue str x0, [sp, #-16]! svc 0x30 @@ -284,6 +322,36 @@ SVC_BEGIN svcGetThreadContext3 ret SVC_END +SVC_BEGIN svcWaitForAddress + svc 0x34 + ret +SVC_END + +SVC_BEGIN svcSignalToAddress + svc 0x35 + ret +SVC_END + +SVC_BEGIN svcSynchronizePreemptionState + svc 0x36 + ret +SVC_END + +SVC_BEGIN svcDumpInfo + svc 0x3C + ret +SVC_END + +SVC_BEGIN svcKernelDebug + svc 0x3C + ret +SVC_END + +SVC_BEGIN svcChangeKernelTraceState + svc 0x3D + ret +SVC_END + SVC_BEGIN svcCreateSession stp x0, x1, [sp, #-16]! svc 0x40 @@ -301,6 +369,11 @@ SVC_BEGIN svcAcceptSession ret SVC_END +SVC_BEGIN svcReplyAndReceiveLight + svc 0x42 + ret +SVC_END + SVC_BEGIN svcReplyAndReceive str x0, [sp, #-16]! svc 0x43 @@ -354,6 +427,11 @@ SVC_BEGIN svcControlCodeMemory ret SVC_END +SVC_BEGIN svcSleepSystem + svc 0x4D + ret +SVC_END + SVC_BEGIN svcReadWriteRegister str x0, [sp, #-16]! svc 0x4E @@ -362,6 +440,11 @@ SVC_BEGIN svcReadWriteRegister ret SVC_END +SVC_BEGIN svcSetProcessActivity + svc 0x4F + ret +SVC_END + SVC_BEGIN svcCreateSharedMemory str x0, [sp, #-16]! svc 0x50 @@ -433,11 +516,34 @@ SVC_BEGIN svcMapDeviceAddressSpaceAligned ret SVC_END +SVC_BEGIN svcMapDeviceAddressSpace + str x0, [sp, #-16]! + svc 0x5B + ldr x2, [sp], #16 + str w1, [x2] + ret +SVC_END + SVC_BEGIN svcUnmapDeviceAddressSpace svc 0x5C ret SVC_END +SVC_BEGIN svcInvalidateProcessDataCache + svc 0x5D + ret +SVC_END + +SVC_BEGIN svcStoreProcessDataCache + svc 0x5E + ret +SVC_END + +SVC_BEGIN svcFlushProcessDataCache + svc 0x5F + ret +SVC_END + SVC_BEGIN svcDebugActiveProcess str x0, [sp, #-16]! svc 0x60 @@ -515,6 +621,11 @@ SVC_BEGIN svcWriteDebugProcessMemory ret SVC_END +SVC_BEGIN svcSetHardwareBreakPoint + svc 0x6C + ret +SVC_END + SVC_BEGIN svcGetDebugThreadParam stp x0, x1, [sp, #-16]! svc 0x6D