Difference between revisions of "SVC"
Line 1,183: | Line 1,183: | ||
| Yes | | Yes | ||
| Yes | | Yes | ||
− | | | + | | Powers down the GPU and sync with Process9 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 <handler for the KernelSetState-types called via funcptr>. | 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 <handler for the KernelSetState-types called via funcptr>. | ||
|- | |- |
Revision as of 00:50, 26 November 2016
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.
Id | NF ARM11 | NF ARM9 | TF ARM11 | Description | Notes | |
---|---|---|---|---|---|---|
0x01 | Yes | No | No | Result ControlMemory(u32* outaddr, u32 addr0, u32 addr1, u32 size, MemoryOperation operation, MemoryPermission permissions) | Outaddr is usually the same as the input addr0. | |
0x02 | Yes | No | No | Result QueryMemory(MemoryInfo* info, PageInfo* out, u32 Addr) | ||
0x03 | Yes | No | No | void ExitProcess(void) | ||
0x04 | Yes | No | No | Result GetProcessAffinityMask(u8* affinitymask, Handle process, s32 processorcount) | ||
0x05 | Yes | No | No | Result SetProcessAffinityMask(Handle process, u8* affinitymask, s32 processorcount) | ||
0x06 | Yes | No | No | Result GetProcessIdealProcessor(s32 *idealprocessor, Handle process) | ||
0x07 | Yes | No | No | Result SetProcessIdealProcessor(Handle process, s32 idealprocessor) | ||
0x08 | Yes | Yes | Yes | Result CreateThread(Handle* thread, func entrypoint, u32 arg, u32 stacktop, s32 threadpriority, s32 processorid) | ||
0x09 | Yes | Yes | Yes | void ExitThread(void) | ||
0x0A | Yes | Yes | Yes | void SleepThread(s64 nanoseconds) | ||
0x0B | Yes | Yes | Yes | Result GetThreadPriority(s32* priority, Handle thread) | ||
0x0C | Yes | Yes | Yes | Result SetThreadPriority(Handle thread, s32 priority) | ||
0x0D | Yes | No | No | Result GetThreadAffinityMask(u8* affinitymask, Handle thread, s32 processorcount) | ||
0x0E | Yes | No | No | Result SetThreadAffinityMask(Handle thread, u8* affinitymask, s32 processorcount) | Replaced with a stub in ARM11 NATIVE_FIRM kernel beginning with 8.0.0-18. | |
0x0F | Yes | No | No | Result GetThreadIdealProcessor(s32* processorid, Handle thread) | ||
0x10 | Yes | No | No | Result SetThreadIdealProcessor(Handle thread, s32 processorid) | Replaced with a stub in ARM11 NATIVE_FIRM kernel beginning with 8.0.0-18. | |
0x11 | Yes | No | No | s32 GetCurrentProcessorNumber(void) | ||
0x12 | Yes | No | No | Result Run(Handle process, StartupInfo* info) | This starts the main() thread. Buf+0 is main-thread priority, Buf+4 is main-thread stack-size. | |
0x13 | Yes | Yes | Yes | Result CreateMutex(Handle* mutex, bool initialLocked) | ||
0x14 | Yes | Yes | Yes | Result ReleaseMutex(Handle mutex) | ||
0x15 | Yes | Yes | Yes | Result CreateSemaphore(Handle* semaphore, s32 initialCount, s32 maxCount) | ||
0x16 | Yes | Yes | Yes | Result ReleaseSemaphore(s32* count, Handle semaphore, s32 releaseCount) | ||
0x17 | Yes | Yes | Yes | Result CreateEvent(Handle* event, ResetType resettype) | ||
0x18 | Yes | Yes | Yes | Result SignalEvent(Handle event) | ||
0x19 | Yes | Yes | Yes | Result ClearEvent(Handle event) | ||
0x1A | Yes | Yes | Yes | Result CreateTimer(Handle* timer, ResetType resettype) | ||
0x1B | Yes | Yes | Yes | Result SetTimer(Handle timer, s64 initial_nanoseconds, s64 interval) | ||
0x1C | Yes | Yes | Yes | Result CancelTimer(Handle timer) | ||
0x1D | Yes | Yes | Yes | Result ClearTimer(Handle timer) | ||
0x1E | Yes | No | No | Result CreateMemoryBlock(Handle* memblock, u32 addr, u32 size, MemoryPermission mypermission, MemoryPermission otherpermission) | ||
0x1F | Yes | No | No | Result MapMemoryBlock(Handle memblock, u32 addr, MemoryPermission mypermissions, MemoryPermission otherpermission) | ||
0x20 | Yes | No | No | Result UnmapMemoryBlock(Handle memblock, u32 addr) | ||
0x21 | Yes | Yes | Yes | Result CreateAddressArbiter(Handle* arbiter) | ||
0x22 | Yes | Yes | Yes | Result ArbitrateAddress(Handle arbiter, u32 addr, ArbitrationType type, s32 value, s64 nanoseconds) | ||
0x23 | Yes | Yes | Yes | Result CloseHandle(Handle handle) | ||
0x24 | Yes | Yes | Yes | Result WaitSynchronization1(Handle handle, s64 timeout_nanoseconds) | ||
0x25 | Yes | Yes | Yes | Result WaitSynchronizationN(s32* out, Handle* handles, s32 handlecount, bool waitAll, s64 timeout_nanoseconds) | ||
0x26 | Yes | No | No | Result SignalAndWait(s32* out, Handle signal, Handle* handles, s32 handleCount, bool waitAll, s64 nanoseconds) | Stubbed | |
0x27 | Yes | Yes | Yes | Result DuplicateHandle(Handle* out, Handle original) | ||
0x28 | Yes | Yes | Yes | s64 GetSystemTick(void) (This returns the total CPU ticks elapsed since the CPU was powered-on) | ||
0x29 | Yes | No | No | Result GetHandleInfo(s64* out, Handle handle, HandleInfoType type) | ||
0x2A | Yes | Yes | Yes | Result GetSystemInfo(s64* out, SystemInfoType type, s32 param) | ||
0x2B | Yes | Yes | Yes | Result GetProcessInfo(s64* out, Handle process, ProcessInfoType type) | ||
0x2C | Yes | Yes | Yes | Result GetThreadInfo(s64* out, Handle thread, ThreadInfoType type) | ||
0x2D | Yes | No | No | Result ConnectToPort(Handle* out, const char* portName) | ||
0x2E | Yes | No | No | Result SendSyncRequest1(Handle session) | Stubbed | |
0x2F | Yes | No | No | Result SendSyncRequest2(Handle session) | Stubbed | |
0x30 | Yes | No | No | Result SendSyncRequest3(Handle session) | Stubbed | |
0x31 | Yes | No | No | Result SendSyncRequest4(Handle session) | Stubbed | |
0x32 | Yes | No | No | Result SendSyncRequest(Handle session) | ||
0x33 | Yes | No | No | Result OpenProcess(Handle* process, u32 processId) | ||
0x34 | Yes | No | No | Result OpenThread(Handle* thread, Handle process, u32 threadId) | ||
0x35 | Yes | No | Yes | Result GetProcessId(u32* processId, Handle process) | ||
0x36 | Yes | No | No | Result GetProcessIdOfThread(u32* processId, Handle thread) | ||
0x37 | Yes | Yes | Yes | Result GetThreadId(u32* threadId, Handle thread) | ||
0x38 | Yes | No | No | Result GetResourceLimit(Handle* resourceLimit, Handle process) | ||
0x39 | Yes | No | No | Result GetResourceLimitLimitValues(s64* values, Handle resourceLimit, LimitableResource* names, s32 nameCount) | ||
0x3A | Yes | No | No | Result GetResourceLimitCurrentValues(s64* values, Handle resourceLimit, LimitableResource* names, s32 nameCount) | ||
0x3B | Yes | No | No | Result GetThreadContext(ThreadContext* context, Handle thread) | Stubbed | |
0x3C | Yes | Yes | Yes | Break(BreakReason) | ||
0x3D | Yes | Yes | Yes | OutputDebugString(void const, int) | Does nothing on non-debug units. | |
0x3E | Yes | No | No | ControlPerformanceCounter(unsigned long long, int, unsigned int, unsigned long long) | ||
0x47 | Yes | No | No | Result CreatePort(Handle* portServer, Handle* portClient, const char* name, s32 maxSessions) | Setting name=NULL creates a private port not accessible from svcConnectToPort. | |
0x48 | Yes | No | No | Result CreateSessionToPort(Handle* session, Handle port) | ||
0x49 | Yes | No | No | Result CreateSession(Handle* sessionServer, Handle* sessionClient) | ||
0x4A | Yes | No | No | Result AcceptSession(Handle* session, Handle port) | ||
0x4B | Yes | No | No | Result ReplyAndReceive1(s32* index, Handle* handles, s32 handleCount, Handle replyTarget) | Stubbed. | |
0x4C | Yes | No | No | Result ReplyAndReceive2(s32* index, Handle* handles, s32 handleCount, Handle replyTarget) | Stubbed. | |
0x4D | Yes | No | No | Result ReplyAndReceive3(s32* index, Handle* handles, s32 handleCount, Handle replyTarget) | Stubbed. | |
0x4E | Yes | No | No | Result ReplyAndReceive4(s32* index, Handle* handles, s32 handleCount, Handle replyTarget) | Stubbed. | |
0x4F | Yes | No | No | Result ReplyAndReceive(s32* index, Handle* handles, s32 handleCount, Handle replyTarget) | ||
0x50 | Yes | Yes | Yes | Result BindInterrupt(Interrupt name, Handle syncObject, s32 priority, bool isLevelHighActive) | ||
0x51 | Yes | Yes | Yes | Result UnbindInterrupt(Interrupt name, Handle syncObject) | ||
0x52 | Yes | Yes | Yes | Result InvalidateProcessDataCache(Handle process, void* addr, u32 size) | ||
0x53 | Yes | Yes | Yes | Result StoreProcessDataCache(Handle process, void const* addr, u32 size) | ||
0x54 | Yes | Yes | Yes | Result FlushProcessDataCache(Handle process, void const* addr, u32 size) | ||
0x55 | Yes | Yes | Yes | Result StartInterProcessDma(Handle* dma, Handle dstProcess, void* dst, Handle srcProcess, const void* src, u32 size, const DmaConfig* config) | ||
0x56 | Yes | Yes | Yes | Result StopDma(Handle dma) | ||
0x57 | Yes | Yes | Yes | Result GetDmaState(DmaState* state, Handle dma) | ||
0x58 | Yes | Yes | Yes | RestartDma(Handle, void *, void const*, unsigned int, signed char) | ||
0x60 | Yes | No | No | Result DebugActiveProcess(Handle* debug, u32 processID) | ||
0x61 | Yes | No | No | Result BreakDebugProcess(Handle debug) | ||
0x62 | Yes | No | No | Result TerminateDebugProcess(Handle debug) | ||
0x63 | Yes | No | No | Result GetProcessDebugEvent(DebugEventInfo* info, Handle debug) | ||
0x64 | Yes | No | No | Result ContinueDebugEvent(Handle debug, u32 flags) | ||
0x65 | Yes | No | No | Result GetProcessList(s32* processCount, u32* processIds, s32 processIdMaxCount) | ||
0x66 | Yes | No | No | Result GetThreadList(s32* threadCount, u32* threadIds, s32 threadIdMaxCount, Handle domain) | ||
0x67 | Yes | No | No | Result GetDebugThreadContext(ThreadContext* context, Handle debug, u32 threadId, u32 controlFlags) | ||
0x68 | Yes | No | No | Result SetDebugThreadContext(Handle debug, u32 threadId, ThreadContext* context, u32 controlFlags) | ||
0x69 | Yes | No | No | Result QueryDebugProcessMemory(MemoryInfo* blockInfo, PageInfo* pageInfo, Handle process, u32 addr) | ||
0x6A | Yes | No | No | Result ReadProcessMemory(void* buffer, Handle debug, u32 addr, u32 size) | ||
0x6B | Yes | No | No | Result WriteProcessMemory(Handle debug, void const* buffer, u32 addr, u32 size) | ||
0x6C | Yes | No | No | Result SetHardwareBreakPoint(s32 registerId, u32 control, u32 value) | ||
0x6D | Yes | No | No | GetDebugThreadParam(s64* unused, u32* out, Handle kdebug, u32 threadId, DebugThreadParam param) | Disabled on regular kernel. | |
0x70 | Yes | No | No | Result ControlProcessMemory(Handle KProcess, unsigned int Addr0, unsigned int Addr1, unsigned int Size, unsigned int Type, unsigned int Permissions) | ||
0x71 | Yes | No | No | Result MapProcessMemory(Handle KProcess, unsigned int StartAddr, unsigned int EndAddr) | ||
0x72 | Yes | No | No | Result UnmapProcessMemory(Handle KProcess, unsigned int StartAddr, unsigned int EndAddr) | ||
0x73 | Yes | No | No | Result CreateCodeSet(Handle* handle_out, struct CodeSetInfo, u32 code_ptr, u32 ro_ptr, u32 data_ptr) | ||
0x74 | Yes | No | No | Result RandomStub() | Stubbed | |
0x75 | Yes | No | No | Result CreateProcess(Handle* handle_out, Handle codeset_handle, u32 arm11kernelcaps_ptr, u32 arm11kernelcaps_num) | ||
0x76 | Yes | No | No | TerminateProcess(Handle) | ||
0x77 | Yes | No | No | Result SetProcessResourceLimits(Handle KProcess, Handle KResourceLimit) | ||
0x78 | Yes | No | No | Result CreateResourceLimit(Handle *KResourceLimit) | ||
0x79 | Yes | No | No | Result SetResourceLimitValues(Handle res_limit, LimitableResource* resource_type_list, s64* resource_list, u32 count) | ||
0x7A | Yes | No | Yes | AddCodeSegment (unsigned int Addr, unsigned int Size) | Stubbed on NATIVE_FIRM beginning with 2.0.0-2. Used during TWL_FIRM boot. | |
0x7B | Yes | Yes | No | Backdoor(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). | |
0x7C | Yes | Yes | Yes | KernelSetState(unsigned int Type, unsigned int Param0, unsigned int Param1, unsigned int Param2) | The type determines the meaning of each param | |
0x7D | Yes | No | No | Result QueryProcessMemory(MemInfo *Info, unsigned int *Out, Handle KProcess, unsigned int Addr) | ||
0xFF | Yes | Yes | Yes | Result SignalBreakpointDebugEvent(void) | The 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 type | Id |
---|---|
ONESHOT | 0 |
STICKY | 1 |
PULSE | 2 |
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
Type | Field |
---|---|
s32 | Priority |
u32 | Stack size |
s32 | argc |
s16* | argv |
s16* | envp |
enum BreakReason
Break Reason | Value |
---|---|
PANIC | 0 |
ASSERT | 1 |
USER | 2 |
struct DebugEventInfo
Type | Field |
---|---|
u32 | Event type |
u32 | Thread ID (not used in all events) |
u32[2] | Unknown/padding |
u32[6] | Event-specific data (see below) |
Event type | Id |
---|---|
PROCESS | 0 |
CREATE THREAD | 1 |
EXIT THREAD | 2 |
EXIT PROCESS | 3 |
EXCEPTION | 4 |
DLL LOAD | 5 |
DLL UNLOAD | 6 |
SCHEDULE IN | 7 |
SCHEDULE OUT | 8 |
SYSCALL IN | 9 |
SYSCALL OUT | 10 |
OUTPUT STRING | 11 |
MAP | 12 |
PROCESS event
Type | Field |
---|---|
u64 | Program ID |
char[8] | Process name |
u32 | Process ID |
u32 | 0 = newly created process, 1 = attached process |
CREATE THREAD event
Type | Field |
---|---|
u32 | Creator thread ID |
u32 | Base address (?) |
u32 | Entrypoint |
EXIT THREAD/PROCESS events
A single u32 reason field is used.
Thread exit reasons:
Reason | Id |
---|---|
(None) | 0 |
TERMINATE | 1 |
EXIT PROCESS | 2 |
TERMINATE PROCESS | 3 |
Process exit reasons:
Reason | Id |
---|---|
(None) | 0 |
TERMINATE | 1 |
UNHANDLED EXCEPTION | 2 |
EXCEPTION event
Type | Field |
---|---|
u32 | Exception type |
u32 | Exception address |
u32 | Argument (type-specific) |
Exception types:
Reason | Id | Argument |
---|---|---|
UNDEFINED INSTRUCTION | 0 | register storage |
PREFETCH ABORT | 1 | register storage |
DATA ABORT | 2 | register storage |
VFP EXCEPTION | 3 | ExceptionInfo |
ATTACH BREAK | 4 | (None) |
BREAKPOINT | 5 | (None) |
USER BREAK | 6 | User break type |
DEBUGGER BREAK | 7 | (None) |
UNDEFINED SYSCALL | 8 | Attempted syscall ID |
The register storage layout is as follows (referring to user-mode registers): r0-r12, <event-signaling exception handler>, lr_svc, sp, lr, pc (misadjusted for Thumb instructions), cpsr.
User break types:
Reason | Id |
---|---|
PANIC | 0 |
ASSERT | 1 |
USER | 2 |
SCHEDULER/SYSCALL IN/OUT events
Type | Field |
---|---|
u64 | Clock tick |
u32 | Syscall (only for SYSCALL events) |
OUTPUT STRING event
Type | Field |
---|---|
u32 | String address |
u32 | String size |
MAP event
Type | Field |
---|---|
u32 | Mapped address |
u32 | Mapped size |
u32 | MemoryPermission |
u32 | MemoryState |
enum DebugThreadParam
Parameter | Id |
---|---|
PRIORITY | 0 |
SCHEDULE | 1 |
CPU_IDEAL | 2 |
CPU_CREATOR | 3 |
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:
Handle | Description |
---|---|
0xFFFF8000 | Handle to the active thread |
0xFFFF8001 | Handle 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
BindInterrupt adds the given event handle to an internal list for the given interrupt ID. Whenever the given interrupt is triggered, the kernel's interrupt handler will signal all events in the list corresponding to that interrupt.
Applications hence can wait for specific interrupts to happen by calling WaitSynchronization(N) on the event handles.
It is unknown whether BindInterrupt may be used with non-event 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
Type | Enabled for the NATIVE_FIRM ARM11 kernel | Enabled for the TWL_FIRM ARM11 kernel | Description |
---|---|---|---|
0 | Yes | No | This initializes the programID for launching FIRM, then triggers launching FIRM. Param0 is unused. Param1 is the programID-low, and the programID-high is 0x00040138. Param2 is used only with the New_3DS kernel, pm-module uses value 0 with this. With New3DS kernel, it forces the programIDlow to be the New3DS NATIVE_FIRM, when the input programIDlow is for the Old3DS NATIVE_FIRM and Param2==0.
On New3DS, the kernel disables the additional New3DS cache hw prior to calling the firmlaunch function from the <handler for the KernelSetState-types called via funcptr>. |
1 | Yes | Yes | Does nothing. |
2 | Yes | Yes | Powers down the GPU and sync with Process9 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 <handler for the KernelSetState-types called via funcptr>. |
3 | Yes | No | This used for initializing the 0x1000-byte buffer used by the launched FIRM. Param2 is unused. When Param0 is value 1, this buffer is copied to the beginning of FCRAM at 0xF0000000, and Param1 is unused. When Param0 is value 0, this kernel buffer is mapped to process address Param1. |
4 | No | Yes | Param0-Param3 are unused. This 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. |
5 | Yes | Yes | Used by kernelpanic. This makes core0 enter a WFI/B infinite loop. Threads that were created on core1 or core2 have their priority set to 0x3F, except if the thread was created on core1 and whose parent process (if any) has the "Runnable on sleep" ARM11 kernel flag set. Core1 threads with a priority of 0x40 without a parent process have their priority set to 0x3E.
Prior to first invoking this handler, if and only if both UNITINFO and 0x1FF80015 are not 0, and if there is no LCD fill set at the time kernelpanic is called, kernelpanic fill the top screen with white (it does the same for the bottom screen if the current process is running under the APPLICATION memregion). Before invoking this handler a second time, kernelpanic wait for the user to hold L+R+Start+Select down. |
6 | Yes | No | Debug related? |
7 | Yes | No | This triggers an MCU (hard) reboot. Param0-3 are unused. 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 <handler for the KernelSetState-types called via funcptr>. |
8 | Yes | No | Alternate FIRM launch code-path, with different PXI FIFO word constants. Usually not used. PTM-sysmodule can use this but it's unknown what exactly triggers that in PTM-sysmodule. |
9 | Yes, implemented at some point after system-version v4.5. | ? | Unknown |
10 | Yes | ? | ConfigureNew3DSCPU. Only available for the New_3DS kernel. The actual code for processing this runs under the <handler for the KernelSetState-types called via funcptr>, which runs on all ARM11 cores. Param0 = input value. Only bit0-1 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 value | s32 param | Description |
---|---|---|
0 | 0 | This writes the total used memory size in the following memory regions to out: APPLICATION, SYSTEM, and BASE. |
0 | 1 | This writes the total used memory size in the APPLICATION memory region to out. |
0 | 2 | This writes the total used memory size in the SYSTEM memory region to out. |
0 | 3 | This writes the total used memory size in the BASE memory region to out. |
2 | Unused | This writes the FCRAM memory used by the kernel to out. |
25 | Unused | This writes the total number of threads which were directly launched by the kernel, to out. No longer exists with some kernel version? |
26 | Unused | This 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 value | Available since system version | Description |
---|---|---|
9-19 | 8.0.0-18 | This only returns error 0xD8E007ED. |
20 | 8.0.0-18 | low u32 = (0x20000000 - <LINEAR virtual-memory base for this process>). That is, the output value is the value which can be added to LINEAR memory vaddrs for converting to physical-memory addrs. |
21-23 | 8.0.0-18 | This only returns error 0xE0E01BF4. |
GetHandleInfo
HandleInfoType value | Description |
---|---|
0 | This 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. |
1 | Get internal refcount-1 for kernel object (u32), and also a boolean if the refcount-1 is negative (u32). |
0x32107 | Returns (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).
Kernel error-codes
See Error codes.
Error-code value | Description |
---|---|
0x09401BFE | Timeout occurred with svcWaitSynchronization*, when timeout is not ~0. |
0xC8601801 | No more unused/free synchronization objects left to use in a given object's linked list. (KEvent, KMutex, KTimer, KSemaphore, KAddressArbiter, KThread) |
0xC8601802 | No more unused/free KSharedMemory objects left to use in the KSharedMemory linked list - out of blocks |
0xC8601809 | No more unused/free KSessions left to use in the KSession linked list - out of sessions |
0xC860180A | Not enough free memory available for memory allocation. |
0xC920181A | The session was closed by the other process.. |
0xD0401834 | Max connections to port have been exceeded |
0xD8609013 | Unknown, probably reslimit related? |
0xD88007FA | Returned if no KObjectName object in the linked list of such objects matches the port name provided to the svc. |
0xD8E007ED | This indicates that a value is outside of the enum being used. |
0xD8E007F1 | This error indicates Misaligned address. |
0xD8E007F7 | This 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. |
0xD9000402 | Invalid memory permissions for input/output buffers, for svcStartInterProcessDma. |
0xD9001814 | Failed unprivileged load or store - wrong permissions on memory |
0xD9001BF7 | This error is returned when the kernel retrieves a pointer to a kernel object, but the object type doesn't match the desired one. |
0xD92007EA | This error is returned when a process attempts to use svcCreateMemoryBlock when the process memorytype is the application memorytype, and when addr=0. |
0xE0E01BF5 | This indicates an invalid address was used. |
0xF8C007F4 | Invalid type/param0-param3 input for svcKernelSetState. This is also returned for those syscalls marked as stubs. |