系统调用列表
系统调用
| Id | Description | 
|---|---|
| 0x1 | Result ControlMemory(u32* outaddr, u32 addr0, u32 addr1, u32 size, u32 operation, u32 permissions) (outaddr is usually the same as the input addr0) | 
| 0x2 | Result QueryMemory(MemoryInfo* info, PageInfo* out, u32 Addr) | 
| 0x3 | void ExitProcess(void) | 
| 0x4 | Result GetProcessAffinityMask(u8* affinitymask, Handle process, s32 processorcount) | 
| 0x5 | Result SetProcessAffinityMask(Handle process, u8* affinitymask, s32 processorcount) | 
| 0x6 | Result GetProcessIdealProcessor(s32 *idealprocessor, Handle process) | 
| 0x7 | Result SetProcessIdealProcessor(Handle process, s32 idealprocessor) | 
| 0x8 | Result CreateThread(Handle* thread, func entrypoint, u32 arg, u32 stacktop, s32 threadpriority, s32 processorid) | 
| 0x9 | void ExitThread(void) | 
| 0xA | void SleepThread(s64 nanoseconds) | 
| 0xB | Result GetThreadPriority(s32* priority, Handle thread) | 
| 0xC | Result SetThreadPriority(Handle thread, s32 priority) | 
| 0xD | Result GetThreadAffinityMask(u8* affinitymask, Handle thread, s32 processorcount) | 
| 0xE | Result SetThreadAffinityMask(Handle thread, u8* affinitymask, s32 processorcount) | 
| 0xF | Result GetThreadIdealProcessor(s32* processorid, Handle thread) | 
| 0x10 | Result SetThreadIdealProcessor(Handle thread, s32 processorid) | 
| 0x11 | s32 GetCurrentProcessorNumber(void) | 
| 0x12 | Result Run(Handle process, StartupInfo* info) (This starts the main() thread. Buf+0 is main-thread priority, Buf+4 is main-thread stack-size.) | 
| 0x13 | Result CreateMutex(Handle* mutex, bool initialLocked) | 
| 0x14 | Result ReleaseMutex(Handle mutex) | 
| 0x15 | Result CreateSemaphore(Handle* semaphore, s32 initialCount, s32 maxCount) | 
| 0x16 | Result ReleaseSemaphore(s32* count, Handle semaphore, s32 releaseCount) | 
| 0x17 | Result CreateEvent(Handle* event, ResetType resettype) | 
| 0x18 | Result SignalEvent(Handle event) | 
| 0x19 | Result ClearEvent(Handle event) | 
| 0x1A | Result CreateTimer(Handle* timer, ResetType resettype) | 
| 0x1B | Result SetTimer(Handle timer, s64 initial, s64 interval) | 
| 0x1C | Result CancelTimer(Handle timer) | 
| 0x1D | Result ClearTimer(Handle timer) | 
| 0x1E | Result CreateMemoryBlock(Handle* memblock, u32 memory, u32 size, u32 mypermission, u32 otherpermission) | 
| 0x1F | Result MapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherpermission) | 
| 0x20 | Result UnmapMemoryBlock(Handle memblock, u32 addr) | 
| 0x21 | Result CreateAddressArbiter(Handle* arbiter) | 
| 0x22 | Result ArbitrateAddress(Handle arbiter, u32 addr, ArbitrationType type, s32 value) | 
| 0x23 | Result CloseHandle(Handle handle) | 
| 0x24 | Result WaitSynchronization1(Handle handle, s64 nanoseconds) | 
| 0x25 | Result WaitSynchronizationN(s32* out, Handle* handles, s32 handlecount, bool waitAll, s64 nanoseconds) | 
| 0x26 | Result SignalAndWait(s32* out, Handle signal, Handle* handles, s32 handleCount, bool waitAll, s64 nanoseconds) | 
| 0x27 | Result DuplicateHandle(Handle* out, Handle original) | 
| 0x28 | s64 GetSystemTick(void) | 
| 0x29 | Result GetHandleInfo(s64* out, Handle handle, HandleInfoType type) | 
| 0x2A | Result GetSystemInfo(s64* out, SystemInfoType type, s32 param) | 
| 0x2B | Result GetProcessInfo(s64* out, Handle process, ProcessInfoType type) | 
| 0x2C | Result GetThreadInfo(s64* out, Handle thread, ThreadInfoType type) | 
| 0x2D | Result ConnectToPort(Handle* out, const char* portName) | 
| 0x2E | Result SendSyncRequest1(Handle session) (Stubbed) | 
| 0x2F | Result SendSyncRequest2(Handle session) (Stubbed) | 
| 0x30 | Result SendSyncRequest3(Handle session) (Stubbed) | 
| 0x31 | Result SendSyncRequest4(Handle session) (Stubbed) | 
| 0x32 | Result SendSyncRequest(Handle session) | 
| 0x33 | Result OpenProcess(Handle* process, u32 processId) | 
| 0x34 | Result OpenThread(Handle* thread, Handle process, u32 threadId) | 
| 0x35 | Result GetProcessId(u32* processId, Handle process) | 
| 0x36 | Result GetProcessIdOfThread(u32* processId, Handle thread) | 
| 0x37 | Result GetThreadId(u32* threadId, Handle thread) | 
| 0x38 | Result GetResourceLimit(Handle* resourceLimit, Handle process) | 
| 0x39 | Result GetResourceLimitLimitValues(s64* values, Handle resourceLimit, LimitableResource* names, s32 nameCount) | 
| 0x3A | Result GetResourceLimitCurrentValues(s64* values, Handle resourceLimit, LimitableResource* names, s32 nameCount) | 
| 0x3B | Result GetThreadContext(ThreadContext* context, Handle thread) (Stubbed) | 
| 0x3C | Break(BreakReason) | 
| 0x3D | OutputDebugString(void const, int) (Does nothing on non-debug units) | 
| 0x3E | ControlPerformanceCounter(unsigned long long, int, unsigned int, unsigned long long) | 
| 0x47 | Result CreatePort(Handle* portServer, Handle* portClient, const char* name, s32 maxSessions) | 
| 0x48 | Result CreateSessionToPort(Handle* session, Handle port) | 
| 0x49 | Result CreateSession(Handle* sessionServer, Handle* sessionClient) | 
| 0x4A | Result AcceptSession(Handle* session, Handle port) | 
| 0x4B | Result ReplyAndReceive1(s32* index, Handle* handles, s32 handleCount, Handle replyTarget) (Stubbed) | 
| 0x4C | Result ReplyAndReceive2(s32* index, Handle* handles, s32 handleCount, Handle replyTarget) (Stubbed) | 
| 0x4D | Result ReplyAndReceive3(s32* index, Handle* handles, s32 handleCount, Handle replyTarget) (Stubbed) | 
| 0x4E | Result ReplyAndReceive4(s32* index, Handle* handles, s32 handleCount, Handle replyTarget) (Stubbed) | 
| 0x4F | Result ReplyAndReceive(s32* index, Handle* handles, s32 handleCount, Handle replyTarget) | 
| 0x50 | Result BindInterrupt(Interrupt name, Handle syncObject, s32 priority, bool isManualClear) | 
| 0x51 | Result UnbindInterrupt(Interrupt name, Handle syncObject) | 
| 0x52 | Result InvalidateProcessDataCache(Handle process, void* addr, u32 size) | 
| 0x53 | Result StoreProcessDataCache(Handle process, void const* addr, u32 size) | 
| 0x54 | Result FlushProcessDataCache(Handle process, void const* addr, u32 size) | 
| 0x55 | Result StartInterProcessDma(Handle* dma, Handle dstProcess, void* dst, Handle srcProcess, const void* src, u32 size, const DmaConfig& config ) | 
| 0x56 | Result StopDma(Handle dma) | 
| 0x57 | Result GetDmaState(DmaState* state, Handle dma) | 
| 0x58 | RestartDma(nn::Handle, void *, void const*, unsigned int, signed char) | 
| 0x60 | Result DebugActiveProcess(Handle* debug, u32 processID) | 
| 0x61 | Result BreakDebugProcess(Handle debug) | 
| 0x62 | Result TerminateDebugProcess(Handle debug) | 
| 0x63 | Result GetProcessDebugEvent(DebugEventInfo* info, Handle debug) | 
| 0x64 | Result ContinueDebugEvent(Handle debug, u32 flags) | 
| 0x65 | Result GetProcessList(s32* processCount, u32* processIds, s32 processIdMaxCount) | 
| 0x66 | Result GetThreadList(s32* threadCount, u32* threadIds, s32 threadIdMaxCount, Handle domain) | 
| 0x67 | Result GetDebugThreadContext(ThreadContext* context, Handle debug, u32 threadId, u32 controlFlags) | 
| 0x68 | Result SetDebugThreadContext(Handle debug, u32 threadId, ThreadContext* context, u32 controlFlags) | 
| 0x69 | Result QueryDebugProcessMemory(MemoryInfo* blockInfo, PageInfo* pageInfo, Handle process, u32 addr) | 
| 0x6A | Result ReadProcessMemory(void* buffer, Handle debug, u32 addr, u32 size) | 
| 0x6B | Result WriteProcessMemory(Handle debug, void const* buffer, u32 addr, u32 size) | 
| 0x6C | Result SetHardwareBreakPoint(s32 registerId, u32 control, u32 value) | 
| 0x6D | GetDebugThreadParam(long long *, int *, nn::Handle, unsigned int, nn::dmnt::DebugThreadParam) (Disabled on regular kernel) | 
| 0x70 | ControlProcessMemory(Handle KProcess, unsigned int Addr0, unsigned int Addr1, unsigned int Size, unsigned int Type, unsigned int Permissions) | 
| 0x71 | MapProcessMemory(Handle KProcess, unsigned int StartAddr, unsigned int EndAddr) | 
| 0x72 | UnmapProcessMemory(Handle KProcess, unsigned int StartAddr, unsigned int EndAddr) | 
| 0x73 | ? | 
| 0x74 | Stubbed on regular kernel | 
| 0x75 | ? | 
| 0x76 | TerminateProcess(Handle) | 
| 0x77 | (Handle KProcess, Handle KResourceLimit) | 
| 0x78 | CreateResourceLimit(Handle *KResourceLimit) | 
| 0x79 | ? | 
| 0x7A | DisableExecuteNever(unsigned int Addr, unsigned int Size) (Stubbed for regular kernel beginning with 2.0.0-2) | 
| 0x7C | KernelSetState(unsigned int Type, unsigned int Param0, unsigned int Param1, unsigned int Param2) (The Type determines the usage of each param) | 
| 0x7D | QueryProcessMemory(MemInfo *Info, unsigned int *Out, Handle KProcess, unsigned int Addr) | 
| 0xFF | Debug related (The Syscall access control mask doesn't apply for this SVC) | 
CreateThread
R0=s32 threadpriority R1=func entrypoint R2=u32 arg R3=u32 stacktop R4=s32 processorid
Result result=R0 Handle* thread=R1
类型和结构
枚举MemoryState
| Memory state flags | Bit | 
|---|---|
| FREE | 0 | 
| RESERVED | 1 | 
| IO | 2 | 
| STATIC | 3 | 
| CODE | 4 | 
| PRIVATE | 5 | 
| SHARED | 6 | 
| CONTINUOUS | 7 | 
| ALIASED | 8 | 
| ALIAS | 9 | 
| ALIAS CODE | 10 | 
| LOCKED | 11 | 
枚举PageFlags
| Page flags | Bit | 
|---|---|
| LOCKED | 0 | 
| CHANGED | 1 | 
枚举MemoryOperation
| Memory operation | Id | 
|---|---|
| FREE | 1 | 
| RESERVE | 2 | 
| COMMIT | 3 | 
| MAP | 4 | 
| UNMAP | 5 | 
| PROTECT | 6 | 
| REGION APP | 0x100 | 
| REGION SYSTEM | 0x200 | 
| REGION BASE | 0x300 | 
| LINEAR | 0x1000 | 
枚举MemoryPermission
| Memory permission | Id | 
|---|---|
| NONE | 0 | 
| READ | 1 | 
| WRITE | 2 | 
| READWRITE | 3 | 
| DONTCARE | 0x10000000 | 
枚举ResetType
| Reset type | Id | 
|---|---|
| ONESHOT | 0 | 
| STICKY | 1 | 
| PULSE | 2 | 
结构MemoryInfo
| Type | Field | 
|---|---|
| u32 | Base address | 
| u32 | Size | 
| u32 | Permission | 
| enum MemoryState | State | 
结构PageInfo
| Type | Field | 
|---|---|
| u32 | Flags | 
结构StartupInfo
| Type | Field | 
|---|---|
| s32 | Priority | 
| u32 | Stack size | 
| s32 | argc | 
| s16* | argv | 
| s16* | envp | 
进程
任何进程只能使用在exheader中为本进程启用的SVCs。ARM11内核SVN句柄会在SVC模式的栈中检查系统访问控制掩码以确定SVC是否已经启用,SVC没有启用时会触发kernelpanic。每个进程都有独立的SVC模式栈,这个栈和存放其中的系统访问控制掩码是在进程启动时候初始化的。应用程序一般只有那些<=0x3D的SVC访问权限,不过并非所有应用程序都有<=0x3D的所有SVCs权限。大部分应用程序可访问的SVCs并没有被应用程序使用。
每个进程都有各自的句柄表,表达大小存在exheader里面。在句柄表中的句柄不能被其他进程的上下文使用,因为这些句柄并不存在于其他的句柄表中。
0xFFFF8001是当前KProcess的句柄别称,而0xFFFF8000则是当前KThread的句柄别称。
在零售版机器上调用svcBreak只能造成调用这个SVC的进程被终止。
线程
对于svcCreateThread,用于Entrypoint_Param和StackTop输入地址常常一样,不过这可以任意设置。比如主线程的Entrypoint_Param就是0值。
用KThread句柄调用CloseHandle()会终结指定的线程。
内存映射
ControlMemory和MapMemoryBlock可以在映射内存页面时使用,这两个SVCs只支持映射不可执行的R/W页面。为这两个SVCs输入的权限和参数必须<=3,如果要取消映射,需要使用0值。对于ControlMemory参数MemoryType的位码0xF00是内存类型,该位使用0的时候,会从exheader中ARM11内核描述的内核标记中,为使用此SVC的进程读取内存类型。ControlMemory参数MemoryType取值0x10003对应的是映射GSP堆。低八位是类型:1是未映射内存,3是已经映射的内存;类型4用于备份,从Addr1到Addr0的RW内存,如果Addr1在只读区域,类型4会返回一个错误。Addr1在类型1和3中不使用。
ControlProcessMemory映射指定进程的内存,只是唯一允许映射可执行区域内存的SVC。内存映射SVC的权限格式为bit0=R, bit1=W, bit2=X。类型6设置Addr0已经映射的内存权限到输入权限。
MapProcessMemory映射指定KProcess由当前进程指定的StartAddr从0x00100000开始的RW内存。MapProcessMemory之后会映射指定进程的0x08000000到当前进程StartAddr+0x7f00000的内存。UnmapProcessMemory则取消MapProcessMemory映射的内存。
调试
DebugActiveProcess用于调试时附加进程。这个SVC只有在目标进程的exheader的ARM11描述中设置了"Enable debug"才能调用。如果目标进程的那个标记是零,那么调用这个SVC的进程必须有设置内核标记的"Force debug"标记为一才行。
KernelSetState
类型0为启动固件初始化programID,然后触发启动固件。参数0和参数2没有使用。参数1是programID低位,而programID的高位时0x00040138。
类型3用于给启动的固件初始化0x1000字节的缓存。参数2没用。当参数0为1时候,缓存会复制到FCRAM的0xF0000000开始的地址,参数1没用。当参数0为0,这段内核缓存会映射到进程地址参数1。
GetSystemInfo
类型0值为26(类型1没用)会将直接由内核启动的进程总数写到输出。对于NATIVE_FIRM/SAFE_MODE_FIRM固件的ARM11内核,结果常为5,也即是进程sm,fs,pm,loader,和pxi。