SVC

SVC

System calls #

Note: The argument-lists here apply to the official syscall wrapper-functions that are found in userland processes. The actual ordering passed to the kernel via the SVC instruction is documented in Kernel ABI.

IdNF ARM11NF ARM9TF ARM11DescriptionNotes
0x01YesNoNoResult ControlMemory(u32* outaddr, u32 addr0, u32 addr1, u32 size, MemoryOperation operation, MemoryPermission permissions)Outaddr is usually the same as the input addr0.
0x02YesNoNoResult QueryMemory( MemoryInfo* info, PageInfo* out, u32 Addr)
0x03YesNoNovoid ExitProcess(void)
0x04YesNoNoResult GetProcessAffinityMask(u8* affinitymask, Handle process, s32 processorcount)
0x05YesNoNoResult SetProcessAffinityMask(Handle process, u8* affinitymask, s32 processorcount)
0x06YesNoNoResult GetProcessIdealProcessor(s32 *idealprocessor, Handle process)
0x07YesNoNoResult SetProcessIdealProcessor(Handle process, s32 idealprocessor)
0x08YesYesYesResult CreateThread(Handle* thread, func entrypoint, u32 arg, u32 stacktop, s32 threadpriority, s32 processorid)
0x09YesYesYesvoid ExitThread(void)
0x0AYesYesYesvoid SleepThread(s64 nanoseconds)
0x0BYesYesYesResult GetThreadPriority(s32* priority, Handle thread)
0x0CYesYesYesResult SetThreadPriority(Handle thread, s32 priority)
0x0DYesNoNoResult GetThreadAffinityMask(u8* affinitymask, Handle thread, s32 processorcount)
0x0EYesNoNoResult SetThreadAffinityMask(Handle thread, u8* affinitymask, s32 processorcount)Replaced with a stub in ARM11 NATIVE_FIRM kernel beginning with 8.0.0-18.
0x0FYesNoNoResult GetThreadIdealProcessor(s32* processorid, Handle thread)
0x10YesNoNoResult SetThreadIdealProcessor(Handle thread, s32 processorid)Replaced with a stub in ARM11 NATIVE_FIRM kernel beginning with 8.0.0-18.
0x11YesNoNos32 GetCurrentProcessorNumber(void)
0x12YesNoNoResult Run(Handle process, StartupInfo* info)This starts the main() thread. Buf+0 is main-thread priority, Buf+4 is main-thread stack-size.
0x13YesYesYesResult CreateMutex(Handle* mutex, bool initialLocked)
0x14YesYesYesResult ReleaseMutex(Handle mutex)
0x15YesYesYesResult CreateSemaphore(Handle* semaphore, s32 initialCount, s32 maxCount)
0x16YesYesYesResult ReleaseSemaphore(s32* count, Handle semaphore, s32 releaseCount)
0x17YesYesYesResult CreateEvent(Handle* event, ResetType resettype)
0x18YesYesYesResult SignalEvent(Handle event)
0x19YesYesYesResult ClearEvent(Handle event)
0x1AYesYesYesResult CreateTimer(Handle* timer, ResetType resettype)
0x1BYesYesYesResult SetTimer(Handle timer, s64 initial_nanoseconds, s64 interval)
0x1CYesYesYesResult CancelTimer(Handle timer)
0x1DYesYesYesResult ClearTimer(Handle timer)
0x1EYesNoNoResult CreateMemoryBlock(Handle* memblock, u32 addr, u32 size, MemoryPermission mypermission, MemoryPermission otherpermission)
0x1FYesNoNoResult MapMemoryBlock(Handle memblock, u32 addr, MemoryPermission mypermissions, MemoryPermission otherpermission)
0x20YesNoNoResult UnmapMemoryBlock(Handle memblock, u32 addr)
0x21YesYesYesResult CreateAddressArbiter(Handle* arbiter)
0x22YesYesYesResult ArbitrateAddress(Handle arbiter, u32 addr, ArbitrationType type, s32 value, s64 nanoseconds)
0x23YesYesYesResult CloseHandle(Handle handle)
0x24YesYesYesResult WaitSynchronization1(Handle handle, s64 timeout_nanoseconds)
0x25YesYesYesResult WaitSynchronizationN(s32* out, Handle* handles, s32 handlecount, bool waitAll, s64 timeout_nanoseconds)
0x26YesNoNoResult SignalAndWait(s32* out, Handle signal, Handle* handles, s32 handleCount, bool waitAll, s64 nanoseconds)Stubbed
0x27YesYesYesResult DuplicateHandle(Handle* out, Handle original)
0x28YesYesYess64 GetSystemTick(void) (This returns the total CPU ticks elapsed since the CPU was powered-on)
0x29YesNoNoResult GetHandleInfo(s64* out, Handle handle, HandleInfoType type)
0x2AYesYesYesResult GetSystemInfo(s64* out, SystemInfoType type, s32 param)
0x2BYesYesYesResult GetProcessInfo(s64* out, Handle process, ProcessInfoType type)
0x2CYesYesYesResult GetThreadInfo(s64* out, Handle thread, ThreadInfoType type)
0x2DYesNoNoResult ConnectToPort(Handle* out, const char* portName)
0x2EYesNoNoResult SendSyncRequest1(Handle session)Stubbed
0x2FYesNoNoResult SendSyncRequest2(Handle session)Stubbed
0x30YesNoNoResult SendSyncRequest3(Handle session)Stubbed
0x31YesNoNoResult SendSyncRequest4(Handle session)Stubbed
0x32YesNoNoResult SendSyncRequest(Handle session)
0x33YesNoNoResult OpenProcess(Handle* process, u32 processId)
0x34YesNoNoResult OpenThread(Handle* thread, Handle process, u32 threadId)
0x35YesNoYesResult GetProcessId(u32* processId, Handle process)
0x36YesNoNoResult GetProcessIdOfThread(u32* processId, Handle thread)
0x37YesYesYesResult GetThreadId(u32* threadId, Handle thread)
0x38YesNoNoResult GetResourceLimit(Handle* resourceLimit, Handle process)
0x39YesNoNoResult GetResourceLimitLimitValues(s64* values, Handle resourceLimit, LimitableResource* names, s32 nameCount)
0x3AYesNoNoResult GetResourceLimitCurrentValues(s64* values, Handle resourceLimit, LimitableResource* names, s32 nameCount)
0x3BYesNoNoResult GetThreadContext(ThreadContext* context, Handle thread)Stubbed
0x3CYesYesYesBreak(BreakReason reason) Break(BreakReason debugReason, const void* croInfo, u32 croInfoSize)
0x3DYesYesYesOutputDebugString(void const, int)Does nothing on non-debug units.
0x3EYesNoNoControlPerformanceCounter(unsigned long long, int, unsigned int, unsigned long long)
0x47YesNoNoResult CreatePort(Handle* portServer, Handle* portClient, const char* name, s16 maxSessions)Setting name=NULL creates a private port not accessible from svcConnectToPort.
0x48YesNoNoResult CreateSessionToPort(Handle* session, Handle port)
0x49YesNoNoResult CreateSession(Handle* sessionServer, Handle* sessionClient)
0x4AYesNoNoResult AcceptSession(Handle* session, Handle port)
0x4BYesNoNoResult ReplyAndReceive1(s32* index, Handle* handles, s32 handleCount, Handle replyTarget)Stubbed.
0x4CYesNoNoResult ReplyAndReceive2(s32* index, Handle* handles, s32 handleCount, Handle replyTarget)Stubbed.
0x4DYesNoNoResult ReplyAndReceive3(s32* index, Handle* handles, s32 handleCount, Handle replyTarget)Stubbed.
0x4EYesNoNoResult ReplyAndReceive4(s32* index, Handle* handles, s32 handleCount, Handle replyTarget)Stubbed.
0x4FYesNoNoResult ReplyAndReceive(s32* index, Handle* handles, s32 handleCount, Handle replyTarget)
0x50YesYesYesResult BindInterrupt(Interrupt name, Handle eventOrSemaphore, s32 priority, bool isLevelHighActive)
0x51YesYesYesResult UnbindInterrupt(Interrupt name, Handle eventOrSemaphore)
0x52YesYesYesResult InvalidateProcessDataCache(Handle process, void* addr, u32 size)
0x53YesYesYesResult StoreProcessDataCache(Handle process, void const* addr, u32 size)
0x54YesYesYesResult FlushProcessDataCache(Handle process, void const* addr, u32 size)
0x55YesYesYesResult StartInterProcessDma(Handle* dma, Handle dstProcess, void* dst, Handle srcProcess, const void* src, u32 size, const DmaConfig* config)
0x56YesYesYesResult StopDma(Handle dma)
0x57YesYesYesResult GetDmaState(DmaState* state, Handle dma)
0x58YesYesYesRestartDma(Handle, void *, void const*, unsigned int, signed char)
0x59YesNo?NoSetGpuProt(s8 input_flag). Implemented with 11.3.0-X, see below.
0x5AYesNo?NoSetWifiEnabled(s0 input_flag). Implemented with 11.4.0-X, see below.
0x60YesNoNoResult DebugActiveProcess(Handle* debug, u32 processID)
0x61YesNoNoResult BreakDebugProcess(Handle debug)
0x62YesNoNoResult TerminateDebugProcess(Handle debug)
0x63YesNoNoResult GetProcessDebugEvent(DebugEventInfo* info, Handle debug)
0x64YesNoNoResult ContinueDebugEvent(Handle debug, u32 flags)
0x65YesNoNoResult GetProcessList(s32* processCount, u32* processIds, s32 processIdMaxCount)
0x66YesNoNoResult GetThreadList(s32* threadCount, u32* threadIds, s32 threadIdMaxCount, Handle domain)
0x67YesNoNoResult GetDebugThreadContext(ThreadContext* context, Handle debug, u32 threadId, u32 controlFlags)
0x68YesNoNoResult SetDebugThreadContext(Handle debug, u32 threadId, const ThreadContext* context, u32 controlFlags)
0x69YesNoNoResult QueryDebugProcessMemory(MemoryInfo* blockInfo, PageInfo* pageInfo, Handle debug, u32 addr)
0x6AYesNoNoResult ReadProcessMemory(void* buffer, Handle debug, u32 addr, u32 size)
0x6BYesNoNoResult WriteProcessMemory(Handle debug, void const* buffer, u32 addr, u32 size)
0x6CYesNoNoResult SetHardwareBreakPoint(s32 registerId, u32 control, u32 value)
0x6DYesNoNoGetDebugThreadParam(s64* unused, u32* out, Handle kdebug, u32 threadId, DebugThreadParameter param)
0x70YesNoNoResult ControlProcessMemory(Handle KProcess, unsigned int Addr0, unsigned int Addr1, unsigned int Size, unsigned int Type, unsigned int Permissions)
0x71YesNoNoResult MapProcessMemory(Handle process, u32 startAddr, u32 size)
0x72YesNoNoResult UnmapProcessMemory(Handle process, u32 startAddr, u32 size)
0x73YesNoNoResult CreateCodeSet(Handle* handle_out, struct CodeSetInfo, u32 code_ptr, u32 ro_ptr, u32 data_ptr)
0x74YesNoNoResult RandomStub()Stubbed
0x75YesNoNoResult CreateProcess(Handle* handle_out, Handle codeset_handle, u32 arm11kernelcaps_ptr, u32 arm11kernelcaps_num)
0x76YesNoNoTerminateProcess(Handle)
0x77YesNoNoResult SetProcessResourceLimits(Handle KProcess, Handle KResourceLimit)
0x78YesNoNoResult CreateResourceLimit(Handle *KResourceLimit)
0x79YesNoNoResult SetResourceLimitLimitValues(Handle res_limit, LimitableResource* resource_type_list, s64* resource_list, u32 count)
0x7AYesNoYesAddCodeSegment (unsigned int Addr, unsigned int Size)Stubbed on NATIVE_FIRM beginning with 2.0.0-2. Used during TWL_FIRM boot.
0x7BYesYesNoBackdoor(unsigned int CodeAddress)This is used on ARM9 NATIVE_FIRM. No ARM11 processes have access to it without some form of kernelhax, and this was removed on 11.0.0-33 (for ARM11).
0x7CYesYesYesKernelSetState(unsigned int Type, …)The type determines the args to be passed
0x7DYesNoNoResult QueryProcessMemory(MemInfo *Info, unsigned int *Out, Handle KProcess, unsigned int Addr)
0xFFYesYesYesStop pointThe svcaccesscontrol mask doesn’t apply for this SVC. This svc doesn’t check the “debug mode enabled” flag either. Does nothing if there is no KDebug object associated to the current process. Stubbed on ARM9 NATIVE_FIRM.

NF: NATIVE_FIRM. TF: TWL_FIRM.

Note that “stubbed” here means that the SVC only returns an error, as in the following snippet:

ROM:FFF04D98                 LDR             R0, =0xF8C007F4
ROM:FFF04D9C                 BX              LR

Types and structures #

enum ResetType #

Reset typeId
ONESHOT0
STICKY1
PULSE2

Timers/Events may be waited on by a thread using svcWaitSynchronization. Once the timer runs out/the event gets signaled, threads waiting on the respective handles until the timer/event is reset. STICKY timers/events wake up threads until they are explicitly reset by some thread. ONESHOT timers/events will wake up exactly one thread and then are reset automatically. PULSE timers will be reset after waking up one thread too, but will also be started again immediately. It’s unknown whether PULSE is a valid reset type for events.

struct StartupInfo #

TypeField
s32Priority
u32Stack size
s32argc
s16*argv
s16*envp

enum BreakReason #

Break ReasonValue
PANIC0
ASSERT1
USER2

struct DebugEventInfo #

Size: 0x28 bytes

When using svcGetProcessDebugEvent, the kernel fetches the first KEventInfo instance of the process’s KDebug. The debug event is handled and parsed into this structure.

TypeField
u32Event type
u32Thread ID (not used in all events)
u32Flags. Bit0 means that svcContinueDebugEvent needs to be called for this event
u8[4]Remnants of the corresponding flags in KEventInfo, always 0 here
u32[6]Event-specific data (see below)
Event typeId
ATTACH PROCESS0
ATTACH THREAD1
EXIT THREAD2
EXIT PROCESS (1)3
EXCEPTION4
DLL LOAD (3)5
DLL UNLOAD (3)6
SCHEDULE IN (1) (2)7
SCHEDULE OUT (1) (2)8
SYSCALL IN (1) (2)9
SYSCALL OUT (1) (2)10
OUTPUT STRING11
MAP (1) (2)12

(1) Non-blocking: all other events preempt and block all the threads of their process until they are continued.

(2) There is handling code in the kernel but nothing signal those events.

(3) Completely removed from the kernel, but referenced in DMNT. Stubbed relocation code (e.g., in Process9 and in PXI sysmodule) and even whole libraries (e.g., in PXI sysmodule’s .rodata section) seem to indicate that Nintendo used dynamic libraries early in system development.

When calling svcDebugActiveProcess, an ATTACH PROCESS debug event is signaled, then ATTACH THREAD for each of its opened threads, then finally ATTACH BREAK.

ATTACH THREAD events are also emitted when a thread is created from an attached process.

ATTACH PROCESS event #

TypeField
u64Program ID
char[8]Process name
u32Process ID
u32“Other” flag. Always 0 in available kernel versions

ATTACH THREAD event #

TypeField
u32Creator thread ID (0 if attached by svcDebugActiveProcess)
void *Thread local storage
u32 *Entrypoint = .text load address of the parent process

EXIT THREAD/PROCESS events #

A single u32 reason field is used.

Thread exit reasons:

ReasonId
(None)0
TERMINATE1
EXIT PROCESS2
TERMINATE PROCESS3

Process exit reasons:

ReasonId
(None)0
TERMINATE1
DEBUG TERMINATE2

EXCEPTION event #

TypeField
u32Exception type
u32Exception address
u32[4]Type-specific data, see below

Exception types:

Exception typeId
UNDEFINED INSTRUCTION0
PREFETCH ABORT1
DATA ABORT2
UNALIGNED DATA ACCESS3
ATTACH BREAK4
STOP POINT5
USER BREAK6
DEBUGGER BREAK7
UNDEFINED SYSCALL8

UNDEFINED INSTRUCTION/PREFETCH ABORT/DATA ABORT/UNALIGNED DATA ACCESS/UNDEFINED SYSCALL events #

TypeField
u32Fault information: Fault Address Register (for DATA ABORT and UNALIGNED DATA ACCESS), attempted SVC ID (for UNDEFINED SYSCALL), otherwise 0

STOP POINT event #

TypeField
u32Stop point type that caused the event: 0 = svc 0xFF, 1 = breakpoint, 2 = watchpoint
u32Fault information: FAR for watchpoints, 0 otherwise

USER BREAK event #

TypeField
u32Break reason
u32[2]Info for LOAD_RO and UNLOAD_RO

User break types:

ReasonId
PANIC0
ASSERT1
USER2
LOAD_RO3
UNLOAD_RO4

DEBUGGER BREAK event #

TypeField
s32[4]IDs of the attached process’s threads that were running on each core at the time of the @ref svcBreakDebugProcess call, or -1 (only the first 2 values are meaningful on O3DS).

SCHEDULE/SYSCALL IN/OUT events #

TypeField
u64Clock tick
u32CPU ID (SCHEDULE events) Syscall (SYSCALL events)

OUTPUT STRING event #

TypeField
u32String address
u32String size

MAP event #

TypeField
u32Mapped address
u32Mapped size
u32MemoryPermission
u32MemoryState

struct ThreadContext #

Size: 0xCC bytes

OffsetTypeDescription
0x0CpuRegistersSaved CPU registers (r0-r12, sp, lr, pc, cpsr)
0x44FpuRegistersSaved FPU registers (d0-d15, fpscr, fpexc)

The user needs to adjust pc for exceptions that occured while in Thumb mode.

Flags for svcGetDebugThreadContext/svcSetDebugThreadContext:

BitDescription
0Get/set CPU GPRs (r0-r12)
1Get/set CPU SPRs (sp, lr, pc, cpsr)
2Get/set FPU GPRs (d0-d15 aka. f0-f31)
3Get/set FPU SPRs (fpscr, fpexc)

When setting CPSR, the following assignment is done: ctx->cpsr = ctx->cpsr & 0x7F0FDFF | userCtx->cpuRegisters.cpsr & 0xF80F0200;. This is to avoid obvious security issues.

enum DebugThreadParameter #

ParameterId
PRIORITY0
SCHEDULING_MASK_LOW1
CPU_IDEAL2
CPU_CREATOR3

typedef Handle #

User-visible references to internal objects are represented by 32-bit integers called handles. Handles are only valid in the process they have been created in; hence, they cannot be exchanged between processes directly (the IPC functions provide a mean to copy handles to other processes, though).

There are a number of special-purpose handles, which provide easy access to information on objects in the current process:

HandleDescription
0xFFFF8000Handle to the active thread
0xFFFF8001Handle to the active process

svcSetHardwareBreakPoint #

This is essentially an interface for writing values to the debug-unit (B/W)RP registers. registerId range 0..5 = breakpoints(BRP0-5), 0x100..0x101 = watchpoints(WRP0-1), anything outside of these ranges will result in an error. This is used for both adding and removing/disabling breakpoints/watchpoints, hence the raw control value parameter.

Here the kernel sets bit15 in the DSCR, to enable monitor-mode debugging.

Regardless of whether this is for a BRP, when bit21 is set in the control input parameter(BRP type = contextID), the kernel will load the target process contextID and use that internally for the value field. The target process is specified via a KDebug handle passed as the “value” parameter.

Lastly, the kernel disables the specified (B/W)RP, then writes the value parameter / loaded contextID to the (B/W)VR, then writes the input control value to the (B/W)CR.

DMA #

The CTRSDK code for using svcStartInterProcessDma will execute svcBreak when svcStartInterProcessDma returns an error(except for certain error value(s)). Therefore on retail, triggering a svcStartInterProcessDma via a system-module which results in an error from svcStartInterProcessDma will result in the system-module terminating.

Interrupt Handling #

svcBindInterrupt registers the given event or semaphore corresponding to the handle to the global “interrupt table” for the given interrupt ID. Interrupts 0-14 and 16-31 can never be mapped regardless of the interrupt flags of the process’s exheader, and the latter are not checked when mapping interrupt 15. The “is level high active”/“is manual clear” parameter must be false when binding a semaphore handle (otherwise 0xD8E007EE “invalid combination” is returned).

If something was already registered for the given ID, svcBindInterrupt returns error 0xD8E007F0. See KBaseInterruptEvent for more information on what happens on receipt of an interrupt.

Applications hence can wait for specific interrupts to happen by calling WaitSynchronization(N) on the event or semaphore handles.

The set of existing ARM11 interrupts is listed on this page.

Debugging #

DebugActiveProcess is used to attach to a process for debugging. This SVC can only be used when the target process’ ARM11 descriptors stored in the exheader have the kernel flag for “Enable debug” set. Otherwise when that flag is clear, the kernel flags for the process using this SVC must have the “Force debug” flag set.

This SVC can only be used when a certain kernel state debug flag is non-zero(it’s set to zero for retail).

KernelSetState #

KernelSetState uses the 6th software-generated interrupt for any operation involving synchronization between cores.

TypeEnabled for the NATIVE_FIRM ARM11 kernelEnabled for the TWL_FIRM ARM11 kernelDescription
0YesNoArguments : u64 firmTitleID (the high 32-bits of that title ID (0 when using N3DS pm) have a special meaning on N3DS, they're otherwise ignored, see below). This initializes the programID for launching FIRM, then triggers launching FIRM. With New3DS kernel, it forces the firm title ID to be the New3DS NATIVE_FIRM, when the input firm title ID is 2. The high firm title ID is always set to 0x40138. On New3DS, the kernel disables the additional New3DS cache hw prior to calling the firmlaunch function from the .
1YesYesDoes nothing.
2YesYesPowers down the GPU and syncs with Process9 (waits for *(vu8 *)PXI_SYNC11 to be 1) during the process. On New3DS, the kernel disables the additional New3DS cache hw, when it's actually enabled, prior to executing the rest of the code from the .
3YesNoArguments: 0, void* address or 1 This used for initializing the 0x1000-byte buffer used by the launched FIRM. When the first parameter is 1, this buffer is copied to the beginning of FCRAM at 0xE0000000. When it is 0, this kernel buffer is mapped to the process address specified by the second argument.
4NoYesThis unmaps(?) the following virtual memory by writing value physaddr (where physaddr base is 0x80000000) to the L1 MMU table entries: 0x00300000..0x04300000, 0x08000000..0x0FE00000, and 0x10000000..0xF8000000.
5YesYesPower state change. Takes one u32 parameter.

0: shutdown/reboot. hangs the Arm11. Used by kernelpanic and PTM. This makes all cores enter a WFI/B infinite loop.

6YesNoArguments: u32 what, u64 val UNITINFO needs to be non-zero for what 1 and 2.

If what is 0 or any invalid value, nothing is done.

If it is 1, val != 0 is written to the global variable enabling ERR:F-format register dumps on user-mode CPU/VFP exceptions (the VFP exception handler acts as if this variable was always true and works on retail environments). The user handler, stack pointer to use for exception handling, and pointer to use for the exception info structure are contiguously located in either the thread's TLS, or if the handler is NULL, in the main thread's TLS, at offset 0x40. If the specified stack pointer is 1, sp_usr - 0x5c is used instead; if the specified exception info buffer is 1, sp_usr - 0x5c is used instead, and if it is 0, - 0x5c is used (0x5c is the size of the exception info structure that is being pushed). Configured by NS on startup on dev-units (default being 0 on non-debugger/jtag units) using the 0x000F0000 configuration block in the config savegame.

If 2, kernelpanic will be called when svcBreak is used by a non-attached process. Configured by NS on startup on dev-units (default being 0 on non-debugger/jtag units) using the 0x000F0000 configuration block in the config savegame.

If 3, this changes the scheduling/preemption mode (when no threads are being preempted, otherwise returns error 0xC8A01414), see KResourceLimit for more details.

7YesNoThis triggers an MCU (hard) reboot. This reboot is triggered via device address 0x4A on the second I2C bus (the MCU). Register address 0x20 is written to with value 4. This code will not return. On New3DS, the kernel disables the additional New3DS cache hw prior to calling the reboot function from the .
8YesNoHangs the Arm9, using a code path similar to the one used on firmlaunch. Used by PTM on shutdown/reboot.
9Yes, implemented at some point after system-version v4.5.?Argumens: u64 titleID. When creating a process, if the process has a non-zero TID equal to the parameter above (which is stored in a global variable), then KProcessHwInfo+0x32 ("process is the currently running app") is set to true. Used by NS conditionally based on the contents of the NS CFA.
10Yes?Arguments: u32 config ConfigureNew3DSCPU. Only available for the New_3DS kernel. The actual code for processing this runs under the , which runs on all ARM11 cores. Only bit0-1 of the argument are used here. Bit 0 enables higher core clock, and bit 1 enables additional (L2) cache. This configures the hardware register for the flags listed here, among other code which uses the MPCore private memory region registers.

GetSystemInfo #

SystemInfoType values32 paramDescription
00This writes the total used memory size in the following memory regions to out: APPLICATION, SYSTEM, and BASE.
01This writes the total used memory size in the APPLICATION memory region to out.
02This writes the total used memory size in the SYSTEM memory region to out.
03This writes the total used memory size in the BASE memory region to out.
2UnusedThis writes the FCRAM memory used by the kernel to out.
25UnusedThis writes the total number of threads which were directly launched by the kernel, to out. No longer exists with some kernel version?
26UnusedThis writes the total number of processes which were directly launched by the kernel, to out. For the NATIVE_FIRM/SAFE_MODE_FIRM ARM11 kernel, this is normally 5, for processes sm, fs, pm, loader, and pxi.

GetProcessInfo #

Input:

R0 = unused
R1 = Handle process
R2 = ProcessInfoType type

Output:

R0 = Result
R1 = output value lower word
R2 = output value upper word
ProcessInfoType valueAvailable since system versionDescription
0Returns the amount of private (code, data, regular heap) and shared memory used by the process + total supervisor-mode stack size + page-rounded size of the external handle table. This is the amount of physical memory the process is using, minus TLS, main thread stack and linear memory.
1Returns the amount of + total supervisor-mode stack size + page-rounded size of the external handle table
2Returns the amount of private (code, data, heap) memory used by the process + total supervisor-mode stack size + page-rounded size of the external handle table
3Returns the amount of + total supervisor-mode stack size + page-rounded size of the external handle table
4Returns the amount of handles in use by the process.
5Returns the highest count of handles that have been open at once by the process
6Returns *(u32*)(KProcess+0x234) which is always 0
7Returns the number of threads of the process
8Returns the maximum number of threads which can be opened by this process (always 0)
9-188.0.0-18This only returns error 0xD8E007ED.
19Stub: 8.0.0-18. Implementation: 11.3.0-X.Originally this only returned 0xD8E007ED. Now with v11.3 this returns the memregion for the process: out low u32 = KProcess “Kernel flags from the exheader kernel descriptors” & 0xF00 (memory region flag). High out u32 = 0.
208.0.0-18low u32 = (0x20000000 - ). That is, the output value is the value which can be added to LINEAR memory vaddrs for converting to physical-memory addrs.
218.0.0-18. N3DS only.Returns the VA -> PA conversion offset for the QTM static mem block reserved in the exheader (0x800000), otherwise 0 (+ error 0xE0E01BF4) if it doesn’t exist
228.0.0-18. N3DS only.Returns the base VA of the QTM static mem block reserved in the exheader, otherwise 0 (+ error 0xE0E01BF4) if it doesn’t exist
238.0.0-18. N3DS only.Returns the size of the QTM static mem block reserved in the exheader, otherwise 0 (+ error 0xE0E01BF4) if it doesn’t exist

GetHandleInfo #

HandleInfoType valueDescription
0This returns the time in ticks the KProcess referenced by the handle was created. If a KProcess handle was not given, it will write whatever was in r5, r6 when the svc was called.
1Get internal refcount for kernel object (not counting the one this SVC adds internally to operate), sign-extended to 64 bits.
2Unimplemented, returns an uninitialized u64 variable (corresponding to r5-r6, which were not altered outside of userland).
0x32107Returns (u64) 0.

svc7B Backdoor #

This saves SVC-mode SP+LR on the user-mode stack, then sets the SVC-mode SP to the user-mode SP. This then calls the specified code in SVC-mode. Once the called code returns, this pops the saved SP+LR off the stack for restoring the SVC-mode SP, then returns from the svc7b handler. Note that this svc7b handler does not disable IRQs, if any IRQs/context-switches occur while the SVC-mode SP is set to the user-mode one here, the ARM11-kernel will crash(which hangs the whole ARM11-side system).

svc 0x59 #

Implemented with 11.3.0-X. Used with GSP module starting with that version. This always returns 0.

When input_flag is not 0x1, it will use value 0x0 internally. When a state field already matches input_flag, this will immediately return. Otherwise, after this SVC finishes running, it will write input_flag to this state field. GSP module uses 0x0 for APPLICATION-memregionid and 0x1 for non-APPLICATION-memregionid.

This writes “0x100 | <val>” to pdnregbase+0x140, where val depends on input_flag and a kernel state field for APPMEMTYPE.

When input_flag is 0x1 val is fixed:

  • Old3DS: 0x3
  • New3DS: 0x460

Otherwise, val depends on the kernel APPMEMTYPE state field:

FIRMAPPMEMTYPEval
Old3DS20x3
Old3DS30x5
Old3DS40x6
Old3DSNon-value-{2/3/4}0x7
New3DS70x490
New3DSNon-value-70x4F0

This same register is also initialized during kernel boot starting with 3.0.0-5, with the following values:

  • Old3DS: 0x103
  • New3DS: 0x550

svc 0x5A #

Like what NWM did previously, this one does the following:

 if (in_flag)
    CFG11_WIFICNT |= 1;
 else
    CFG11_WIFICNT &= ~1;

Kernel error-codes #

See Error codes.

Error-code valueDescription
0x09401BFETimeout occurred with svcWaitSynchronization*, when timeout is not ~0.
0xC8601801No more unused/free synchronization objects left to use in a given object’s linked list. (KEvent, KMutex, KTimer, KSemaphore, KAddressArbiter, KThread)
0xC8601802No more unused/free KSharedMemory objects left to use in the KSharedMemory linked list - out of blocks
0xC8601809No more unused/free KSessions left to use in the KSession linked list - out of sessions
0xC860180ANot enough free memory available for memory allocation.
0xC920181AThe session was closed by the other process..
0xD0401834Max connections to port have been exceeded
0xD8609013Unknown, probably reslimit related?
0xD88007FAReturned if no KObjectName object in the linked list of such objects matches the port name provided to the svc.
0xD8E007EDThis indicates that a value is outside of the enum being used.
0xD8E007F1This error indicates Misaligned address.
0xD8E007F7This error indicates that the input handle used with the SVC does not exist in the process handle-table, or that the handle kernel object type does not match the type used by the SVC.
0xD9000402Invalid memory permissions for input/output buffers, for svcStartInterProcessDma.
0xD9001814Failed unprivileged load or store - wrong permissions on memory
0xD9001BF7This error is returned when the kernel retrieves a pointer to a kernel object, but the object type doesn’t match the desired one.
0xD92007EAThis error is returned when a process attempts to use svcCreateMemoryBlock when the process memorytype is the application memorytype, and when addr=0.
0xE0E01BF5This indicates an invalid address was used.
0xF8C007F4Invalid type/param0-param3 input for svcKernelSetState. This is also returned for those syscalls marked as stubs.