Line 5: |
Line 5: |
| ! Id || Name || In || Out | | ! Id || Name || In || Out |
| |- | | |- |
− | | 0x1 || [[#svcSetHeapSize]] || W1=size || W0=result, X1=outaddr | + | | 0x1 || [[#svcSetHeapSize]] || || |
| |- | | |- |
− | | 0x2 || [[#svcSetMemoryPermission]] || X0=addr, X1=size, W2=prot || W0=result | + | | 0x2 || [[#svcSetMemoryPermission]] || || |
| |- | | |- |
− | | 0x3 || [[#svcSetMemoryAttribute]] || X0=addr, X1=size, W2=state0, W3=state1 || W0=result | + | | 0x3 || [[#svcSetMemoryAttribute]] || || |
| |- | | |- |
− | | 0x4 || [[#svcMapMemory]] || X0=dstaddr, X1=srcaddr, X2=size || W0=result | + | | 0x4 || [[#svcMapMemory]] || || |
| |- | | |- |
− | | 0x5 || [[#svcUnmapMemory]] || X0=dstaddr, X1=srcaddr, X2=size || W0=result | + | | 0x5 || [[#svcUnmapMemory]] || || |
| |- | | |- |
− | | 0x6 || [[#svcQueryMemory]] || X0=MemoryInfo*, X2=addr || W0=result, W1=PageInfo | + | | 0x6 || [[#svcQueryMemory]] || || |
| |- | | |- |
− | | 0x7 || [[#svcExitProcess]] || None || | + | | 0x7 || [[#svcExitProcess]] || || |
| |- | | |- |
− | | 0x8 || [[#svcCreateThread]] || X1=entry, X2=thread_context, X3=stacktop, W4=prio, W5=processor_id | + | | 0x8 || [[#svcCreateThread]] || || |
− | R0=prio, R1=entry, R2=thread_context, R3=stacktop, R4=processor_id
| |
− | || W0=result, W1=handle | |
| |- | | |- |
− | | 0x9 || [[#svcStartThread]] || W0=thread_handle || W0=result | + | | 0x9 || [[#svcStartThread]] || || |
| |- | | |- |
− | | 0xA || [[#svcExitThread]] || None || | + | | 0xA || [[#svcExitThread]] || || |
| |- | | |- |
− | | 0xB || [[#svcSleepThread]] || X0=nano | + | | 0xB || [[#svcSleepThread]] || || |
− | R0=nano_lower32, R1=lower_upper32
| |
− | || | |
| |- | | |- |
− | | 0xC || [[#svcGetThreadPriority]] || W1=thread_handle || W0=result, W1=prio | + | | 0xC || [[#svcGetThreadPriority]] || || |
| |- | | |- |
− | | 0xD || [[#svcSetThreadPriority]] || W0=thread_handle, W1=prio || W0=result | + | | 0xD || [[#svcSetThreadPriority]] || || |
| |- | | |- |
− | | 0xE || [[#svcGetThreadCoreMask]] || W2=thread_handle || W0=result, W1=out0, X2=out1 | + | | 0xE || [[#svcGetThreadCoreMask]] || || |
− | R0=result, R1=out0, R2=out1_lower32, R3=out1_upper32
| |
| |- | | |- |
− | | 0xF || [[#svcSetThreadCoreMask]] || W0=thread_handle, W1=in, X2=in2 | + | | 0xF || [[#svcSetThreadCoreMask]] || || |
− | R0=thread_handle, R1=in, R2=in2_lower32, R3=in2_upper32
| |
− | || W0=result | |
| |- | | |- |
− | | 0x10 || [[#svcGetCurrentProcessorNumber]] || None || W0/X0=cpuid | + | | 0x10 || [[#svcGetCurrentProcessorNumber]] || || |
| |- | | |- |
− | | 0x11 || [[#svcSignalEvent]] || W0=wevent_handle || W0=result | + | | 0x11 || [[#svcSignalEvent]] || || |
| |- | | |- |
− | | 0x12 || [[#svcClearEvent]] || W0=wevent_or_revent_handle || W0=result | + | | 0x12 || [[#svcClearEvent]] || || |
| |- | | |- |
− | | 0x13 || [[#svcMapSharedMemory]] || W0=shmem_handle, X1=addr, X2=size, W3=perm || W0=result | + | | 0x13 || [[#svcMapSharedMemory]] || || |
| |- | | |- |
− | | 0x14 || svcUnmapSharedMemory || W0=shmem_handle, X1=addr, X2=size || W0=result | + | | 0x14 || [[#svcUnmapSharedMemory]] || || |
| |- | | |- |
− | | 0x15 || [[#svcCreateTransferMemory]] || X1=addr, X2=size, W3=perm || W0=result, W1=tmem_handle | + | | 0x15 || [[#svcCreateTransferMemory]] || || |
| |- | | |- |
− | | 0x16 || svcCloseHandle || W0=handle || W0=result | + | | 0x16 || [[#svcCloseHandle]] || || |
| |- | | |- |
− | | 0x17 || [[#svcResetSignal]] || W0=revent_or_process_handle || W0=result | + | | 0x17 || [[#svcResetSignal]] || || |
| |- | | |- |
− | | 0x18 || [[#svcWaitSynchronization]] || X1=handles_ptr, W2=num_handles, X3=timeout | + | | 0x18 || [[#svcWaitSynchronization]] || || |
− | R0=timeout_lower32, R1=handles_ptr, R2=num_handles, R3=timeout_upper32
| |
− | || W0=result, W1=handle_idx | |
| |- | | |- |
− | | 0x19 || [[#svcCancelSynchronization]] || W0=thread_handle || W0=result | + | | 0x19 || [[#svcCancelSynchronization]] || || |
| |- | | |- |
− | | 0x1A || svcArbitrateLock || W0=cur_thread_handle, X1=ptr, W2=req_thread_handle || | + | | 0x1A || [[#svcArbitrateLock]] || || |
| |- | | |- |
− | | 0x1B || svcArbitrateUnlock || X0=ptr || | + | | 0x1B || [[#svcArbitrateUnlock]] || || |
| |- | | |- |
− | | 0x1C || svcWaitProcessWideKeyAtomic || X0=ptr0, X1=ptr, W2=thread_handle, X3=timeout | + | | 0x1C || [[#svcWaitProcessWideKeyAtomic]] || || |
− | R0=ptr0, R1=ptr, R2=thread_handle, R3=timeout_lower32, R4=timeout_upper32
| |
− | || W0=result | |
| |- | | |- |
− | | 0x1D || svcSignalProcessWideKey || X0=ptr, W1=value || W0=result | + | | 0x1D || [[#svcSignalProcessWideKey]] || || |
| |- | | |- |
− | | 0x1E || [[#svcGetSystemTick]] || None || X0={value of cntpct_el0} | + | | 0x1E || [[#svcGetSystemTick]] || || |
− | R0=cntpct_el0_lower32, R1=cntpct_el0_upper32
| |
| |- | | |- |
− | | 0x1F || svcConnectToNamedPort || X1=port_name_str || W0=result, W1=handle | + | | 0x1F || [[#svcConnectToNamedPort]] || || |
| |- | | |- |
− | | 0x20 || svcSendSyncRequestLight || W0=light_session_handle, X1=? || W0=result | + | | 0x20 || [[#svcSendSyncRequestLight]] || || |
| |- | | |- |
− | | 0x21 || svcSendSyncRequest || X0=normal_session_handle || W0=result | + | | 0x21 || [[#svcSendSyncRequest]] || || |
| |- | | |- |
− | | 0x22 || [[#svcSendSyncRequestWithUserBuffer]] || X0=cmdbufptr, X1=size, X2=handle || W0=result | + | | 0x22 || [[#svcSendSyncRequestWithUserBuffer]] || || |
| |- | | |- |
| | 0x23 || svcSendAsyncRequestWithUserBuffer || X1=cmdbufptr, X2=size, X3=handle || W0=result, W1=revent_handle | | | 0x23 || svcSendAsyncRequestWithUserBuffer || X1=cmdbufptr, X2=size, X3=handle || W0=result, W1=revent_handle |
Line 93: |
Line 81: |
| R0=result, R1=out_lower32, R2=out_upper32 | | R0=result, R1=out_lower32, R2=out_upper32 |
| |- | | |- |
− | | 0x26 || [[#svcBreak]] || X0=break_reason,X1,X2=info || W0=result = 0 | + | | 0x26 || [[#svcBreak]] || || |
| |- | | |- |
| | 0x27 || svcOutputDebugString || X0=str, X1=size || W0=result | | | 0x27 || svcOutputDebugString || X0=str, X1=size || W0=result |
Line 99: |
Line 87: |
| | 0x28 || svcReturnFromException || X0=result || | | | 0x28 || svcReturnFromException || X0=result || |
| |- | | |- |
− | | 0x29 || [[#svcGetInfo]] || W1=info_id, X2=handle, X3=info_sub_id | + | | 0x29 || [[#svcGetInfo]] || || |
− | R0=info_sub_id_lower32, R1=info_id, R2=handle, R3=info_sub_id_upper32
| |
− | || W0=result, X1=out | |
− | R0=result, R1=out_lower32, R2=out_upper32
| |
| |- | | |- |
| | 0x2A || svcFlushEntireDataCache || None || None | | | 0x2A || svcFlushEntireDataCache || None || None |
Line 136: |
Line 121: |
| | 0x36 || [8.0.0+] svcSynchronizePreemptionState || None || W0=result | | | 0x36 || [8.0.0+] svcSynchronizePreemptionState || None || W0=result |
| |- style="border-top: double" | | |- style="border-top: double" |
− | | 0x3C || [[#svcDumpInfo]] || || | + | | 0x3C || [4.0.0+] svcKernelDebug ([1.0.0-3.0.2] [[#svcDumpInfo]]) || || |
| |- | | |- |
− | | 0x3D || [4.0.0+] svcDumpInfoNew || || | + | | 0x3D || [4.0.0+] svcChangeKernelTraceState || || |
| |- style="border-top: double" | | |- style="border-top: double" |
| | 0x40 || svcCreateSession || W2=is_light, X3=name_ptr || W0=result, W1=server_handle, W2=client_handle | | | 0x40 || svcCreateSession || W2=is_light, X3=name_ptr || W0=result, W1=server_handle, W2=client_handle |
Line 346: |
Line 331: |
| </div> | | </div> |
| | | |
− | '''Description:''' Set the process heap to a given Size. It can both extend and shrink the heap.
| + | Sets the process heap to a given Size. It can both extend and shrink the heap. |
| | | |
| Size must be a multiple of 0x200000 (2MB). | | Size must be a multiple of 0x200000 (2MB). |
Line 357: |
Line 342: |
| | | |
| === Result codes === | | === Result codes === |
− |
| |
| '''0x0:''' Success. | | '''0x0:''' Success. |
| | | |
Line 371: |
Line 355: |
| | | |
| == svcSetMemoryPermission == | | == svcSetMemoryPermission == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 387: |
Line 370: |
| </div> | | </div> |
| | | |
− | '''Description:''' Change permission of page-aligned memory region.
| + | Changes permission of page-aligned memory region. |
| | | |
| Bit2 of permission (exec) is not allowed. Setting write-only is not allowed either (bit1). | | Bit2 of permission (exec) is not allowed. Setting write-only is not allowed either (bit1). |
Line 394: |
Line 377: |
| | | |
| === Result codes === | | === Result codes === |
− |
| |
| '''0x0:''' Success. The memory region was reprotected. | | '''0x0:''' Success. The memory region was reprotected. |
| | | |
Line 410: |
Line 392: |
| | | |
| == svcSetMemoryAttribute == | | == svcSetMemoryAttribute == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 428: |
Line 409: |
| </div> | | </div> |
| | | |
− | '''Description:''' Change attribute of page-aligned memory region.
| + | Changes attribute of page-aligned memory region. |
| | | |
| This is used to turn on/off caching for a given memory area. Useful when talking to devices such as the GPU. | | This is used to turn on/off caching for a given memory area. Useful when talking to devices such as the GPU. |
Line 445: |
Line 426: |
| | | |
| == svcMapMemory == | | == svcMapMemory == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 461: |
Line 441: |
| </div> | | </div> |
| | | |
− | '''Description:''' Maps a memory range into a different range.
| + | Maps a memory range into a different range. |
| | | |
| Mainly used for adding guard pages around stack. | | Mainly used for adding guard pages around stack. |
Line 478: |
Line 458: |
| | | |
| == svcUnmapMemory == | | == svcUnmapMemory == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 494: |
Line 473: |
| </div> | | </div> |
| | | |
− | '''Description:''' Unmaps a region that was previously mapped with [[#svcMapMemory]].
| + | Unmaps a region that was previously mapped with [[#svcMapMemory]]. |
| | | |
| It's possible to unmap ranges partially, you don't need to unmap the entire range "in one go". | | It's possible to unmap ranges partially, you don't need to unmap the entire range "in one go". |
Line 501: |
Line 480: |
| | | |
| == svcQueryMemory == | | == svcQueryMemory == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 517: |
Line 495: |
| </div> | | </div> |
| | | |
− | '''Description:''' Query information about an address. Will always fetch the lowest page-aligned mapping that contains the provided address.
| + | Queries information about an address. Will always fetch the lowest page-aligned mapping that contains the provided address. |
| | | |
| Outputs a [[#MemoryInfo]] struct. | | Outputs a [[#MemoryInfo]] struct. |
| | | |
| == svcExitProcess == | | == svcExitProcess == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 534: |
Line 511: |
| </div> | | </div> |
| | | |
− | '''Description:''' Exits the current process.
| + | Exits the current process. |
| | | |
| == svcCreateThread == | | == svcCreateThread == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 559: |
Line 535: |
| </div> | | </div> |
| | | |
− | '''Description:''' Create a thread in the current process.
| + | Creates a thread in the current process. |
| | | |
| Processor_id must be 0,1,2,3 or -2, where -2 uses the default cpuid for process. | | Processor_id must be 0,1,2,3 or -2, where -2 uses the default cpuid for process. |
| | | |
| == svcStartThread == | | == svcStartThread == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 576: |
Line 551: |
| </div> | | </div> |
| | | |
− | '''Description:''' Starts the thread for the provided handle.
| + | Starts the thread for the provided handle. |
| | | |
| == svcExitThread == | | == svcExitThread == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 591: |
Line 565: |
| </div> | | </div> |
| | | |
− | '''Description:''' Exits the current thread.
| + | Exits the current thread. |
| | | |
| == svcSleepThread == | | == svcSleepThread == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 605: |
Line 578: |
| </div> | | </div> |
| | | |
− | '''Description:''' Sleep for a specified amount of time, or yield thread.
| + | Sleeps for a specified amount of time, or yields the thread. |
| | | |
| Setting nanoseconds to 0, -1, or -2 indicates a yielding type. | | Setting nanoseconds to 0, -1, or -2 indicates a yielding type. |
Line 619: |
Line 592: |
| |- | | |- |
| | -2 || Yielding to any other thread | | | -2 || Yielding to any other thread |
− | |-
| |
| |} | | |} |
| </div> | | </div> |
| | | |
| == svcGetThreadPriority == | | == svcGetThreadPriority == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 638: |
Line 609: |
| </div> | | </div> |
| | | |
− | '''Description:''' Get priority of provided thread handle.
| + | Gets the priority of provided thread handle. |
| | | |
| == svcSetThreadPriority == | | == svcSetThreadPriority == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 655: |
Line 625: |
| </div> | | </div> |
| | | |
− | '''Description:''' Set priority of provided thread handle.
| + | Sets the priority of provided thread handle. |
| | | |
| Priority is a number 0-0x3F. Lower value means higher priority. | | Priority is a number 0-0x3F. Lower value means higher priority. |
| | | |
| == svcGetThreadCoreMask == | | == svcGetThreadCoreMask == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 676: |
Line 645: |
| </div> | | </div> |
| | | |
− | '''Description:''' Get affinity mask of provided thread handle.
| + | Gets the affinity mask of provided thread handle. |
| | | |
| == svcSetThreadCoreMask == | | == svcSetThreadCoreMask == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 695: |
Line 663: |
| </div> | | </div> |
| | | |
− | '''Description:''' Set affinity mask of provided thread handle.
| + | Sets the affinity mask of provided thread handle. |
| | | |
| == svcGetCurrentProcessorNumber == | | == svcGetCurrentProcessorNumber == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 710: |
Line 677: |
| </div> | | </div> |
| | | |
− | '''Description:''' Get which cpu is executing the current thread.
| + | Gets which cpu is executing the current thread. |
| | | |
− | Cpu-id is an integer in the range 0-3.
| + | CpuId is an integer in the range 0-3. |
| | | |
| == svcSignalEvent == | | == svcSignalEvent == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 727: |
Line 693: |
| </div> | | </div> |
| | | |
− | '''Description:''' Puts the given event in the signaled state.
| + | Puts the given event in the signaled state. |
| | | |
| Will wake up any thread currently waiting on this event. Can potentially trigger a reschedule. | | Will wake up any thread currently waiting on this event. Can potentially trigger a reschedule. |
Line 734: |
Line 700: |
| | | |
| === Result codes === | | === Result codes === |
− |
| |
| '''0x0:''' Success. Event is now in signaled state. | | '''0x0:''' Success. Event is now in signaled state. |
| | | |
Line 740: |
Line 705: |
| | | |
| == svcClearEvent == | | == svcClearEvent == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 752: |
Line 716: |
| </div> | | </div> |
| | | |
− | '''Description:''' Takes the given event out of the signaled state.
| + | Takes the given event out of the signaled state. |
| | | |
| === Result codes === | | === Result codes === |
− |
| |
| '''0x0:''' Success, the event is now in the not-signaled state. | | '''0x0:''' Success, the event is now in the not-signaled state. |
| | | |
Line 763: |
Line 726: |
| | | |
| == svcMapSharedMemory == | | == svcMapSharedMemory == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 785: |
Line 747: |
| Increases reference count for the KSharedMemory object. Thus in order to release the memory associated with the object, all handles to it must be closed and all mappings must be unmapped. | | Increases reference count for the KSharedMemory object. Thus in order to release the memory associated with the object, all handles to it must be closed and all mappings must be unmapped. |
| | | |
− | == svcCreateTransferMemory == | + | == svcUnmapSharedMemory == |
− | | + | <div style="display: inline-block;"> |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Argument || Type || Name |
| + | |- |
| + | | (In) W0 || Handle<SharedMemory> || MemHandle |
| + | |- |
| + | | (In) X1 || void* || Addr |
| + | |- |
| + | | (In) X2 || u64 || Size |
| + | |- |
| + | | (Out) W0 || [[#Result]] || Ret |
| + | |} |
| + | </div> |
| + | |
| + | == svcCreateTransferMemory == |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 809: |
Line 786: |
| | | |
| Closing all handles automatically causes the bit0 in [[#MemoryAttribute]] to clear, and the permission to reset. | | Closing all handles automatically causes the bit0 in [[#MemoryAttribute]] to clear, and the permission to reset. |
| + | |
| + | == svcCloseHandle == |
| + | <div style="display: inline-block;"> |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Argument || Type || Name |
| + | |- |
| + | | (In) W0 || Handle || Handle |
| + | |- |
| + | | (Out) W0 || [[#Result]] || Ret |
| + | |} |
| + | </div> |
| | | |
| == svcResetSignal == | | == svcResetSignal == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 828: |
Line 816: |
| | | |
| === Result codes === | | === Result codes === |
− |
| |
| '''0x0:''' Success. The signal was reset. | | '''0x0:''' Success. The signal was reset. |
| | | |
Line 836: |
Line 823: |
| | | |
| == svcWaitSynchronization == | | == svcWaitSynchronization == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 853: |
Line 839: |
| |} | | |} |
| </div> | | </div> |
| + | |
| Works with num_handles <= 0x40. | | Works with num_handles <= 0x40. |
| | | |
Line 860: |
Line 847: |
| | | |
| === Object types === | | === Object types === |
− |
| |
| '''KDebug:''' signals when there is a new [[#DebugEventInfo|DebugEvent]] (retrievable via [[#svcGetDebugEvent]]). | | '''KDebug:''' signals when there is a new [[#DebugEventInfo|DebugEvent]] (retrievable via [[#svcGetDebugEvent]]). |
| | | |
Line 876: |
Line 862: |
| | | |
| === Result codes === | | === Result codes === |
− |
| |
| '''0x0:''' Success. One of the objects was signaled before the timeout expired, or one of the objects is a Session with a closed remote. Handle index is updated to indicate which object signaled. | | '''0x0:''' Success. One of the objects was signaled before the timeout expired, or one of the objects is a Session with a closed remote. Handle index is updated to indicate which object signaled. |
| | | |
Line 892: |
Line 877: |
| | | |
| == svcCancelSynchronization == | | == svcCancelSynchronization == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 910: |
Line 894: |
| | | |
| === Result codes === | | === Result codes === |
− |
| |
| '''0x0:''' Success. The thread was either interrupted or has had its flag set. | | '''0x0:''' Success. The thread was either interrupted or has had its flag set. |
| | | |
| '''0xe401:''' Invalid handle. The handle given was either invalid or not a thread handle. | | '''0xe401:''' Invalid handle. The handle given was either invalid or not a thread handle. |
| | | |
− | == svcGetSystemTick == | + | == svcArbitrateLock == |
− | | + | <div style="display: inline-block;"> |
− | <div style="display: inline-block;"> | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
− | ! Argument64 || Argument32 || Type || Name | + | ! Argument || Type || Name |
| + | |- |
| + | | (In) W0 || Handle<Thread> || Handle |
| + | |- |
| + | | (In) X1 || void* || Addr |
| + | |- |
| + | | (In) W2 || u32 || Tag |
| |- | | |- |
− | | (Out) X0 || R0, R1 || u64 || Ticks | + | | (Out) W0 || [[#Result]] || Ret |
| |} | | |} |
− | </div> | + | </div> |
− | | |
− | Returns the value of cntpct_el0.
| |
− | | |
− | The frequency is 19200000 Hz (constant from official sw).
| |
− | | |
− | Official sw reads cntpct_el0 directly from usermode without using this SVC. [[ExeFS|sdk-nso]] has this SVC, but it's not known to be called anywhere.
| |
− | | |
− | == svcSendSyncRequestWithUserBuffer ==
| |
| | | |
| + | == svcArbitrateUnlock == |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 939: |
Line 920: |
| ! Argument || Type || Name | | ! Argument || Type || Name |
| |- | | |- |
− | | (In) X0 || void* || CmdPtr | + | | (In) X0 || void* || Addr |
− | |-
| |
− | | (In) X1 || u64 || Size
| |
− | |-
| |
− | | (In) W2 || Handle<Session> || Handle
| |
| |- | | |- |
| | (Out) W0 || [[#Result]] || Ret | | | (Out) W0 || [[#Result]] || Ret |
Line 949: |
Line 926: |
| </div> | | </div> |
| | | |
− | Size and CmdPtr must be 0x1000-aligned.
| + | == svcWaitProcessWideKeyAtomic == |
− | | + | <div style="display: inline-block;"> |
− | === Result codes ===
| + | {| class="wikitable" border="1" |
− | | + | |- |
− | '''0x0:''' Success.
| + | ! Argument64 || Argument32 || Type || Name |
− | | + | |- |
− | '''0xcc01:''' CmdPtr is not 0x1000-aligned.
| + | | (In) X0 || R0 || void* || KeyAddr |
− | | |
− | '''0xca01:''' Size is not 0x1000-aligned.
| |
− | | |
− | '''0xce01:''' KSessionRequest allocation failed (unlikely) or pointer buffer size exceeded.
| |
− | | |
− | '''0xe401:''' Handles does not exist, or handle is not an instance of KClientSession.
| |
− | | |
− | == svcBreak == | |
− | | |
− | <div style="display: inline-block;"> | |
− | {| class="wikitable" border="1" | |
| |- | | |- |
− | ! Argument || Type || Name
| + | | (In) X1 || R1 || void* || TagAddr |
| |- | | |- |
− | | (In) X0 || u64 || Break Reason | + | | (In) W2 || R2 || u32 || Tag |
| |- | | |- |
− | | (In) X1 || u64 || | + | | (In) X3 || R3, R4 || u64 || Timeout |
| |- | | |- |
− | | (In) X2 || u64 || Info | + | | (Out) W0 || R0 || [[#Result]] || Ret |
− | |- | |
− | | (Out) W0 || Result || 0 (Success)
| |
| |} | | |} |
| </div> | | </div> |
| | | |
− | If the process is attached, report the Break event. Then, if svcContinueDebugEvent didn't apply IgnoreException on the thread: if TPIDR_EL0 is 0, adjust ELR_EL1 to retry to svc instruction (and set TPIDR_EL0 to 1).
| + | == svcSignalProcessWideKey == |
− | | |
− | Otherwise, if bit31 in reason isn't set, perform crash reporting (see Exception Handling section below), if it doesn't terminate the process adjust ELR_EL1 as well.
| |
− | | |
− | Otherwise just return 0.
| |
− | | |
− | == svcGetInfo == | |
− | | |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 993: |
Line 950: |
| ! Argument || Type || Name | | ! Argument || Type || Name |
| |- | | |- |
− | | (In) W1 || u32 || InfoId | + | | (In) X0 || void* || Addr |
| |- | | |- |
− | | (In) W2 || Handle || Handle | + | | (In) W1 || u32 || Value |
| |- | | |- |
− | | (In) X3 || u64 || InfoSubId | + | | (Out) W0 || [[#Result]] || Ret |
| + | |} |
| + | </div> |
| + | |
| + | == svcGetSystemTick == |
| + | <div style="display: inline-block;"> |
| + | {| class="wikitable" border="1" |
| |- | | |- |
− | | (Out) W0 || [[#Result]] || Ret | + | ! Argument64 || Argument32 || Type || Name |
| |- | | |- |
− | | (Out) X1 || u64 || Out | + | | (Out) X0 || R0, R1 || u64 || Ticks |
| |} | | |} |
| </div> | | </div> |
− | <div style="display: inline-block; vertical-align:top;"> | + | |
| + | Returns the value of cntpct_el0. |
| + | |
| + | The frequency is 19200000 Hz (constant from official sw). |
| + | |
| + | Official sw reads cntpct_el0 directly from usermode without using this SVC. [[ExeFS|sdk-nso]] has this SVC, but it's not known to be called anywhere. |
| + | |
| + | == svcConnectToNamedPort == |
| + | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
| ! Argument || Type || Name | | ! Argument || Type || Name |
| |- | | |- |
− | | (In) R0 || u32 || InfoSubIdLower32 | + | | (In) X1 || char* || Name |
| |- | | |- |
− | | (In) R1 || u32 || InfoId | + | | (Out) W0 || [[#Result]] || Ret |
| |- | | |- |
− | | (In) R2 || Handle || Handle | + | | (Out) W1 || Handle<Session> || Handle |
| + | |} |
| + | </div> |
| + | |
| + | == svcSendSyncRequestLight == |
| + | <div style="display: inline-block;"> |
| + | {| class="wikitable" border="1" |
| |- | | |- |
− | | (In) R3 || u32 || InfoSubIdUpper32 | + | ! Argument || Type || Name |
| |- | | |- |
− | | (Out) R0 || [[#Result]] || Ret | + | | (In) W0 || Handle<Session> || Handle |
| |- | | |- |
− | | (Out) R1 || u32 || OutLower32 | + | | (Out) W0 || [[#Result]] || Ret |
− | |-
| |
− | | (Out) R2 || u32 || OutUpper32
| |
| |} | | |} |
| </div> | | </div> |
| | | |
− | | + | == svcSendSyncRequest == |
− | {| class=wikitable | + | <div style="display: inline-block;"> |
− | ! Handle type || Id0 || Id1 || Description
| + | {| class="wikitable" border="1" |
| |- | | |- |
− | | Process || 0 || 0 || AllowedCpuIdBitmask | + | ! Argument || Type || Name |
| |- | | |- |
− | | Process || 1 || 0 || AllowedThreadPrioBitmask | + | | (In) W0 || Handle<Session> || Handle |
| |- | | |- |
− | | Process || 2 || 0 || AliasRegionBaseAddr | + | | (Out) W0 || [[#Result]] || Ret |
| + | |} |
| + | </div> |
| + | |
| + | == svcSendSyncRequestWithUserBuffer == |
| + | <div style="display: inline-block;"> |
| + | {| class="wikitable" border="1" |
| |- | | |- |
− | | Process || 3 || 0 || AliasRegionSize | + | ! Argument || Type || Name |
| |- | | |- |
− | | Process || 4 || 0 || HeapRegionBaseAddr | + | | (In) X0 || void* || CmdPtr |
| |- | | |- |
− | | Process || 5 || 0 || HeapRegionSize | + | | (In) X1 || u64 || Size |
| |- | | |- |
− | | Process || 6 || 0 || TotalMemoryAvailable. Total memory available(free+used). | + | | (In) W2 || Handle<Session> || Handle |
| |- | | |- |
− | | Process || 7 || 0 || TotalMemoryUsage. Total used size of codebin memory + main-thread stack + allocated heap. | + | | (Out) W0 || [[#Result]] || Ret |
− | |-
| + | |} |
− | | Zero || 8 || 0 || IsCurrentProcessBeingDebugged
| + | </div> |
− | |-
| + | |
− | | Zero || 9 || 0 || Returns ResourceLimit handle for current process. Used by [[Process_Manager_services|PM]].
| + | Size and CmdPtr must be 0x1000-aligned. |
| + | |
| + | === Result codes === |
| + | '''0x0:''' Success. |
| + | |
| + | '''0xcc01:''' CmdPtr is not 0x1000-aligned. |
| + | |
| + | '''0xca01:''' Size is not 0x1000-aligned. |
| + | |
| + | '''0xce01:''' KSessionRequest allocation failed (unlikely) or pointer buffer size exceeded. |
| + | |
| + | '''0xe401:''' Handles does not exist, or handle is not an instance of KClientSession. |
| + | |
| + | == svcBreak == |
| + | <div style="display: inline-block;"> |
| + | {| class="wikitable" border="1" |
| |- | | |- |
− | | Zero || 10 || -1, {current coreid} || IdleTickCount | + | ! Argument || Type || Name |
| |- | | |- |
− | | Zero || 11 || 0-3 || RandomEntropy from current process. TRNG. Used to seed usermode PRNGs. | + | | (In) X0 || u64 || Break Reason |
| |- | | |- |
− | | Process || 12 || 0 || [2.0.0+] AddressSpaceBaseAddr | + | | (In) X1 || u64 || |
| |- | | |- |
− | | Process || 13 || 0 || [2.0.0+] AddressSpaceSize | + | | (In) X2 || u64 || Info |
| |- | | |- |
− | | Process || 14 || 0 || [2.0.0+] StackRegionBaseAddr | + | | (Out) W0 || Result || 0 (Success) |
− | |-
| + | |} |
− | | Process || 15 || 0 || [2.0.0+] StackRegionSize | + | </div> |
− | |- | + | |
− | | Process || 16 || 0 || [3.0.0+] PersonalMmHeapSize
| + | If the process is attached, report the Break event. Then, if svcContinueDebugEvent didn't apply IgnoreException on the thread: if TPIDR_EL0 is 0, adjust ELR_EL1 to retry to svc instruction (and set TPIDR_EL0 to 1). |
| + | |
| + | Otherwise, if bit31 in reason isn't set, perform crash reporting (see Exception Handling section below), if it doesn't terminate the process adjust ELR_EL1 as well. |
| + | |
| + | Otherwise just return 0. |
| + | |
| + | == svcGetInfo == |
| + | <div style="display: inline-block;"> |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Argument64 || Argument32 || Type || Name |
| |- | | |- |
− | | Process || 17 || 0 || [3.0.0+] PersonalMmHeapUsage | + | | (In) W1 || R1 || u32 || InfoId |
| + | |- |
| + | | (In) W2 || R2 || Handle || Handle |
| |- | | |- |
− | | Process || 18 || 0 || [3.0.0+] TitleId | + | | (In) X3 || R0, R3 || u64 || InfoSubId |
| |- | | |- |
− | | Zero || 19 || 0 || [4.0.0-4.1.0] PrivilegedProcessId_LowerBound | + | | (Out) W0 || R0 || [[#Result]] || Ret |
| |- | | |- |
− | | Zero || 19 || 1 || [4.0.0-4.1.0] PrivilegedProcessId_UpperBound | + | | (Out) X1 || R1, R2 || u64 || Out |
| + | |} |
| + | </div> |
| + | |
| + | {| class=wikitable |
| + | ! Handle type || Id0 || Id1 || Description |
| |- | | |- |
− | | Process || 20 || 0 || [5.0.0+] UserExceptionContextAddr | + | | Process || 0 || 0 || AllowedCpuIdBitmask |
| |- | | |- |
− | | Process || 21 || 0 || [6.0.0+] TotalMemoryAvailableWithoutMmHeap | + | | Process || 1 || 0 || AllowedThreadPrioBitmask |
| |- | | |- |
− | | Process || 22 || 0 || [6.0.0+] TotalMemoryUsedWithoutMmHeap | + | | Process || 2 || 0 || AliasRegionBaseAddr |
| |- | | |- |
− | | Process || 23 || 0 || [9.0.0+] IsApplication | + | | Process || 3 || 0 || AliasRegionSize |
| |- | | |- |
− | | Thread || 0xF0000002 || 0-3, -1 || Thread Ticks. When 0-3 are passed, gets specific core CPU ticks spent on thread. When -1 is passed, gets total CPU ticks spent on thread. | + | | Process || 4 || 0 || HeapRegionBaseAddr |
− | |} | + | |- |
− | | + | | Process || 5 || 0 || HeapRegionSize |
− | == svcMapPhysicalMemory ==
| |
− | This is like svcSetHeapSize except you can allocate heap at any address you'd like.
| |
− | | |
− | Uses current process pool partition.
| |
− | | |
− | == svcDumpInfo ==
| |
− | | |
− | <div style="display: inline-block;">
| |
− | {| class="wikitable" border="1"
| |
| |- | | |- |
− | ! Argument || Type || Name
| + | | Process || 6 || 0 || TotalMemoryAvailable. Total memory available(free+used). |
| |- | | |- |
− | | (In) None || || | + | | Process || 7 || 0 || TotalMemoryUsage. Total used size of codebin memory + main-thread stack + allocated heap. |
| |- | | |- |
− | | (Out) None || || | + | | Zero || 8 || 0 || IsCurrentProcessBeingDebugged |
− | |} | |
− | </div>
| |
− | | |
− | Does nothing, just returns with registers set to all-zero.
| |
− | | |
− | == svcAcceptSession ==
| |
− | | |
− | <div style="display: inline-block;">
| |
− | {| class="wikitable" border="1"
| |
| |- | | |- |
− | ! Argument || Type || Name
| + | | Zero || 9 || 0 || Returns ResourceLimit handle for current process. Used by [[Process_Manager_services|PM]]. |
| |- | | |- |
− | | (In) W1 || Handle<Port> || Port | + | | Zero || 10 || -1, {current coreid} || IdleTickCount |
| |- | | |- |
− | | (Out) W0 || [[#Result]] || Result | + | | Zero || 11 || 0-3 || RandomEntropy from current process. TRNG. Used to seed usermode PRNGs. |
| |- | | |- |
− | | (Out) W1 || Handle<ServerSession> || Session | + | | Process || 12 || 0 || [2.0.0+] AddressSpaceBaseAddr |
− | |} | + | |- |
− | </div>
| + | | Process || 13 || 0 || [2.0.0+] AddressSpaceSize |
− | | + | |- |
− | === Result codes ===
| + | | Process || 14 || 0 || [2.0.0+] StackRegionBaseAddr |
− | | |
− | '''0xf201:''' No session waiting to be accepted
| |
− | | |
− | == svcReplyAndReceive ==
| |
− | | |
− | <div style="display: inline-block;">
| |
− | {| class="wikitable" border="1"
| |
| |- | | |- |
− | ! Argument64 || Argument32 || Type || Name
| + | | Process || 15 || 0 || [2.0.0+] StackRegionSize |
| |- | | |- |
− | | (In) W1 || R1 || *Handle<Port or ServerSession> || Handles | + | | Process || 16 || 0 || [3.0.0+] PersonalMmHeapSize |
| |- | | |- |
− | | (In) W2 || R2 || u32 || NumHandles | + | | Process || 17 || 0 || [3.0.0+] PersonalMmHeapUsage |
| |- | | |- |
− | | (In) W3 || R3 || Handle<ServerSession> || ReplyTarget | + | | Process || 18 || 0 || [3.0.0+] TitleId |
| |- | | |- |
− | | (In) X4 || R0, R4 || u64 (nanoseconds) || Timeout | + | | Zero || 19 || 0 || [4.0.0-4.1.0] PrivilegedProcessId_LowerBound |
| |- | | |- |
− | | (Out) W0 || R0 || [[#Result]] || Result | + | | Zero || 19 || 1 || [4.0.0-4.1.0] PrivilegedProcessId_UpperBound |
| |- | | |- |
− | | (Out) W1 || R1 || u32 || HandleIndex | + | | Process || 20 || 0 || [5.0.0+] UserExceptionContextAddr |
− | |} | + | |- |
− | </div>
| + | | Process || 21 || 0 || [6.0.0+] TotalMemoryAvailableWithoutMmHeap |
− | | + | |- |
− | If ReplyTarget is not zero, a reply from the TLS will be sent to that session.
| + | | Process || 22 || 0 || [6.0.0+] TotalMemoryUsedWithoutMmHeap |
− | Then it will wait until either of the passed sessions has an incoming message, is closed, a passed port has an incoming connection, or the timeout expires.
| + | |- |
− | If there is an incoming message, it is copied to the TLS.
| + | | Process || 23 || 0 || [9.0.0+] IsApplication |
| + | |- |
| + | | Thread || 0xF0000002 || 0-3, -1 || Thread Ticks. When 0-3 are passed, gets specific core CPU ticks spent on thread. When -1 is passed, gets total CPU ticks spent on thread. |
| + | |} |
| | | |
− | If ReplyTarget is zero, the TLS should contain a blank message. If this message has a C descriptor, the buffer it points to will be used as the pointer buffer. See [[IPC_Marshalling#IPC_buffers]]. Note that a pointer buffer cannot be specified if ReplyTarget is not zero.
| + | == svcMapPhysicalMemory == |
| + | This is like svcSetHeapSize except you can allocate heap at any address you'd like. |
| | | |
− | After being validated, passed handles will be enumerated in order; even if a session has been closed, if one that appears earlier in the list has an incoming message, it will take priority and a result code of 0x0 will be returned.
| + | Uses current process pool partition. |
| | | |
− | === Result codes === | + | == svcDumpInfo == |
| + | <div style="display: inline-block;"> |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Argument || Type || Name |
| + | |- |
| + | | (In) None || || |
| + | |- |
| + | | (Out) None || || |
| + | |} |
| + | </div> |
| | | |
− | '''0x0:''' Success. Either a session has an incoming message or a port has an incoming connection. HandleIndex is set appropriately.
| + | Does nothing, just returns with registers set to all-zero. |
| | | |
− | '''0xea01:''' Timeout. No handles were signalled before the timeout expired. HandleIndex is not updated.
| + | == svcAcceptSession == |
− | | + | <div style="display: inline-block;"> |
− | '''0xf601:''' Port remote dead. One of the sessions has been closed. HandleIndex is set appropriately.
| |
− | | |
− | == svcMapPhysicalMemoryUnsafe == | |
− | Same as [[#svcMapPhysicalMemory]] except it always uses pool partition 0.
| |
− | | |
− | == svcCreateCodeMemory ==
| |
− | Takes an address range with backing memory to create the code memory object.
| |
− | | |
− | The memory is initially memset to 0xFF after being locked.
| |
− | | |
− | == svcControlCodeMemory ==
| |
− | Maps the backing memory for a Code memory object into the current process.
| |
− | | |
− | For [[#CodeMemoryOperation|CodeMemoryOperation_MapOwner]], memory permission must be RW-.
| |
− | | |
− | For [[#CodeMemoryOperation|CodeMemoryOperation_MapSlave]], memory permission must be R-- or R-X.
| |
− | | |
− | Operations [[#CodeMemoryOperation|CodeMemoryOperation_UnmapOwner/CodeMemoryOperation_UnmapSlave]] unmap memory that was previously mapped this way.
| |
− | | |
− | This allows one "secure JIT" process to map the code memory as RW-, and the other "slave" process to map it R-X.
| |
− | | |
− | [5.0.0+] Error 0xE401 is now returned when the process owner of the Code memory object is the same as the current process.
| |
− | | |
− | == svcReadWriteRegister ==
| |
− | | |
− | <div style="display: inline-block;"> | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
− | ! Argument64 || Argument32 || Type || Name | + | ! Argument || Type || Name |
| |- | | |- |
− | | (In) X1 || R2, R3 || u64 || RegAddr | + | | (In) W1 || Handle<Port> || Port |
| |- | | |- |
− | | (In) W2 || R0 || u64 || RwMask | + | | (Out) W0 || [[#Result]] || Result |
| |- | | |- |
− | | (In) W3 || R1 || u64 || InValue | + | | (Out) W1 || Handle<ServerSession> || Session |
| + | |} |
| + | </div> |
| + | |
| + | === Result codes === |
| + | '''0xf201:''' No session waiting to be accepted |
| + | |
| + | == svcReplyAndReceive == |
| + | <div style="display: inline-block;"> |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Argument64 || Argument32 || Type || Name |
| + | |- |
| + | | (In) W1 || R1 || *Handle<Port or ServerSession> || Handles |
| + | |- |
| + | | (In) W2 || R2 || u32 || NumHandles |
| + | |- |
| + | | (In) W3 || R3 || Handle<ServerSession> || ReplyTarget |
| + | |- |
| + | | (In) X4 || R0, R4 || u64 (nanoseconds) || Timeout |
| |- | | |- |
− | | (Out) W0 || R0 || [[#Result]] || Ret | + | | (Out) W0 || R0 || [[#Result]] || Result |
| |- | | |- |
− | | (Out) W1 || R1 || u64 || OutValue | + | | (Out) W1 || R1 || u32 || HandleIndex |
| |} | | |} |
| </div> | | </div> |
| | | |
− | Read/write IO registers with a hardcoded whitelist. Input address is physical-address and must be aligned to 4.
| + | If ReplyTarget is not zero, a reply from the TLS will be sent to that session. |
| + | Then it will wait until either of the passed sessions has an incoming message, is closed, a passed port has an incoming connection, or the timeout expires. |
| + | If there is an incoming message, it is copied to the TLS. |
| | | |
− | rw_mask is 0 for reading and 0xffffffff for writing. You can also write individual bits by using a mask value.
| + | If ReplyTarget is zero, the TLS should contain a blank message. If this message has a C descriptor, the buffer it points to will be used as the pointer buffer. See [[IPC_Marshalling#IPC_buffers]]. Note that a pointer buffer cannot be specified if ReplyTarget is not zero. |
| | | |
− | You can only write to registers inside physical pages 0x70019000 (MC), 0x7001C000 (MC0), 0x7001D000 (MC1), and they all share the same whitelist.
| + | After being validated, passed handles will be enumerated in order; even if a session has been closed, if one that appears earlier in the list has an incoming message, it will take priority and a result code of 0x0 will be returned. |
| | | |
− | The whitelist is same for writing as for reading.
| + | === Result codes === |
| + | '''0x0:''' Success. Either a session has an incoming message or a port has an incoming connection. HandleIndex is set appropriately. |
| | | |
− | The whitelist is:
| + | '''0xea01:''' Timeout. No handles were signalled before the timeout expired. HandleIndex is not updated. |
| | | |
− | 0x054, 0x090, 0x094, 0x098, 0x09c, 0x0a0, 0x0a4, 0x0a8, 0x0ac, 0x0b0, 0x0b4, 0x0b8, 0x0bc, 0x0c0, 0x0c4, 0x0c8, 0x0d0, 0x0d4, 0x0d8, 0x0dc, 0x0e0, 0x100, 0x108, 0x10c, 0x118, 0x11c, 0x124, 0x128, 0x12c, 0x130, 0x134, 0x138, 0x13c, 0x158, 0x15c, 0x164, 0x168, 0x16c, 0x170, 0x174, 0x178, 0x17c, 0x200, 0x204, 0x2e4, 0x2e8, 0x2ec, 0x2f4, 0x2f8, 0x310, 0x314, 0x320, 0x328, 0x344, 0x348, 0x370, 0x374, 0x37c, 0x380, 0x390, 0x394, 0x398, 0x3ac, 0x3b8, 0x3bc, 0x3c0, 0x3c4, 0x3d8, 0x3e8, 0x41c, 0x420, 0x424, 0x428, 0x42c, 0x430, 0x44c, 0x47c, 0x480, 0x484, 0x50c, 0x554, 0x558, 0x55c, 0x670, 0x674, 0x690, 0x694, 0x698, 0x69c, 0x6a0, 0x6a4, 0x6c0, 0x6c4, 0x6f0, 0x6f4, 0x960, 0x970, 0x974, 0xa20, 0xa24, 0xb88, 0xb8c, 0xbc4, 0xbc8, 0xbcc, 0xbd0, 0xbd4, 0xbd8, 0xbdc, 0xbe0, 0xbe4, 0xbe8, 0xbec, 0xc00, 0xc5c, 0xcac
| + | '''0xf601:''' Port remote dead. One of the sessions has been closed. HandleIndex is set appropriately. |
| | | |
| + | == svcMapPhysicalMemoryUnsafe == |
| + | Same as [[#svcMapPhysicalMemory]] except it always uses pool partition 0. |
| | | |
− | [2.0.0+] Whitelist was extended with 0x4c4, 0x4c8, 0x4cc, 0x584, 0x588, 0x58c.
| + | == svcCreateCodeMemory == |
| + | Takes an address range with backing memory to create the code memory object. |
| | | |
− | [2.0.0+] The IO registers in range 0x7000E400 (PMC) size 0xC00 skip the whitelist, and do a TrustZone call using [[SMC]] Id1 0xC3000008(ReadWriteRegister).
| + | The memory is initially memset to 0xFF after being locked. |
| | | |
− | [4.0.0+] Access to the Memory Controller (0x70019000) also uses smcReadWriteRegister.
| + | == svcControlCodeMemory == |
| + | Maps the backing memory for a Code memory object into the current process. |
| | | |
− | Here is the whitelist imposed by that SMC, relative to the start of the PMC registers:
| + | For [[#CodeMemoryOperation|CodeMemoryOperation_MapOwner]], memory permission must be RW-. |
| | | |
− | 0x000, 0x00c, 0x010, 0x014, 0x01c, 0x020, 0x02c, 0x030, 0x034, 0x038, 0x03c, 0x040, 0x044, 0x048, 0x0dc, 0x0e0, 0x0e4, 0x160, 0x164, 0x168, 0x170, 0x1a8, 0x1b8, 0x1bc, 0x1c0, 0x1c4, 0x1c8, 0x2b4, 0x2d4, 0x440, 0x4d8
| + | For [[#CodeMemoryOperation|CodeMemoryOperation_MapSlave]], memory permission must be R-- or R-X. |
| | | |
− | Here is the whitelist imposed by smcReadWriteRegister (checked in addition to the whitelist in svcReadWriteRegister), relative to the start of the MC registers:
| + | Operations [[#CodeMemoryOperation|CodeMemoryOperation_UnmapOwner/CodeMemoryOperation_UnmapSlave]] unmap memory that was previously mapped this way. |
| | | |
− | 0x000, 0x004, 0x008, 0x00C, 0x010, 0x01C, 0x020, 0x030, 0x034, 0x050, 0x054, 0x090, 0x094, 0x098, 0x09C, 0x0A0, 0x0A4, 0x0A8, 0x0AC, 0x0B0, 0x0B4, 0x0B8, 0x0BC, 0x0C0, 0x0C4, 0x0C8, 0x0D0, 0x0D4, 0x0D8, 0x0DC, 0x0E0, 0x100, 0x108, 0x10C, 0x118, 0x11C, 0x124, 0x128, 0x12C, 0x130, 0x134, 0x138, 0x13C, 0x158, 0x15C, 0x164, 0x168, 0x16C, 0x170, 0x174, 0x178, 0x17C, 0x200, 0x204, 0x238, 0x240, 0x244, 0x250, 0x254, 0x258, 0x264, 0x268, 0x26C, 0x270, 0x274, 0x280, 0x284, 0x288, 0x28C, 0x294, 0x2E4, 0x2E8, 0x2EC, 0x2F4, 0x2F8, 0x310, 0x314, 0x320, 0x328, 0x344, 0x348, 0x370, 0x374, 0x37C, 0x380, 0x390, 0x394, 0x398, 0x3AC, 0x3B8, 0x3BC, 0x3C0, 0x3C4, 0x3D8, 0x3E8, 0x41C, 0x420, 0x424, 0x428, 0x42C, 0x430, 0x44C, 0x47C, 0x480, 0x484, 0x4C4, 0x4C8, 0x4CC, 0x50C, 0x554, 0x558, 0x55C, 0x584, 0x588, 0x58C, 0x670, 0x674, 0x690, 0x694, 0x698, 0x69C, 0x6A0, 0x6A4, 0x6C0, 0x6C4, 0x6F0, 0x6F4, 0x960, 0x970, 0x974, 0x9B8, 0xA20, 0xA24, 0xA88, 0xA94, 0xA98, 0xA9C, 0xAA0, 0xAA4, 0xAA8, 0xAAC, 0xAB0, 0xAB4, 0xAB8, 0xABC, 0xAC0, 0xAC4, 0xAC8, 0xACC, 0xAD0, 0xAD4, 0xAD8, 0xADC, 0xAE0, 0xB88, 0xB8C, 0xBC4, 0xBC8, 0xBCC, 0xBD0, 0xBD4, 0xBD8, 0xBDC, 0xBE0, 0xBE4, 0xBE8, 0xBEC, 0xC00, 0xC5C, 0xCAC
| + | This allows one "secure JIT" process to map the code memory as RW-, and the other "slave" process to map it R-X. |
| | | |
− | == svcCreateSharedMemory ==
| + | [5.0.0+] Error 0xE401 is now returned when the process owner of the Code memory object is the same as the current process. |
| | | |
| + | == svcReadWriteRegister == |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
− | ! Argument || Type || Name | + | ! Argument64 || Argument32 || Type || Name |
| |- | | |- |
− | | (In) W1 || u64 || Size | + | | (In) X1 || R2, R3 || u64 || RegAddr |
| |- | | |- |
− | | (In) W2 || [[#Permission]] || LocalPerm | + | | (In) W2 || R0 || u64 || RwMask |
| |- | | |- |
− | | (In) W3 || [[#Permission]] || RemotePerm | + | | (In) W3 || R1 || u64 || InValue |
| |- | | |- |
− | | (Out) W0 || [[#Result]] || Ret | + | | (Out) W0 || R0 || [[#Result]] || Ret |
| |- | | |- |
− | | (Out) W1 || Handle<SharedMemory> || MemHandle | + | | (Out) W1 || R1 || u64 || OutValue |
| |} | | |} |
| </div> | | </div> |
| | | |
− | Other perm can be used to enforce permission 1, 3, or 0x10000000 if don't care.
| + | Read/write IO registers with a hardcoded whitelist. Input address is physical-address and must be aligned to 4. |
| | | |
− | Allocates memory from the current process' pool partition.
| + | rw_mask is 0 for reading and 0xffffffff for writing. You can also write individual bits by using a mask value. |
| | | |
− | == svcMapTransferMemory ==
| + | You can only write to registers inside physical pages 0x70019000 (MC), 0x7001C000 (MC0), 0x7001D000 (MC1), and they all share the same whitelist. |
| | | |
− | <div style="display: inline-block;">
| + | The whitelist is same for writing as for reading. |
− | {| class="wikitable" border="1"
| |
− | |-
| |
− | ! Argument || Type || Name
| |
− | |-
| |
− | | (In) X0 || Handle<TransferMemory> || MemHandle
| |
− | |-
| |
− | | (In) X1 || void* || Addr
| |
− | |-
| |
− | | (In) X2 || u64 || Size
| |
− | |-
| |
− | | (In) W3 || [[#Permission]] || Permissions
| |
− | |-
| |
− | | (Out) W0 || [[#Result]] || Ret
| |
− | |}
| |
− | </div>
| |
| | | |
− | The newly mapped pages will have [[#MemoryState]] type 0xE. | + | The whitelist is: |
| | | |
− | You must pass same size and permissions as given in svcCreateMemoryMirror, otherwise error.
| + | 0x054, 0x090, 0x094, 0x098, 0x09c, 0x0a0, 0x0a4, 0x0a8, 0x0ac, 0x0b0, 0x0b4, 0x0b8, 0x0bc, 0x0c0, 0x0c4, 0x0c8, 0x0d0, 0x0d4, 0x0d8, 0x0dc, 0x0e0, 0x100, 0x108, 0x10c, 0x118, 0x11c, 0x124, 0x128, 0x12c, 0x130, 0x134, 0x138, 0x13c, 0x158, 0x15c, 0x164, 0x168, 0x16c, 0x170, 0x174, 0x178, 0x17c, 0x200, 0x204, 0x2e4, 0x2e8, 0x2ec, 0x2f4, 0x2f8, 0x310, 0x314, 0x320, 0x328, 0x344, 0x348, 0x370, 0x374, 0x37c, 0x380, 0x390, 0x394, 0x398, 0x3ac, 0x3b8, 0x3bc, 0x3c0, 0x3c4, 0x3d8, 0x3e8, 0x41c, 0x420, 0x424, 0x428, 0x42c, 0x430, 0x44c, 0x47c, 0x480, 0x484, 0x50c, 0x554, 0x558, 0x55c, 0x670, 0x674, 0x690, 0x694, 0x698, 0x69c, 0x6a0, 0x6a4, 0x6c0, 0x6c4, 0x6f0, 0x6f4, 0x960, 0x970, 0x974, 0xa20, 0xa24, 0xb88, 0xb8c, 0xbc4, 0xbc8, 0xbcc, 0xbd0, 0xbd4, 0xbd8, 0xbdc, 0xbe0, 0xbe4, 0xbe8, 0xbec, 0xc00, 0xc5c, 0xcac |
| + | |
| + | [2.0.0+] Whitelist was extended with 0x4c4, 0x4c8, 0x4cc, 0x584, 0x588, 0x58c. |
| + | |
| + | [2.0.0+] The IO registers in range 0x7000E400 (PMC) size 0xC00 skip the whitelist, and do a TrustZone call using [[SMC]] Id1 0xC3000008(ReadWriteRegister). |
| + | |
| + | [4.0.0+] Access to the Memory Controller (0x70019000) also uses smcReadWriteRegister. |
| + | |
| + | Here is the whitelist imposed by that SMC, relative to the start of the PMC registers: |
| + | |
| + | 0x000, 0x00c, 0x010, 0x014, 0x01c, 0x020, 0x02c, 0x030, 0x034, 0x038, 0x03c, 0x040, 0x044, 0x048, 0x0dc, 0x0e0, 0x0e4, 0x160, 0x164, 0x168, 0x170, 0x1a8, 0x1b8, 0x1bc, 0x1c0, 0x1c4, 0x1c8, 0x2b4, 0x2d4, 0x440, 0x4d8 |
| + | |
| + | Here is the whitelist imposed by smcReadWriteRegister (checked in addition to the whitelist in svcReadWriteRegister), relative to the start of the MC registers: |
| | | |
− | == svcUnmapTransferMemory ==
| + | 0x000, 0x004, 0x008, 0x00C, 0x010, 0x01C, 0x020, 0x030, 0x034, 0x050, 0x054, 0x090, 0x094, 0x098, 0x09C, 0x0A0, 0x0A4, 0x0A8, 0x0AC, 0x0B0, 0x0B4, 0x0B8, 0x0BC, 0x0C0, 0x0C4, 0x0C8, 0x0D0, 0x0D4, 0x0D8, 0x0DC, 0x0E0, 0x100, 0x108, 0x10C, 0x118, 0x11C, 0x124, 0x128, 0x12C, 0x130, 0x134, 0x138, 0x13C, 0x158, 0x15C, 0x164, 0x168, 0x16C, 0x170, 0x174, 0x178, 0x17C, 0x200, 0x204, 0x238, 0x240, 0x244, 0x250, 0x254, 0x258, 0x264, 0x268, 0x26C, 0x270, 0x274, 0x280, 0x284, 0x288, 0x28C, 0x294, 0x2E4, 0x2E8, 0x2EC, 0x2F4, 0x2F8, 0x310, 0x314, 0x320, 0x328, 0x344, 0x348, 0x370, 0x374, 0x37C, 0x380, 0x390, 0x394, 0x398, 0x3AC, 0x3B8, 0x3BC, 0x3C0, 0x3C4, 0x3D8, 0x3E8, 0x41C, 0x420, 0x424, 0x428, 0x42C, 0x430, 0x44C, 0x47C, 0x480, 0x484, 0x4C4, 0x4C8, 0x4CC, 0x50C, 0x554, 0x558, 0x55C, 0x584, 0x588, 0x58C, 0x670, 0x674, 0x690, 0x694, 0x698, 0x69C, 0x6A0, 0x6A4, 0x6C0, 0x6C4, 0x6F0, 0x6F4, 0x960, 0x970, 0x974, 0x9B8, 0xA20, 0xA24, 0xA88, 0xA94, 0xA98, 0xA9C, 0xAA0, 0xAA4, 0xAA8, 0xAAC, 0xAB0, 0xAB4, 0xAB8, 0xABC, 0xAC0, 0xAC4, 0xAC8, 0xACC, 0xAD0, 0xAD4, 0xAD8, 0xADC, 0xAE0, 0xB88, 0xB8C, 0xBC4, 0xBC8, 0xBCC, 0xBD0, 0xBD4, 0xBD8, 0xBDC, 0xBE0, 0xBE4, 0xBE8, 0xBEC, 0xC00, 0xC5C, 0xCAC |
| | | |
| + | == svcCreateSharedMemory == |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 1,278: |
Line 1,279: |
| ! Argument || Type || Name | | ! Argument || Type || Name |
| |- | | |- |
− | | (In) X0 || Handle<TransferMemory> || MemHandle | + | | (In) W1 || u64 || Size |
| |- | | |- |
− | | (In) X1 || void* || Addr | + | | (In) W2 || [[#Permission]] || LocalPerm |
| |- | | |- |
− | | (In) X2 || u64 || Size | + | | (In) W3 || [[#Permission]] || RemotePerm |
| |- | | |- |
| | (Out) W0 || [[#Result]] || Ret | | | (Out) W0 || [[#Result]] || Ret |
| + | |- |
| + | | (Out) W1 || Handle<SharedMemory> || MemHandle |
| |} | | |} |
| </div> | | </div> |
| | | |
− | Size must match size given in map syscall, otherwise there's an invalid-size error.
| + | Other perm can be used to enforce permission 1, 3, or 0x10000000 if don't care. |
| | | |
| + | Allocates memory from the current process' pool partition. |
| | | |
− | == svcCreateInterruptEvent == | + | == svcMapTransferMemory == |
− | | |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 1,298: |
Line 1,301: |
| ! Argument || Type || Name | | ! Argument || Type || Name |
| |- | | |- |
− | | (In) X1 || u64 || IrqNum | + | | (In) X0 || Handle<TransferMemory> || MemHandle |
| |- | | |- |
− | | (In) W2 || bool || Flags | + | | (In) X1 || void* || Addr |
| + | |- |
| + | | (In) X2 || u64 || Size |
| + | |- |
| + | | (In) W3 || [[#Permission]] || Permissions |
| |- | | |- |
| | (Out) W0 || [[#Result]] || Ret | | | (Out) W0 || [[#Result]] || Ret |
− | |-
| |
− | | (Out) W1 || Handle<ReadableEvent> || ReadableEventHandle
| |
| |} | | |} |
| </div> | | </div> |
| | | |
− | Create an event handle for the given IRQ number. Waiting on this handle will wait until the IRQ is triggered. The flags argument configures the triggering. If it is false, the IRQ is active HIGH level sensitive, if it is true it is rising-edge sensitive.
| + | The newly mapped pages will have [[#MemoryState]] type 0xE. |
| | | |
− | === Result codes ===
| + | You must pass same size and permissions as given in svcCreateMemoryMirror, otherwise error. |
− | | |
− | '''0x0:''' Success.
| |
− | | |
− | '''0xF001:''' Flags was > 1
| |
− | | |
− | '''0xF201:''' IRQ above 0x3FF or outside the [[NPDM#Kernel_Access_Control|IRQ access mask]] was given.
| |
− | | |
− | '''0xCE01:''' A SlabHeap was exhausted (too many interrupts created).
| |
− | | |
− | '''0xF401:''' IRQ already has an event registered.
| |
− | | |
− | '''0xD201:''' The handle table is full. Try closing some handles.
| |
− | | |
− | | |
− | == svcQueryPhysicalAddress ==
| |
| | | |
| + | == svcUnmapTransferMemory == |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 1,332: |
Line 1,323: |
| ! Argument || Type || Name | | ! Argument || Type || Name |
| |- | | |- |
− | | (In) X1 || u64 || Addr | + | | (In) X0 || Handle<TransferMemory> || MemHandle |
| |- | | |- |
− | | (Out) W0 || [[#Result]]|| Ret | + | | (In) X1 || void* || Addr |
| |- | | |- |
− | | (Out) X1 || u64 || PhysAddr | + | | (In) X2 || u64 || Size |
| |- | | |- |
− | | (Out) X2 || u64 || BaseAddr | + | | (Out) W0 || [[#Result]] || Ret |
− | |-
| |
− | | (Out) X3 || u64 || Size
| |
| |} | | |} |
| </div> | | </div> |
| | | |
− | '''Description:''' Query the physical address of a virtual address. Will always fetch the lowest page-aligned mapping that contains the provided physical address. | + | Size must match size given in map syscall, otherwise there's an invalid-size error. |
− | | |
− | The returned BaseAddr is the virtual address of that page-aligned mapping, while PhysAddr is the physical address of that page. Size is the amount of continuous physical memory in that mapping.
| |
− | | |
− | == svcQueryIoMapping ==
| |
| | | |
| + | == svcCreateInterruptEvent == |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
− | ! Argument64 || Argument32 || Type || Name | + | ! Argument || Type || Name |
| |- | | |- |
− | | (In) X1 || R2, R3 || u64 || PhysAddr | + | | (In) X1 || u64 || IrqNum |
| |- | | |- |
− | | (In) X2 || R0 || u64 || Size | + | | (In) W2 || bool || Flags |
| |- | | |- |
− | | (Out) W0 || R0 || [[#Result]] || Ret | + | | (Out) W0 || [[#Result]] || Ret |
| |- | | |- |
− | | (Out) X1 || R1 || void* || VirtAddr | + | | (Out) W1 || Handle<ReadableEvent> || ReadableEventHandle |
| |} | | |} |
| </div> | | </div> |
| | | |
− | '''Description:''' Returns a virtual address mapped to a given IO range. | + | Creates an event handle for the given IRQ number. Waiting on this handle will wait until the IRQ is triggered. The flags argument configures the triggering. If it is false, the IRQ is active HIGH level sensitive, if it is true it is rising-edge sensitive. |
| + | |
| + | === Result codes === |
| + | '''0x0:''' Success. |
| + | |
| + | '''0xF001:''' Flags was > 1 |
| + | |
| + | '''0xF201:''' IRQ above 0x3FF or outside the [[NPDM#Kernel_Access_Control|IRQ access mask]] was given. |
| + | |
| + | '''0xCE01:''' A SlabHeap was exhausted (too many interrupts created). |
| + | |
| + | '''0xF401:''' IRQ already has an event registered. |
| | | |
− | == svcCreateDeviceAddressSpace ==
| + | '''0xD201:''' The handle table is full. Try closing some handles. |
| | | |
| + | == svcQueryPhysicalAddress == |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
− | ! Argument64 || Argument32 || Type || Name | + | ! Argument || Type || Name |
| + | |- |
| + | | (In) X1 || u64 || Addr |
| |- | | |- |
− | | (In) X1 || R2, R3 || u64 || StartAddr | + | | (Out) W0 || [[#Result]]|| Ret |
| |- | | |- |
− | | (In) X2 || R0, R1 || u64 || EndAddr | + | | (Out) X1 || u64 || PhysAddr |
| |- | | |- |
− | | (Out) W0 || R0 || [[#Result]] || Ret | + | | (Out) X2 || u64 || BaseAddr |
| |- | | |- |
− | | (Out) W1 || R1 || Handle<DeviceAddressSpace> || AddressSpaceHandle | + | | (Out) X3 || u64 || Size |
| |} | | |} |
| </div> | | </div> |
| | | |
− | '''Description:''' Creates a virtual address space for binding device address spaces and returns a handle.
| + | Queries the physical address of a virtual address. Will always fetch the lowest page-aligned mapping that contains the provided physical address. |
| | | |
− | dev_as_start_addr is normally set to 0 and dev_as_end_addr is normally set to 0xFFFFFFFF.
| + | The returned BaseAddr is the virtual address of that page-aligned mapping, while PhysAddr is the physical address of that page. Size is the amount of continuous physical memory in that mapping. |
− | | |
− | == svcAttachDeviceAddressSpace ==
| |
| | | |
| + | == svcQueryIoMapping == |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
− | ! Argument || Type || Name | + | ! Argument64 || Argument32 || Type || Name |
| + | |- |
| + | | (In) X1 || R2, R3 || u64 || PhysAddr |
| |- | | |- |
− | | (In) W0 || [[#DeviceName]] || DeviceId | + | | (In) X2 || R0 || u64 || Size |
| |- | | |- |
− | | (In) X1 || Handle<DeviceAddressSpace> || DeviceAsHandle | + | | (Out) W0 || R0 || [[#Result]] || Ret |
| |- | | |- |
− | | (Out) W0 || [[#Result]] || Ret | + | | (Out) X1 || R1 || void* || VirtAddr |
| |} | | |} |
| </div> | | </div> |
| | | |
− | '''Description:''' Attaches a device address space to a [[#DeviceName|device]].
| + | Returns a virtual address mapped to a given IO range. |
− | | |
− | == svcDetachDeviceAddressSpace ==
| |
| | | |
| + | == svcCreateDeviceAddressSpace == |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
− | ! Argument || Type || Name | + | ! Argument64 || Argument32 || Type || Name |
| |- | | |- |
− | | (In) W0 || [[#DeviceName]] || DeviceId | + | | (In) X1 || R2, R3 || u64 || StartAddr |
| |- | | |- |
− | | (In) X1 || Handle<DeviceAddressSpace> || DeviceAsHandle | + | | (In) X2 || R0, R1 || u64 || EndAddr |
| + | |- |
| + | | (Out) W0 || R0 || [[#Result]] || Ret |
| |- | | |- |
− | | (Out) W0 || [[#Result]] || Ret | + | | (Out) W1 || R1 || Handle<DeviceAddressSpace> || AddressSpaceHandle |
| |} | | |} |
| </div> | | </div> |
| | | |
− | '''Description:''' Detaches a device address space from a [[#DeviceName|device]].
| + | Creates a virtual address space for binding device address spaces and returns a handle. |
| | | |
− | == svcMapDeviceAddressSpaceByForce ==
| + | StartAddr is normally set to 0 and EndAddr is normally set to 0xFFFFFFFF. |
| | | |
| + | == svcAttachDeviceAddressSpace == |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
− | ! Argument64 || Argument32 || Type || Name | + | ! Argument || Type || Name |
| |- | | |- |
− | | (In) W0 || R0 || Handle<DeviceAddressSpace> || DeviceAsHandle | + | | (In) W0 || [[#DeviceName]] || DeviceId |
| |- | | |- |
− | | (In) W1 || R1 || Handle<Process> || ProcessHandle | + | | (In) X1 || Handle<DeviceAddressSpace> || DeviceAsHandle |
| |- | | |- |
− | | (In) X2 || R2, R3 || void* || SrcAddr | + | | (Out) W0 || [[#Result]] || Ret |
| + | |} |
| + | </div> |
| + | |
| + | Attaches a device address space to a [[#DeviceName|device]]. |
| + | |
| + | == svcDetachDeviceAddressSpace == |
| + | <div style="display: inline-block;"> |
| + | {| class="wikitable" border="1" |
| |- | | |- |
− | | (In) X3 || R4 || u64 || DeviceAsSize | + | ! Argument || Type || Name |
| |- | | |- |
− | | (In) X4 || R5, R6 || u64 || DeviceAsAddr | + | | (In) W0 || [[#DeviceName]] || DeviceId |
| |- | | |- |
− | | (In) W5 || R7 || [[#Permission]] || Permissions | + | | (In) X1 || Handle<DeviceAddressSpace> || DeviceAsHandle |
| |- | | |- |
− | | (Out) W0 || R0 || [[#Result]] || Ret | + | | (Out) W0 || [[#Result]] || Ret |
| |} | | |} |
| </div> | | </div> |
| | | |
− | '''Description:''' Maps an attached device address space to an userspace address.
| + | Detaches a device address space from a [[#DeviceName|device]]. |
| | | |
− | dev_map_addr is the userspace destination address, while dev_as_addr is the source address between dev_as_start_addr and dev_as_end_addr (passed to [[#svcCreateDeviceAddressSpace]]). | + | == svcMapDeviceAddressSpaceByForce == |
| + | <div style="display: inline-block;"> |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Argument64 || Argument32 || Type || Name |
| + | |- |
| + | | (In) W0 || R0 || Handle<DeviceAddressSpace> || DeviceAsHandle |
| + | |- |
| + | | (In) W1 || R1 || Handle<Process> || ProcessHandle |
| + | |- |
| + | | (In) X2 || R2, R3 || void* || SrcAddr |
| + | |- |
| + | | (In) X3 || R4 || u64 || DeviceAsSize |
| + | |- |
| + | | (In) X4 || R5, R6 || u64 || DeviceAsAddr |
| + | |- |
| + | | (In) W5 || R7 || [[#Permission]] || Permissions |
| + | |- |
| + | | (Out) W0 || R0 || [[#Result]] || Ret |
| + | |} |
| + | </div> |
| + | |
| + | Maps an attached device address space to an userspace address. |
| + | |
| + | dev_map_addr is the userspace destination address, while dev_as_addr is the source address between dev_as_start_addr and dev_as_end_addr (passed to [[#svcCreateDeviceAddressSpace]]). |
| | | |
| The userspace destination address must have the [[SVC#MemoryState|MapDeviceAllowed]] bit set. Bit [[SVC#MemoryAttribute|IsDeviceMapped]] will be set after mapping. | | The userspace destination address must have the [[SVC#MemoryState|MapDeviceAllowed]] bit set. Bit [[SVC#MemoryAttribute|IsDeviceMapped]] will be set after mapping. |
| | | |
| == svcMapDeviceAddressSpaceAligned == | | == svcMapDeviceAddressSpaceAligned == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 1,474: |
Line 1,508: |
| </div> | | </div> |
| | | |
− | '''Description:''' Maps an attached device address space to an userspace address.
| + | Maps an attached device address space to an userspace address. |
| | | |
| Same as [[#svcMapDeviceAddressSpaceByForce]], but the userspace destination address must have the [[SVC#MemoryState|MapDeviceAlignedAllowed]] bit set instead. | | Same as [[#svcMapDeviceAddressSpaceByForce]], but the userspace destination address must have the [[SVC#MemoryState|MapDeviceAlignedAllowed]] bit set instead. |
| | | |
| == svcUnmapDeviceAddressSpace == | | == svcUnmapDeviceAddressSpace == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 1,499: |
Line 1,532: |
| </div> | | </div> |
| | | |
− | '''Description:''' Unmaps an attached device address space from an userspace address.
| + | Unmaps an attached device address space from an userspace address. |
| | | |
| == svcContinueDebugEvent == | | == svcContinueDebugEvent == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 1,536: |
Line 1,568: |
| | | |
| === Result codes === | | === Result codes === |
− |
| |
| '''0x0:''' Success. The process has been resumed. | | '''0x0:''' Success. The process has been resumed. |
| | | |
Line 1,544: |
Line 1,575: |
| | | |
| == svcGetProcessList == | | == svcGetProcessList == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 1,555: |
Line 1,585: |
| |- | | |- |
| | (Out) X0 || R0 || [[#Result]] || Ret | | | (Out) X0 || R0 || [[#Result]] || Ret |
− | |- | + | |- |
− | | (Out) X1 || R1 || size_t || NumProcesses | + | | (Out) X1 || R1 || size_t || NumProcesses |
− | |} | + | |} |
− | </div> | + | </div> |
− | | + | |
− | '''Description:''' Fills the provided array with the pids of currently living processes. A process "lives" so long as it is currently running or a handle to it still exists.
| + | Fills the provided array with the pids of currently living processes. A process "lives" so long as it is currently running or a handle to it still exists. |
− | | + | |
− | It returns the total number of processes currently alive. If this number is bigger than the size of PidBuffer, the user won't have all the pids. | + | It returns the total number of processes currently alive. If this number is bigger than the size of PidBuffer, the user won't have all the pids. |
− | | + | |
− | === Result codes === | + | === Result codes === |
− | | + | '''0x0:''' Success. |
− | '''0x0:''' Success. | + | |
− | | + | '''0xd401:''' The provided buffer is outside the process address space. |
− | '''0xd401:''' The provided buffer is outside the process address space. | + | |
− | | + | '''0xe601:''' copyToUser failed. The provided buffer is not user-accessible. |
− | '''0xe601:''' copyToUser failed. The provided buffer is not user-accessible. | + | |
− | | + | '''0xee01:''' The provided buffer size is too big. Max value is 0xFFFFFFF. |
− | '''0xee01:''' The provided buffer size is too big. Max value is 0xFFFFFFF. | + | |
| + | == svcSetHardwareBreakPoint == |
| + | <div style="display: inline-block;"> |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Argument64 || Argument32 || Type || Name |
| + | |- |
| + | | (In) W0 || R0 || u32 || hardware_breakpoint_id |
| + | |- |
| + | | (In) X1 || R2, R3 || u64 || flags |
| + | |- |
| + | | (In) X2 || R1, R4 || u64 || value |
| + | |- |
| + | | (Out) W0 || R0 || [[#Result]] || Ret |
| + | |} |
| + | </div> |
| + | |
| + | Sets one of the AArch64 hardware breakpoints. The nintendo switch has 6 hardware breakpoints, and 4 hardware watchpoints. The syscall has two behaviors depending on the value of hardware_breakpoint_id: |
| + | |
| + | If hardware_breakpoint_id < 0x10, then it sets one of the AArch64 hardware breakpoints. Flags will go to DBGBCRn_EL1, and value to DBGBVRn_EL1. The only flags the user is allowed to set are those in the bitmask 0x7F01E1. Furthermore, the kernel will or it with 0x4004, in order to set various security flags to guarantee the watchpoints only triggers for code in EL0. If the user asks for a Breakpoint Type of ContextIDR match, the kernel shall use the given debug_handle to set DBGBVRn_EL1 to the ContextID of the debugged process. |
| + | |
| + | If hardware_breakpoint_id is between 0x10 and 0x20 (exclusive), then it sets one of the AArch64 hardware watchpoints. Flags will go to DBGWCRn_EL1, and the value to DBGWVRn_EL1. The only flags the user is allowed to set are those in the bitmask 0xFF0F1FF9. Furthermore, the kernel will or it with 0x104004. This will set various security flags, and set the watchpoint type to be a Linked Watchpoint. This means that you need to link it to a Linked ContextIDR breakpoint. Check the ARM documentation for more information. |
| + | |
| + | Note that hardware_breakpoint_id 0 to 4 match only to Virtual Address, while hardware_breakpoint_id 5 and 6 match against either Virtual Address, ContextID, or VMID. As such, if you are configuring a breakpoint to link for a watchpoint, make sure you use hardware_breakpoint_id 5 or 6. |
| + | |
| + | For more documentation for hardware breakpoints, check out the AArch64 documentation for the [http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0488h/way1382455558968.html DBGBCRn_EL1 register] and the [http://infocenter.arm.com/help/topic/com.arm.doc.ddi0488h/way1382455560629.html DBGWCRn_EL1 register] |
| | | |
| == svcGetSystemInfo == | | == svcGetSystemInfo == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 1,615: |
Line 1,669: |
| |- | | |- |
| | Zero || 2 || 1 || PrivilegedProcessId_UpperBound | | | Zero || 2 || 1 || PrivilegedProcessId_UpperBound |
− | |-
| |
| |} | | |} |
| | | |
| == svcSetProcessMemoryPermission == | | == svcSetProcessMemoryPermission == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 1,642: |
Line 1,694: |
| | | |
| == svcMapProcessMemory == | | == svcMapProcessMemory == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 1,665: |
Line 1,716: |
| | | |
| == svcUnmapProcessMemory == | | == svcUnmapProcessMemory == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 1,686: |
Line 1,736: |
| | | |
| == svcQueryProcessMemory == | | == svcQueryProcessMemory == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 1,707: |
Line 1,756: |
| | | |
| == svcMapProcessCodeMemory == | | == svcMapProcessCodeMemory == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 1,728: |
Line 1,776: |
| | | |
| == svcUnmapProcessCodeMemory == | | == svcUnmapProcessCodeMemory == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 1,749: |
Line 1,796: |
| | | |
| == svcCreateProcess == | | == svcCreateProcess == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 1,772: |
Line 1,818: |
| | | |
| === Result codes === | | === Result codes === |
− |
| |
| '''0x0:''' Success. | | '''0x0:''' Success. |
| | | |
Line 1,788: |
Line 1,833: |
| | | |
| == svcGetProcessInfo == | | == svcGetProcessInfo == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 1,807: |
Line 1,851: |
| | | |
| == svcCallSecureMonitor == | | == svcCallSecureMonitor == |
− |
| |
| <div style="display: inline-block;"> | | <div style="display: inline-block;"> |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 1,841: |
Line 1,884: |
| | | |
| svcDebugActiveProcess stops execution of the target process, the normal method for resuming it requires svcContinueDebugEvent(see above). Closing the debug handle also results in execution being resumed. | | svcDebugActiveProcess stops execution of the target process, the normal method for resuming it requires svcContinueDebugEvent(see above). Closing the debug handle also results in execution being resumed. |
− |
| |
− | == svcSetHardwareBreakPoint ==
| |
− |
| |
− | <div style="display: inline-block;">
| |
− | {| class="wikitable" border="1"
| |
− | |-
| |
− | ! Argument64 || Argument32 || Type || Name
| |
− | |-
| |
− | | (In) W0 || R0 || u32 || hardware_breakpoint_id
| |
− | |-
| |
− | | (In) X1 || R2, R3 || u64 || flags
| |
− | |-
| |
− | | (In) X2 || R1, R4 || u64 || value
| |
− | |-
| |
− | | (Out) W0 || R0 || [[#Result]] || Ret
| |
− | |}
| |
− | </div>
| |
− |
| |
− | Sets one of the AArch64 hardware breakpoints. The nintendo switch has 6 hardware breakpoints, and 4 hardware watchpoints. The syscall has two behaviors depending on the value of hardware_breakpoint_id:
| |
− |
| |
− | If hardware_breakpoint_id < 0x10, then it sets one of the AArch64 hardware breakpoints. Flags will go to DBGBCRn_EL1, and value to DBGBVRn_EL1. The only flags the user is allowed to set are those in the bitmask 0x7F01E1. Furthermore, the kernel will or it with 0x4004, in order to set various security flags to guarantee the watchpoints only triggers for code in EL0. If the user asks for a Breakpoint Type of ContextIDR match, the kernel shall use the given debug_handle to set DBGBVRn_EL1 to the ContextID of the debugged process.
| |
− |
| |
− |
| |
− | If hardware_breakpoint_id is between 0x10 and 0x20 (exclusive), then it sets one of the AArch64 hardware watchpoints. Flags will go to DBGWCRn_EL1, and the value to DBGWVRn_EL1. The only flags the user is allowed to set are those in the bitmask 0xFF0F1FF9. Furthermore, the kernel will or it with 0x104004. This will set various security flags, and set the watchpoint type to be a Linked Watchpoint. This means that you need to link it to a Linked ContextIDR breakpoint. Check the ARM documentation for more information.
| |
− |
| |
− | Note that hardware_breakpoint_id 0 to 4 match only to Virtual Address, while hardware_breakpoint_id 5 and 6 match against either Virtual Address, ContextID, or VMID. As such, if you are configuring a breakpoint to link for a watchpoint, make sure you use hardware_breakpoint_id 5 or 6.
| |
− |
| |
− |
| |
− | For more documentation for hardware breakpoints, check out the AArch64 documentation for the [http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0488h/way1382455558968.html DBGBCRn_EL1 register] and the [http://infocenter.arm.com/help/topic/com.arm.doc.ddi0488h/way1382455560629.html DBGWCRn_EL1 register]
| |
| | | |
| = Enum/Structures = | | = Enum/Structures = |
Line 1,886: |
Line 1,900: |
| | 3 || 8 || Floating-point control registers || Reads/writes the FPCR and FPSR registers. | | | 3 || 8 || Floating-point control registers || Reads/writes the FPCR and FPSR registers. |
| |} | | |} |
− |
| |
| | | |
| == DeviceName == | | == DeviceName == |
Line 1,983: |
Line 1,996: |
| | 3 || CodeMemoryOperation_UnmapSlave | | | 3 || CodeMemoryOperation_UnmapSlave |
| |} | | |} |
− |
| |
| | | |
| == LimitableResource == | | == LimitableResource == |
Line 2,001: |
Line 2,013: |
| | | |
| == ProcessInfoType == | | == ProcessInfoType == |
− |
| |
| {| class=wikitable | | {| class=wikitable |
| ! Value || Name | | ! Value || Name |
Line 2,263: |
Line 2,274: |
| | | |
| == ArbitrationType == | | == ArbitrationType == |
− |
| |
| {| class=wikitable | | {| class=wikitable |
| ! Value || Type | | ! Value || Type |
Line 2,276: |
Line 2,286: |
| | | |
| == SignalType == | | == SignalType == |
− |
| |
| {| class=wikitable | | {| class=wikitable |
| ! Value || Type | | ! Value || Type |
Line 2,323: |
Line 2,332: |
| | | |
| == DebugEventInfo == | | == DebugEventInfo == |
− |
| |
| The below table is for the Aarch64 version of the system call. For A32, all u64 fields but title/process/thread id are actually u32, making the structure 0x28-byte-big (0x40 for a64). | | The below table is for the Aarch64 version of the system call. For A32, all u64 fields but title/process/thread id are actually u32, making the structure 0x28-byte-big (0x40 for a64). |
| | | |
Line 2,539: |
Line 2,547: |
| | | |
| ExceptionFrameA32: | | ExceptionFrameA32: |
− |
| |
| {| class=wikitable | | {| class=wikitable |
| ! Offset || Length || Description | | ! Offset || Length || Description |
Line 2,565: |
Line 2,572: |
| | | |
| In that case, after storing the regs in the TLS, the exception handler returns to the application's crt0 (entrypoint), with X0=<error description code> (see below) and X1=SP=frame=<stack top> (see above) | | In that case, after storing the regs in the TLS, the exception handler returns to the application's crt0 (entrypoint), with X0=<error description code> (see below) and X1=SP=frame=<stack top> (see above) |
− |
| |
| | | |
| {| class=wikitable | | {| class=wikitable |