Changes

Jump to navigation Jump to search
6,227 bytes added ,  03:40, 5 June 2019
add docs for svcCallSecureMonitor.
Line 25: Line 25:  
|  0xA || [[#svcExitThread]] || None ||                                                         
 
|  0xA || [[#svcExitThread]] || None ||                                                         
 
|-
 
|-
|  0xB || [[#svcSleepThread]] || X0=nano || W0=result
+
|  0xB || [[#svcSleepThread]] || X0=nano ||
 
|-
 
|-
 
|  0xC || [[#svcGetThreadPriority]] || W1=thread_handle || W0=result, W1=prio
 
|  0xC || [[#svcGetThreadPriority]] || W1=thread_handle || W0=result, W1=prio
Line 110: Line 110:  
|-
 
|-
 
| 0x35 || [4.0.0+] svcSignalToAddress || X0=ptr, W1=[[#SignalType]], X2=value W3=num_to_signal ||
 
| 0x35 || [4.0.0+] svcSignalToAddress || X0=ptr, W1=[[#SignalType]], X2=value W3=num_to_signal ||
 +
|-
 +
| 0x36 || [8.0.0+] svcSynchronizePreemptionState || None || W0=result
 
|- style="border-top: double"
 
|- style="border-top: double"
 
| 0x3C || [[#svcDumpInfo]] || ||
 
| 0x3C || [[#svcDumpInfo]] || ||
Line 149: Line 151:  
| 0x52 || [[#svcUnmapTransferMemory]] || W0=tmemhandle, X1=addr, X2=size || W0=result
 
| 0x52 || [[#svcUnmapTransferMemory]] || W0=tmemhandle, X1=addr, X2=size || W0=result
 
|-
 
|-
| 0x53 || svcCreateInterruptEvent || X1=irq_num, W2=flag || W0=result, W1=handle
+
| 0x53 || [[#svcCreateInterruptEvent]] || X1=irq_num, W2=flag || W0=result, W1=handle
 
|-
 
|-
 
| 0x54 || [[#svcQueryPhysicalAddress]] || X1=addr || W0=result, X1=physaddr, X2=kerneladdr, X3=size
 
| 0x54 || [[#svcQueryPhysicalAddress]] || X1=addr || W0=result, X1=physaddr, X2=kerneladdr, X3=size
Line 183: Line 185:  
| 0x63 || svcGetDebugEvent || X0=[[#DebugEventInfo]]*, W1=debug_handle || W0=result
 
| 0x63 || svcGetDebugEvent || X0=[[#DebugEventInfo]]*, W1=debug_handle || W0=result
 
|-
 
|-
| 0x64 || svcContinueDebugEvent || [1.0.0-2.3.0] W0=debug_handle, W1=[[#ContinueDebugFlagsOld]], X2=thread_id  
+
| 0x64 || [[#svcContinueDebugEvent]] || [1.0.0-2.3.0] W0=debug_handle, W1=[[#ContinueDebugFlagsOld]], X2=thread_id  
 
[3.0.0+] W0=debug_handle, W1=[[#ContinueDebugFlags]], X2=thread_id_list(u64 *), W3=num_tids (max 64, 0 means "all threads")
 
[3.0.0+] W0=debug_handle, W1=[[#ContinueDebugFlags]], X2=thread_id_list(u64 *), W3=num_tids (max 64, 0 means "all threads")
 
|| W0=result
 
|| W0=result
Line 193: Line 195:  
| 0x67 || svcGetDebugThreadContext || X0=ThreadContext*, X1=debug_handle, X2=thread_id, W3=[[#ThreadContextFlags]] || W0=result
 
| 0x67 || svcGetDebugThreadContext || X0=ThreadContext*, X1=debug_handle, X2=thread_id, W3=[[#ThreadContextFlags]] || W0=result
 
|-
 
|-
| 0x68 || svcSetDebugThreadContext || W0=debug_handle, W1=[[#ThreadContextFlags]], X2=ThreadContext*, X3=thread_id || W0=result
+
| 0x68 || svcSetDebugThreadContext || W0=debug_handle, X1=thread_id, X2=ThreadContext*, W3=[[#ThreadContextFlags]] || W0=result
 
|-
 
|-
 
| 0x69 || svcQueryDebugProcessMemory || X0=[[#MemoryInfo]]*, X2=debug_handle, X3=addr || W0=result, W1=PageInfo
 
| 0x69 || svcQueryDebugProcessMemory || X0=[[#MemoryInfo]]*, X2=debug_handle, X3=addr || W0=result, W1=PageInfo
Line 207: Line 209:  
| 0x6F || [5.0.0+] [[#svcGetSystemInfo]] || X1=info_id, X2=handle, X3=info_sub_id || W0=result, X1=out
 
| 0x6F || [5.0.0+] [[#svcGetSystemInfo]] || X1=info_id, X2=handle, X3=info_sub_id || W0=result, X1=out
 
|-
 
|-
| 0x70 || svcCreatePort || W2=max_sessions, W3=unk_bool, X4=name_ptr || W0=result, W1=clientport_handle, W2=serverport_handle
+
| 0x70 || svcCreatePort || W2=max_sessions, W3=is_light, X4=name_ptr || W0=result, W1=clientport_handle, W2=serverport_handle
 
|-
 
|-
 
| 0x71 || svcManageNamedPort || X1=name_ptr, W2=max_sessions || W0=result, W1=serverport_handle
 
| 0x71 || svcManageNamedPort || X1=name_ptr, W2=max_sessions || W0=result, W1=serverport_handle
Line 237: Line 239:  
| 0x7E || svcSetResourceLimitLimitValue || W0=reslimit_handle, W1=[[#LimitableResource]], X2=value || W0=result
 
| 0x7E || svcSetResourceLimitLimitValue || W0=reslimit_handle, W1=[[#LimitableResource]], X2=value || W0=result
 
|-
 
|-
| 0x7F || svcCallSecureMonitor || X0=smc_sub_id, X1,X2,X3,X4,X5,X6,X7=smc_args || X0,X1,X2,X3,X4,X5,X6,X7=result
+
| 0x7F || [[#svcCallSecureMonitor]] || X0=smc_sub_id, X1,X2,X3,X4,X5,X6,X7=smc_args || X0,X1,X2,X3,X4,X5,X6,X7=result
 
|}
 
|}
   Line 478: Line 480:  
! Argument || Type || Name
 
! Argument || Type || Name
 
|-
 
|-
| (In) X0 || u64 || Nano
+
| (In) X0 || s64 || Nanoseconds
 
|-
 
|-
| (Out) W0 || [[#Result]] || Ret
   
|}
 
|}
 
</div>
 
</div>
Line 486: Line 487:  
'''Description:''' Sleep for a specified amount of time, or yield thread.
 
'''Description:''' Sleep for a specified amount of time, or yield thread.
   −
Setting nano=0 means "yield thread".
+
Setting nanoseconds to 0, -1, or -2 indicates a yielding type.
 +
 
 +
<div style="display: inline-block;">
 +
{| class="wikitable" border="1"
 +
|-
 +
! Value || Type
 +
|-
 +
| 0 || Yielding without core migration
 +
|-
 +
| -1 || Yielding with core migration
 +
|-
 +
| -2 || Yielding to any other thread
 +
|-
 +
|}
 +
</div>
    
== svcGetThreadPriority ==
 
== svcGetThreadPriority ==
Line 646: Line 661:  
</div>
 
</div>
   −
Works with num_handles <= 0x40, error on num_handles == 0.
+
Works with num_handles <= 0x40.
 +
 
 +
When zero handles are passed, this will wait forever until either timeout or cancellation occurs.
    
Does not accept 0xFFFF8001 or 0xFFFF8000 as handles.
 
Does not accept 0xFFFF8001 or 0xFFFF8000 as handles.
Line 652: Line 669:  
=== Object types ===
 
=== Object types ===
   −
'''Port:''' signals when there is an incoming connection waiting to be [[#svcAcceptSession|accepted]].
+
'''KDebug:''' signals when there is a new [[#DebugEventInfo|DebugEvent]] (retrievable via [[#svcGetDebugEvent]]).
 +
 
 +
'''KClientPort:''' signals when the number of sessions is less than the maximum allowed.
   −
'''Session (server-side):''' signals when there is an incoming message waiting to be [[#svcReplyAndReceive|received]] or the pipe is closed.
+
'''KProcess:''' signals when the process undergoes a state change (retrievable via [[#svcGetProcessInfo]]).
 +
 
 +
'''KReadableEvent:''' signals when the event's corresponding KWritableEvent has been signaled via svcSignalEvent.
 +
 
 +
'''KServerPort:''' signals when there is an incoming connection waiting to be [[#svcAcceptSession|accepted]].
 +
 
 +
'''KServerSession:''' signals when there is an incoming message waiting to be [[#svcReplyAndReceive|received]] or the pipe is closed.
 +
 
 +
'''KThread:''' signals when the thread has exited.
    
=== Result codes ===
 
=== Result codes ===
   −
'''0x0:''' Success. One of the objects was signalled before the timeout expired. Handle index is updated to indicate which object signalled.
+
'''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.
 +
 
 +
'''0x7601:''' Thread termination requested. Handle index is not updated.
    
'''0xe401:''' Invalid handle. Returned when one of the handles passed is invalid. Handle index is not updated.
 
'''0xe401:''' Invalid handle. Returned when one of the handles passed is invalid. Handle index is not updated.
   −
'''0xea01:''' Timeout. Returned when no objects have been signalled within the timeout. Handle index is not updated.
+
'''0xe601:''' Invalid address. Returned when the handles pointer is not a readable address. Handle index is not updated.
 +
 
 +
'''0xea01:''' Timeout. Returned when no objects have been signaled within the timeout. Handle index is not updated.
 +
 
 +
'''0xec01:''' Interrupted. Returned when another thread uses [[#svcCancelSynchronization]] to cancel this thread. Handle index is not updated.
   −
'''0xec01:''' Interrupted. Returns when another thread uses [[#svcCancelSynchronization]] to cancel this thread.
+
'''0xee01:''' Too many handles. Returned when the number of handles passed is > 0x40.
    
== svcCancelSynchronization ==
 
== svcCancelSynchronization ==
Line 724: Line 757:  
</div>
 
</div>
   −
Size must be 0x1000-aligned.
+
Size and CmdPtr must be 0x1000-aligned.
    
=== Result codes ===
 
=== Result codes ===
    
'''0x0:''' Success.
 
'''0x0:''' Success.
 +
 +
'''0xcc01:''' CmdPtr is not 0x1000-aligned.
 +
 +
'''0xca01:''' Size is not 0x1000-aligned.
    
'''0xce01:''' KSessionRequest allocation failed (unlikely) or pointer buffer size exceeded.
 
'''0xce01:''' KSessionRequest allocation failed (unlikely) or pointer buffer size exceeded.
 +
 +
'''0xe401:''' Handles does not exist, or handle is not an instance of KClientSession.
    
== svcBreak ==
 
== svcBreak ==
Line 821: Line 860:  
| Process || 20 || 0 || [5.0.0+] UserExceptionContextAddr
 
| Process || 20 || 0 || [5.0.0+] UserExceptionContextAddr
 
|-
 
|-
| Thread  || 0xF0000002 || 0 || Performance counter related.
+
| Process || 21 || 0 || [6.0.0+] TotalMemoryAvailableWithoutMmHeap
 +
|-
 +
| Process || 22 || 0 || [6.0.0+] TotalMemoryUsedWithoutMmHeap
 +
|-
 +
| Thread  || 0xF0000002 || 0 || Scheduler related.
 
|}
 
|}
   Line 1,032: Line 1,075:  
Size must match size given in map syscall, otherwise there's an invalid-size error.
 
Size must match size given in map syscall, otherwise there's an invalid-size error.
   −
== svcQueryPhysicalAddress ==
+
 
 +
== svcCreateInterruptEvent ==
    
<div style="display: inline-block;">
 
<div style="display: inline-block;">
Line 1,039: Line 1,083:  
! Argument || Type || Name
 
! Argument || Type || Name
 
|-
 
|-
| (In) X1 || u64 || Addr
+
| (In) X1 || u64 || IrqNum
 
|-
 
|-
| (Out) W0 || [[#Result]]|| Ret
+
| (In) W2 || bool || Flags
 +
|-
 +
| (Out) W0 || [[#Result]] || Ret
 +
|-
 +
| (Out) W1 || Handle<ReadableEvent> || ReadableEventHandle
 +
|}
 +
</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.
 +
 
 +
=== 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.
 +
 
 +
'''0xD201:''' The handle table is full. Try closing some handles.
 +
 
 +
 
 +
== svcQueryPhysicalAddress ==
 +
 
 +
<div style="display: inline-block;">
 +
{| class="wikitable" border="1"
 +
|-
 +
! Argument || Type || Name
 +
|-
 +
| (In) X1 || u64 || Addr
 +
|-
 +
| (Out) W0 || [[#Result]]|| Ret
 
|-
 
|-
 
| (Out) X1 || u64 || PhysAddr
 
| (Out) X1 || u64 || PhysAddr
Line 1,204: Line 1,282:  
'''Description:''' Unmaps an attached device address space from an userspace address.
 
'''Description:''' Unmaps an attached device address space from an userspace address.
   −
== svcGetSystemInfo ==
+
== svcContinueDebugEvent ==
 +
 
 +
=== Result codes ===
   −
<div style="display: inline-block;">
+
'''0x0:''' Success. The process has been resumed.
 +
 
 +
'''0xe401:''' Invalid debug handle.
 +
 
 +
'''0xf401:''' Process has debug events queued or is already running.
 +
 
 +
== svcGetSystemInfo ==
 +
 
 +
<div style="display: inline-block;">
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 1,387: Line 1,475:  
| (In) X1 || [[#CreateProcessInfo]]* || InfoPtr
 
| (In) X1 || [[#CreateProcessInfo]]* || InfoPtr
 
|-
 
|-
| (In) X2 || u64 || CapabilitiesPtr
+
| (In) X2 || u32* || CapabilitiesPtr
 
|-
 
|-
 
| (In) X3 || u64 || CapabilitiesNum
 
| (In) X3 || u64 || CapabilitiesNum
Line 1,398: Line 1,486:     
Takes a [[#CreateProcessInfo]] as input.
 
Takes a [[#CreateProcessInfo]] as input.
 +
CapabilitiesPtr points to an array of [[NPDM#Kernel_Access_Control|kernel capabilities]].
 +
CapabilitiesNum is a number of capabilities in the CapabilitiesPtr array (number of element, not number of bytes).
 +
 +
=== Result codes ===
 +
 +
'''0x0:''' Success.
 +
 +
'''0xCA01:''' Attempted to map more code pages than available in address space.
 +
 +
'''0xCC01:''' Provided CodeAddr is invalid (make sure it's in range?)
 +
 +
'''0xE401:''' The resource handle passed is invalid.
 +
 +
'''0xE601:''' Attempt to copy procinfo from user-supplied pointer failed. Attempt to copy capabilities_num from user-supplied pointer failed.
 +
 +
'''0xE801:''' Attempted to create a 32-bit process with a 36-bit address space.
 +
 +
'''0xF001:''' Unused bits are set in mmuflags. Unknown address space type used.
    
== svcGetProcessInfo ==
 
== svcGetProcessInfo ==
Line 1,416: Line 1,522:  
Returns an enum with value 0-7.
 
Returns an enum with value 0-7.
   −
== Debugging ==
+
== svcCallSecureMonitor ==
[2.0.0+] Exactly 6 debug SVCs require that [[SPL_services#GetConfig|IsDebugMode]] is non-zero. Error 0x4201 is returned otherwise.
  −
* svcBreakDebugProcess
  −
* svcContinueDebugEvent
  −
* svcWriteDebugProcessMemory
  −
* svcSetDebugThreadContext
  −
* svcTerminateDebugProcess
  −
* svcSetHardwareBreakPoint
  −
 
  −
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;">
 
<div style="display: inline-block;">
Line 1,434: Line 1,529:  
! Argument || Type || Name
 
! Argument || Type || Name
 
|-
 
|-
| (In) W0 || u32 || hardware_breakpoint_id
+
| (In) X0 || u64 || [[SMC#ID_0|Function ID]]
 
|-
 
|-
| (In) W1 || u64 || flags
+
| (In) X1-X7 || u64 || SMC sub-arguments
 
|-
 
|-
| (In) W2 || u64 || value
+
| (Out) X0 || [[SMC#Errors|SMC Result]] || Result of SMC
 +
|-
 +
| (Out) X1-X7 || u64 || SMC sub-output
 +
|}
 +
</div>
 +
 
 +
Takes in a SMC function ID in X0, and arguments for that SMC function in X1-X7.
 +
 
 +
Passing an invalid SMC function ID or calling from a core other than core 3 will result in a secure monitor panic.
 +
 
 +
The kernel parses bits 9-15 in the passed SMC function ID (per the ARM SMC calling convention), and when set uses as an indicator to translate a pointer in the associated register (X1-X7) to a physical address. The kernel will translate any address mapped as R-W, other addresses (R--, R-X, or invalid pointers) will be translated as 0/NULL.
 +
 
 +
Output is returned raw from the Secure Monitor; X0 will be the untranslated SMC result and X1-X7 will contain other SMC output (or be unchanged, depending on the SMC).
 +
 
 +
== Debugging ==
 +
[2.0.0+] Exactly 6 debug SVCs require that [[SPL_services#GetConfig|IsDebugMode]] is non-zero. Error 0x4201 is returned otherwise.
 +
* svcBreakDebugProcess
 +
* svcContinueDebugEvent
 +
* svcWriteDebugProcessMemory
 +
* svcSetDebugThreadContext
 +
* svcTerminateDebugProcess
 +
* svcSetHardwareBreakPoint
 +
 
 +
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"
 +
|-
 +
! Argument || Type || Name
 +
|-
 +
| (In) W0 || u32 || hardware_breakpoint_id
 +
|-
 +
| (In) W1 || u64 || flags
 +
|-
 +
| (In) W2 || u64 || value
 
|-
 
|-
 
| (Out) W0 || [[#Result]] || Ret
 
| (Out) W0 || [[#Result]] || Ret
Line 1,457: Line 1,588:     
= Enum/Structures =
 
= Enum/Structures =
== ThreadContextRequestFlags ==
+
== ThreadContextFlags ==
 
Bitfield of one of more of these:
 
Bitfield of one of more of these:
    
{| class=wikitable
 
{| class=wikitable
! Bit || Bitmask || Name
+
! Bit || Bitmask || Name || Description
 
|-
 
|-
| 0 || 1 || NormalContext
+
| 0 || 1 || General-purpose registers || If in 64-bit mode, GPRs 0–28 will be read/written. If in 32-bit mode, GPRs 0–12 will be read/written.
 
|-
 
|-
| 1 || 2 ||
+
| 1 || 2 || Control registers || Reads/writes the FP, LR, PC, SP, PSTATE, and TPIDR registers.
 
|-
 
|-
| 2 || 4 ||
+
| 2 || 4 || Floating-point registers || Reads/writes the floating-point vector registers.
 
|-
 
|-
| 3 || 8 ||
+
| 3 || 8 || Floating-point control registers || Reads/writes the FPCR and FPSR registers.
 
|}
 
|}
 +
    
== DeviceName ==
 
== DeviceName ==
Line 1,646: Line 1,778:  
| 0 || 12 || || ProcessName (doesn't have to be null-terminated)
 
| 0 || 12 || || ProcessName (doesn't have to be null-terminated)
 
|-
 
|-
| 0 || 4 || || ProcessCategory (0: regular title, 1: kernel built-in)
+
| 0x0C || 4 || || ProcessCategory (0: regular title, 1: kernel built-in)
 
|-
 
|-
 
| 0x10 || 8 || || TitleId
 
| 0x10 || 8 || || TitleId
Line 1,670: Line 1,802:  
| || || Bit10-7 || [5.0.0+] PoolPartition (0=Application, 1=Applet, 2=Sysmodule, 3=Nvservices)
 
| || || Bit10-7 || [5.0.0+] PoolPartition (0=Application, 1=Applet, 2=Sysmodule, 3=Nvservices)
 
|-
 
|-
| 0x28 || 4 || || ResourceLimitHandle
+
| || || Bit11 || [7.0.0+] Only allowed in combination with bit6.
 +
|-
 +
| 0x28 || 4 || || ResourceLimitHandle or zero
 
|-
 
|-
 
| 0x2C || 4 || || [3.0.0+] PersonalMmHeapNumPages
 
| 0x2C || 4 || || [3.0.0+] PersonalMmHeapNumPages
Line 1,680: Line 1,814:     
On [5.0.0] PoolPartition is specified in CreateProcessArgs. There are now 4 pool partitions.
 
On [5.0.0] PoolPartition is specified in CreateProcessArgs. There are now 4 pool partitions.
 +
 +
On [5.0.0] (maybe lower?) a zero ResourceLimitHandle defaults to sysmodule limits and 0x12300000 bytes of memory.
 +
 +
The PersonalMmHeap are allocated as follows:
 +
* For the application, normal insecure pool is used. Carveout 5 is used to provide protection.
 +
* For the applet, a pre-allocated secure pool segment of size 0x400000 is used.
 +
* For sysmodules, secure pool is allocated.
    
=== AddressSpaceType ===
 
=== AddressSpaceType ===
Line 1,721: Line 1,862:  
| 0 || IsBorrowed
 
| 0 || IsBorrowed
 
|-
 
|-
| 1 || IsIpcMapped: when IpcRefCount > 0.
+
| 1 || IsIpcLocked (when IpcRefCount > 0)
 
|-
 
|-
| 2 || IsDeviceMapped: when DeviceRefCount > 0.
+
| 2 || IsDeviceShared (when DeviceRefCount > 0)
 
|-
 
|-
 
| 3 || IsUncached
 
| 3 || IsUncached
Line 1,738: Line 1,879:  
| 9 || ForceReadWritableByDebugSyscalls
 
| 9 || ForceReadWritableByDebugSyscalls
 
|-
 
|-
| 10 || IpcSendAllowed_Type0
+
| 10 || IpcSendAllowed
 
|-
 
|-
| 11 || IpcSendAllowed_Type3
+
| 11 || NonDeviceIpcSendAllowed
 
|-
 
|-
| 12 || IpcSendAllowed_Type1
+
| 12 || NonSecureIpcSendAllowed
 
|-
 
|-
 
| 14 || [[#svcSetProcessMemoryPermission|ProcessPermissionChangeAllowed]]
 
| 14 || [[#svcSetProcessMemoryPermission|ProcessPermissionChangeAllowed]]
Line 1,812: Line 1,953:  
|| MemoryType_ModuleCodeMutable || Transition from 0xDD7E08 performed by [[#svcSetProcessMemoryPermission]].
 
|| MemoryType_ModuleCodeMutable || Transition from 0xDD7E08 performed by [[#svcSetProcessMemoryPermission]].
 
|-
 
|-
| 0x005C3C0A || [[IPC_Marshalling|MemoryType_IpcBuffer0]] || IPC buffers with descriptor flags=0.
+
| 0x005C3C0A || [[IPC_Marshalling|MemoryType_Ipc]] || IPC buffers with descriptor flags=0.
 
|-
 
|-
 
| 0x005C3C0B || MemoryType_Stack || Mapped using [[#svcMapMemory]].
 
| 0x005C3C0B || MemoryType_Stack || Mapped using [[#svcMapMemory]].
Line 1,826: Line 1,967:  
| 0x00000010 || MemoryType_Reserved ||
 
| 0x00000010 || MemoryType_Reserved ||
 
|-
 
|-
| 0x005C3811 || [[IPC_Marshalling|MemoryType_IpcBuffer1]] || IPC buffers with descriptor flags=1.
+
| 0x005C3811 || [[IPC_Marshalling|MemoryType_NonSecureIpc]] || IPC buffers with descriptor flags=1.
 
|-
 
|-
| 0x004C2812 || [[IPC_Marshalling|MemoryType_IpcBuffer3]] || IPC buffers with descriptor flags=3.
+
| 0x004C2812 || [[IPC_Marshalling|MemoryType_NonDeviceIpc]] || IPC buffers with descriptor flags=3.
 
|-
 
|-
 
| 0x00002013 || MemoryType_KernelStack || Mapped in kernel during [[#svcCreateThread]].
 
| 0x00002013 || MemoryType_KernelStack || Mapped in kernel during [[#svcCreateThread]].
Line 1,999: Line 2,140:  
|}
 
|}
   −
* Undefined instructions, software breakpoints, some other traps.
+
<nowiki>*</nowiki> Undefined instructions, software breakpoints, some other traps.
** Data aborts, FP traps, and everything else that doesn't belong to any of the above.
+
 
 +
<nowiki>**</nowiki> Data aborts, FP traps, and everything else that doesn't belong to any of the above.
    
Trap specifics:
 
Trap specifics:
Line 2,043: Line 2,185:  
KDebug dispatching is used when at least one of the following conditions are met:
 
KDebug dispatching is used when at least one of the following conditions are met:
 
* SMC ConfigItem KernelMemConfig bit 1 is NOT set (it isn't on retail), unless: this is a software or hardware breakpoint, or a watchpoint, or [4.0.0+?] the process is attached and this is a Google PNaCl trap instruction (see LLVM source)
 
* SMC ConfigItem KernelMemConfig bit 1 is NOT set (it isn't on retail), unless: this is a software or hardware breakpoint, or a watchpoint, or [4.0.0+?] the process is attached and this is a Google PNaCl trap instruction (see LLVM source)
* PC doesn't point to a valid address in mapped-readable CodeStatic memory (i.e. this is the case for NRO and JIT memory) or this one of the following exceptions (it particular, that doesn't include FP exceptions occuring in CodeStatic memory):
+
* FAR doesn't point to a valid address in mapped-readable CodeStatic memory (i.e. this is the case for NRO and JIT memory) or this is one of the following exceptions (it particular, that doesn't include FP exceptions occurring in CodeStatic memory):
 
** Uncategorized
 
** Uncategorized
 
** IllegalState
 
** IllegalState
Line 2,063: Line 2,205:  
If the process is attached, the exception is reported to the KDebug. If the thread was continued using flag IgnoreExceptions, it returns from the exception as if nothing happened.
 
If the process is attached, the exception is reported to the KDebug. If the thread was continued using flag IgnoreExceptions, it returns from the exception as if nothing happened.
   −
If the latter is not the case, or if the process isn't attached, process to [2.0.0+] crash reporting (or in [1.0.0] just terminate the process):  
+
If the latter is not the case, or if the process isn't attached, proceed to [2.0.0+] crash reporting (or in [1.0.0] just terminate the process):  
if EnableDebug is set, and depending on the process state (more than one crash per process isn't permitted) it may signal itself with ProcessState_Crashed so that PM asks NS to start creport so that creports attaches to it and reports the crashes. Otherwise, just terminate.
+
if EnableDebug is set, and depending on the process state (more than one crash per process isn't permitted) it may signal itself with ProcessState_Crashed so that PM asks NS to start creport so that creport attaches to it and reports the crashes. Otherwise, just terminate.
    
Userland reporting path and svcReturnFromException:
 
Userland reporting path and svcReturnFromException:
Line 2,075: Line 2,217:  
| 0x0 || 0x148 || Exception stack
 
| 0x0 || 0x148 || Exception stack
 
|-
 
|-
| 0x148 || 0x78 || Frame: x0..x30, sp, elr_el1=unadjusted PC, pstate & 0xFF0FFE20,
+
| 0x148 || 0x78 || ExceptionFrameA64
afsr0, afsr1, esr, pc (stored using the regs' own size)
+
|}
 +
 
 +
ExceptionFrameA64:
 +
 
 +
{| class=wikitable
 +
! Offset || Length || Description
 +
|-
 +
| 0x0 || 0x48 (8*9) || GPRs 0..8.
 +
|-
 +
| 0x48 || 0x8 || lr
 +
|-
 +
| 0x50 || 0x8 || sp
 +
|-
 +
| 0x58 || 0x8 || pc (elr_el1)
 +
|-
 +
| 0x60 || 0x4 || pstate & 0xFF0FFE20
 +
|-
 +
| 0x64 || 0x4 || afsr0
 +
|-
 +
| 0x68 || 0x4 || afsr1
 +
|-
 +
| 0x6C || 0x4 || esr
 +
|-
 +
| 0x70 || 0x8 || far
 
|}
 
|}
   Line 2,086: Line 2,251:  
| 0x0 || 0x178 || Exception stack
 
| 0x0 || 0x178 || Exception stack
 
|-
 
|-
| 0x148 || 0x30 || Frame: r0..r14, elr_el1=unadjusted PC, tpidr_el0 = 1, cpsr & 0xFF0FFE20,
+
| 0x148 || 0x44 || ExceptionFrameA32
afsr0, afsr1, esr, pc (stored using the regs' own size)
   
|}
 
|}
    +
ExceptionFrameA32:
 +
 +
{| class=wikitable
 +
! Offset || Length || Description
 +
|-
 +
| 0x0 || 0x20 (8*4) || GPRs 0..7.
 +
|-
 +
| 0x20 || 0x4 || sp
 +
|-
 +
| 0x24 || 0x4 || lr
 +
|-
 +
| 0x28 || 0x4 || pc (elr_el1)
 +
|-
 +
| 0x2C || 0x4 || tpidr_el0 = 1
 +
|-
 +
| 0x30 || 0x4 || cpsr & 0xFF0FFE20
 +
|-
 +
| 0x34 || 0x4 || afsr0
 +
|-
 +
| 0x38 || 0x4 || afsr1
 +
|-
 +
| 0x3C || 0x4 || esr
 +
|-
 +
| 0x40 || 0x4 || far
 +
|}
    
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)
Line 2,120: Line 2,309:  
* if the provided error code is 0, gracefully pivots and returns from exception
 
* if the provided error code is 0, gracefully pivots and returns from exception
 
* if it is not, replays the exception and pass it to the KDebug (see above). One can pass 0x10001 to prevent process termination. If the process is attached, this also prevents crash-collection/termination (different from the exception handler behavior)
 
* if it is not, replays the exception and pass it to the KDebug (see above). One can pass 0x10001 to prevent process termination. If the process is attached, this also prevents crash-collection/termination (different from the exception handler behavior)
 +
 +
If an exception occurs from the above user handler, the entire exception handling process will repeat with the new exception.
    
Note that if a thread that wasn't faulting calls svcReturnFromException, it signals an "invalid syscall" exception
 
Note that if a thread that wasn't faulting calls svcReturnFromException, it signals an "invalid syscall" exception
 +
 +
Note that [[SMC|IsDebugMode]] is not used during exception-handling, except for enabling printing a message to UART-A. This UART code causes a system-hang on retail (likely due to a loop that doesn't exit). This printing doesn't seem to run when the process is attached for debugging?

Navigation menu