Line 432: |
Line 432: |
| | style="background: green" | Yes | | | style="background: green" | Yes |
| | style="background: green" | Yes | | | style="background: green" | Yes |
− | | Break(BreakReason) | + | | Break(BreakReason reason) |
| + | Break(BreakReason debugReason, const void* croInfo, u32 croInfoSize) |
| | | | | |
| |- | | |- |
Line 453: |
Line 454: |
| | style="background: red" | No | | | style="background: red" | No |
| | style="background: red" | No | | | style="background: red" | No |
− | | Result [[IPC|CreatePort]](Handle* portServer, Handle* portClient, const char* name, s32 maxSessions) | + | | Result [[IPC|CreatePort]](Handle* portServer, Handle* portClient, const char* name, s16 maxSessions) |
| | Setting name=NULL creates a private port not accessible from svcConnectToPort. | | | Setting name=NULL creates a private port not accessible from svcConnectToPort. |
| |- | | |- |
Line 509: |
Line 510: |
| | style="background: red" | No | | | style="background: red" | No |
| | style="background: red" | No | | | style="background: red" | No |
− | | Result [[IPC|ReplyAndReceive]](s32* index, Handle* handles, s32 handleCount, Handle replyTarget) | + | | Result [[IPC#svcReplyAndReceive|ReplyAndReceive]](s32* index, Handle* handles, s32 handleCount, Handle replyTarget) |
| | | | | |
| |- | | |- |
Line 516: |
Line 517: |
| | style="background: green" | Yes | | | style="background: green" | Yes |
| | style="background: green" | Yes | | | style="background: green" | Yes |
− | | Result [[#Interrupt Handling|BindInterrupt]](Interrupt name, Handle syncObject, s32 priority, bool isLevelHighActive) | + | | Result [[#Interrupt Handling|BindInterrupt]](Interrupt name, Handle eventOrSemaphore, s32 priority, bool isLevelHighActive) |
| | | | | |
| |- | | |- |
Line 523: |
Line 524: |
| | style="background: green" | Yes | | | style="background: green" | Yes |
| | style="background: green" | Yes | | | style="background: green" | Yes |
− | | Result UnbindInterrupt(Interrupt name, Handle syncObject) | + | | Result UnbindInterrupt(Interrupt name, Handle eventOrSemaphore) |
| | | | | |
| |- | | |- |
Line 574: |
Line 575: |
| | RestartDma(Handle, void *, void const*, unsigned int, signed char) | | | RestartDma(Handle, void *, void const*, unsigned int, signed char) |
| | | | | |
| + | |- |
| + | | 0x59 |
| + | | style="background: green" | Yes |
| + | | style="background: red" | No? |
| + | | style="background: red" | No |
| + | | SetGpuProt(s8 input_flag). Implemented with [[11.3.0-36|11.3.0-X]], see below. |
| + | |- |
| + | | 0x5A |
| + | | style="background: green" | Yes |
| + | | style="background: red" | No? |
| + | | style="background: red" | No |
| + | | SetWifiEnabled(s0 input_flag). Implemented with [[11.4.0-37|11.4.0-X]], see below. |
| |- style="border-top: double" | | |- style="border-top: double" |
| | 0x60 | | | 0x60 |
Line 635: |
Line 648: |
| | style="background: red" | No | | | style="background: red" | No |
| | style="background: red" | No | | | style="background: red" | No |
− | | Result SetDebugThreadContext(Handle debug, u32 threadId, ThreadContext* context, u32 controlFlags) | + | | Result SetDebugThreadContext(Handle debug, u32 threadId, const ThreadContext* context, u32 controlFlags) |
| | | | | |
| |- | | |- |
Line 642: |
Line 655: |
| | style="background: red" | No | | | style="background: red" | No |
| | style="background: red" | No | | | style="background: red" | No |
− | | Result QueryDebugProcessMemory(MemoryInfo* blockInfo, PageInfo* pageInfo, Handle process, u32 addr) | + | | Result QueryDebugProcessMemory(MemoryInfo* blockInfo, PageInfo* pageInfo, Handle debug, u32 addr) |
| | | | | |
| |- | | |- |
Line 670: |
Line 683: |
| | style="background: red" | No | | | style="background: red" | No |
| | style="background: red" | No | | | style="background: red" | No |
− | | [[Multi-threading#GetDebugThreadParam|GetDebugThreadParam]](s64* unused, u32* out, Handle kdebug, u32 threadId, DebugThreadParam param) | + | | [[Multi-threading#GetDebugThreadParam|GetDebugThreadParam]](s64* unused, u32* out, Handle kdebug, u32 threadId, DebugThreadParameter param) |
− | | Disabled on regular kernel. | + | | |
| |- style="border-top: double" | | |- style="border-top: double" |
| | 0x70 | | | 0x70 |
Line 684: |
Line 697: |
| | style="background: red" | No | | | style="background: red" | No |
| | style="background: red" | No | | | style="background: red" | No |
− | | Result [[Memory Management#Memory_Mapping|MapProcessMemory]](Handle KProcess, unsigned int StartAddr, unsigned int EndAddr) | + | | Result [[Memory Management#Memory_Mapping|MapProcessMemory]](Handle process, u32 startAddr, u32 size) |
| | | | | |
| |- | | |- |
Line 691: |
Line 704: |
| | style="background: red" | No | | | style="background: red" | No |
| | style="background: red" | No | | | style="background: red" | No |
− | | Result [[Memory Management#Memory_Mapping|UnmapProcessMemory]](Handle KProcess, unsigned int StartAddr, unsigned int EndAddr) | + | | Result [[Memory Management#Memory_Mapping|UnmapProcessMemory]](Handle process, u32 startAddr, u32 size) |
| | | | | |
| |- | | |- |
Line 740: |
Line 753: |
| | style="background: red" | No | | | style="background: red" | No |
| | style="background: red" | No | | | style="background: red" | No |
− | | Result SetResourceLimitValues(Handle res_limit, LimitableResource* resource_type_list, s64* resource_list, u32 count) | + | | Result SetResourceLimitLimitValues(Handle res_limit, LimitableResource* resource_type_list, s64* resource_list, u32 count) |
| | | | | |
| |- | | |- |
Line 763: |
Line 776: |
| | style="background: green" | Yes | | | style="background: green" | Yes |
| | style="background: green" | Yes | | | style="background: green" | Yes |
− | | KernelSetState(unsigned int Type, unsigned int Param0, unsigned int Param1, unsigned int Param2) | + | | KernelSetState(unsigned int Type, ...) |
− | | The type determines the meaning of each param | + | | The type determines the args to be passed |
| |- | | |- |
| | 0x7D | | | 0x7D |
Line 777: |
Line 790: |
| | style="background: green" | Yes | | | style="background: green" | Yes |
| | style="background: green" | Yes | | | style="background: green" | Yes |
− | | Result SignalBreakpointDebugEvent(void) | + | | Stop point |
| | 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. | | | 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. |
| |} | | |} |
Line 844: |
Line 857: |
| | | |
| == struct DebugEventInfo == | | == 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. |
| | | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 855: |
Line 871: |
| | Thread ID (not used in all events) | | | Thread ID (not used in all events) |
| |- | | |- |
− | | u32[2] | + | | u32 |
− | | Unknown/padding | + | | Flags. 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] | | | u32[6] |
Line 866: |
Line 885: |
| ! Id | | ! Id |
| |- | | |- |
− | | PROCESS | + | | ATTACH PROCESS |
| | 0 | | | 0 |
| |- | | |- |
− | | CREATE THREAD | + | | ATTACH THREAD |
| | 1 | | | 1 |
| |- | | |- |
Line 875: |
Line 894: |
| | 2 | | | 2 |
| |- | | |- |
− | | EXIT PROCESS | + | | EXIT PROCESS (1) |
| | 3 | | | 3 |
| |- | | |- |
Line 881: |
Line 900: |
| | 4 | | | 4 |
| |- | | |- |
− | | DLL LOAD | + | | DLL LOAD (3) |
| | 5 | | | 5 |
| |- | | |- |
− | | DLL UNLOAD | + | | DLL UNLOAD (3) |
| | 6 | | | 6 |
| |- | | |- |
− | | SCHEDULE IN | + | | SCHEDULE IN (1) (2) |
| | 7 | | | 7 |
| |- | | |- |
− | | SCHEDULE OUT | + | | SCHEDULE OUT (1) (2) |
| | 8 | | | 8 |
| |- | | |- |
− | | SYSCALL IN | + | | SYSCALL IN (1) (2) |
| | 9 | | | 9 |
| |- | | |- |
− | | SYSCALL OUT | + | | SYSCALL OUT (1) (2) |
| | 10 | | | 10 |
| |- | | |- |
Line 902: |
Line 921: |
| | 11 | | | 11 |
| |- | | |- |
− | | MAP | + | | MAP (1) (2) |
| | 12 | | | 12 |
| |} | | |} |
| | | |
− | === PROCESS event === | + | <nowiki>(1)</nowiki> Non-blocking: all other events preempt and block all the threads of their process until they are continued. |
| + | |
| + | <nowiki>(2)</nowiki> There is handling code in the kernel but nothing signal those events. |
| + | |
| + | <nowiki>(3)</nowiki> 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 === |
| | | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 922: |
Line 951: |
| |- | | |- |
| | u32 | | | u32 |
− | | 0 = newly created process, 1 = attached process | + | | "Other" flag. Always 0 in available kernel versions |
| |} | | |} |
| | | |
− | === CREATE THREAD event === | + | === ATTACH THREAD event === |
| | | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 932: |
Line 961: |
| |- | | |- |
| | u32 | | | u32 |
− | | Creator thread ID | + | | Creator thread ID (0 if attached by svcDebugActiveProcess) |
| |- | | |- |
− | | u32 | + | | void * |
− | | Base address (?) | + | | Thread local storage |
| |- | | |- |
− | | u32 | + | | u32 * |
− | | Entrypoint | + | | Entrypoint = .text load address of the parent process |
| |} | | |} |
| | | |
Line 974: |
Line 1,003: |
| | 1 | | | 1 |
| |- | | |- |
− | | UNHANDLED EXCEPTION | + | | DEBUG TERMINATE |
| | 2 | | | 2 |
| |} | | |} |
Line 990: |
Line 1,019: |
| | Exception address | | | Exception address |
| |- | | |- |
− | | u32 | + | | u32[4] |
− | | Argument (type-specific) | + | | Type-specific data, see below |
| |} | | |} |
| | | |
| Exception types: | | Exception types: |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
− | ! Reason | + | ! Exception type |
| ! Id | | ! Id |
− | ! Argument
| |
| |- | | |- |
| | UNDEFINED INSTRUCTION | | | UNDEFINED INSTRUCTION |
| | 0 | | | 0 |
− | | register storage
| |
| |- | | |- |
| | PREFETCH ABORT | | | PREFETCH ABORT |
| | 1 | | | 1 |
− | | register storage
| |
| |- | | |- |
| | DATA ABORT | | | DATA ABORT |
| | 2 | | | 2 |
− | | register storage
| |
| |- | | |- |
− | | VFP EXCEPTION | + | | UNALIGNED DATA ACCESS |
| | 3 | | | 3 |
− | | [[ERR:Throw#ExceptionInfo|ExceptionInfo]]
| |
| |- | | |- |
| | ATTACH BREAK | | | ATTACH BREAK |
| | 4 | | | 4 |
− | | (None)
| |
| |- | | |- |
− | | BREAKPOINT | + | | STOP POINT |
| | 5 | | | 5 |
− | | (None)
| |
| |- | | |- |
| | USER BREAK | | | USER BREAK |
| | 6 | | | 6 |
− | | User break type
| |
| |- | | |- |
| | DEBUGGER BREAK | | | DEBUGGER BREAK |
| | 7 | | | 7 |
− | | (None)
| |
| |- | | |- |
| | UNDEFINED SYSCALL | | | UNDEFINED SYSCALL |
| | 8 | | | 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.
| + | ==== UNDEFINED INSTRUCTION/PREFETCH ABORT/DATA ABORT/UNALIGNED DATA ACCESS/UNDEFINED SYSCALL events ==== |
| + | {| class="wikitable" border="1" |
| + | ! Type |
| + | ! Field |
| + | |- |
| + | | u32 |
| + | | Fault information: Fault Address Register (for DATA ABORT and UNALIGNED DATA ACCESS), |
| + | attempted SVC ID (for UNDEFINED SYSCALL), otherwise 0 |
| + | |} |
| + | |
| + | ==== STOP POINT event ==== |
| + | {| class="wikitable" border="1" |
| + | ! Type |
| + | ! Field |
| + | |- |
| + | | u32 |
| + | | Stop point type that caused the event: 0 = svc 0xFF, 1 = breakpoint, 2 = watchpoint |
| + | |- |
| + | | u32 |
| + | | Fault information: FAR for watchpoints, 0 otherwise |
| + | |} |
| + | |
| + | ==== USER BREAK event ==== |
| + | {| class="wikitable" border="1" |
| + | ! Type |
| + | ! Field |
| + | |- |
| + | | u32 |
| + | | Break reason |
| + | |- |
| + | | u32[2] |
| + | | Info for LOAD_RO and UNLOAD_RO |
| + | |} |
| | | |
| User break types: | | User break types: |
Line 1,052: |
Line 1,103: |
| | USER | | | USER |
| | 2 | | | 2 |
| + | |- |
| + | | LOAD_RO |
| + | | 3 |
| + | |- |
| + | | UNLOAD_RO |
| + | | 4 |
| |} | | |} |
| | | |
− | === SCHEDULER/SYSCALL IN/OUT events === | + | ==== DEBUGGER BREAK event ==== |
| + | {| class="wikitable" border="1" |
| + | ! Type |
| + | ! Field |
| + | |- |
| + | | 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 === |
| | | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 1,064: |
Line 1,130: |
| |- | | |- |
| | u32 | | | u32 |
− | | Syscall (only for SYSCALL events) | + | | CPU ID (SCHEDULE events) Syscall (SYSCALL events) |
| |} | | |} |
| | | |
Line 1,099: |
Line 1,165: |
| |} | | |} |
| | | |
− | == enum DebugThreadParam == | + | == struct ThreadContext == |
| + | |
| + | Size: 0xCC bytes |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Type |
| + | ! Description |
| + | |- |
| + | | 0x0 |
| + | | CpuRegisters |
| + | | Saved CPU registers (r0-r12, sp, lr, pc, cpsr) |
| + | |- |
| + | | 0x44 |
| + | | FpuRegisters |
| + | | Saved FPU registers (d0-d15, fpscr, fpexc) |
| + | |} |
| + | |
| + | The user needs to adjust pc for exceptions that occured while in Thumb mode. |
| + | |
| + | '''Flags for svcGetDebugThreadContext/svcSetDebugThreadContext''': |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Bit |
| + | ! Description |
| + | |- |
| + | | 0 |
| + | | Get/set CPU GPRs (r0-r12) |
| + | |- |
| + | | 1 |
| + | | Get/set CPU SPRs (sp, lr, pc, cpsr) |
| + | |- |
| + | | 2 |
| + | | Get/set FPU GPRs (d0-d15 aka. f0-f31) |
| + | |- |
| + | | 3 |
| + | | Get/set FPU SPRs (fpscr, fpexc) |
| + | |} |
| + | |
| + | When setting CPSR, the following assignment is done: <code>ctx->cpsr = ctx->cpsr & 0x7F0FDFF | userCtx->cpuRegisters.cpsr & 0xF80F0200;</code>. This is to avoid obvious security issues. |
| + | |
| + | == enum DebugThreadParameter == |
| | | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 1,108: |
Line 1,217: |
| | 0 | | | 0 |
| |- | | |- |
− | | SCHEDULE | + | | SCHEDULING_MASK_LOW |
| | 1 | | | 1 |
| |- | | |- |
Line 1,148: |
Line 1,257: |
| = Interrupt Handling = | | = 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.
| + | svcBindInterrupt registers the given event or semaphore corresponding to the handle to the global [[ARM11_Interrupts#Interrupt_Table_.28New3DS.29|"interrupt table"]] for the given interrupt ID. Interrupts 0-14 and 16-31 can never be mapped regardless of the [[NCCH/Extended_Header#ARM11_Kernel_Capabilities|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). |
| | | |
− | Applications hence can wait for specific interrupts to happen by calling WaitSynchronization(N) on the event handles.
| + | 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. |
| | | |
− | It is unknown whether BindInterrupt may be used with non-event handles.
| + | 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 [[ARM11 Interrupts|this page]]. | | The set of existing ARM11 interrupts is listed on [[ARM11 Interrupts|this page]]. |
Line 1,162: |
Line 1,271: |
| | | |
| = KernelSetState = | | = KernelSetState = |
| + | KernelSetState uses the 6th [[ARM11_Interrupts#Private_Interrupts|software-generated interrupt]] for any operation involving synchronization between cores. |
| + | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
Line 1,172: |
Line 1,283: |
| | Yes | | | Yes |
| | No | | | 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. | + | | Arguments : <code>u64 firmTitleID</code> (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). |
− | 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>. | + | 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 <handler for the KernelSetState-types called via funcptr>. |
| |- | | |- |
| | 1 | | | 1 |
Line 1,183: |
Line 1,294: |
| | Yes | | | Yes |
| | Yes | | | Yes |
− | | Unknown. | + | | Powers down the GPU and syncs with Process9 (waits for <code>*(vu8 *)PXI_SYNC11</code> 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 <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>. |
| |- | | |- |
Line 1,189: |
Line 1,300: |
| | Yes | | | Yes |
| | No | | | 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. | + | | Arguments: <code>0, void* address</code> or <code>1</code> |
| + | 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. |
| |- | | |- |
| | 4 | | | 4 |
| | No | | | No |
| | Yes | | | 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. | + | | 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 | | | 5 |
| | Yes | | | Yes |
| | 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" [[NCCH/Extended_Header#ARM11_Kernel_Flags|ARM11 kernel flag]] set. Core1 threads with a priority of 0x40 without a parent process have their priority set to 0x3E. | + | | Power state change. Takes one u32 parameter. |
| | | |
− | Prior to first invoking this handler, if and only if both UNITINFO and [[Configuration_Memory#0x1FF80015|0x1FF80015]] are not 0, and if there is no [[LCD_Registers#Fill_Color|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).
| + | 0: shutdown/reboot. hangs the Arm11. Used by kernelpanic and PTM. This makes all cores enter a WFI/B infinite loop. |
− | | |
− | Before invoking this handler a second time, kernelpanic wait for the user to hold L+R+Start+Select down.
| |
| |- | | |- |
| | 6 | | | 6 |
| | Yes | | | Yes |
| | No | | | No |
− | | Debug related? | + | | Arguments: <code>u32 what, u64 val</code> |
| + | UNITINFO needs to be non-zero for <code>what</code> 1 and 2. |
| + | |
| + | If <code>what</code> is 0 or any invalid value, nothing is done. |
| + | |
| + | If it is 1, <code>val != 0</code> 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, <specified stack> - 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|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|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. |
| |- | | |- |
| | 7 | | | 7 |
| | Yes | | | Yes |
| | No | | | 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. | + | | This 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 <handler for the KernelSetState-types called via funcptr>. | | 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>. |
| |- | | |- |
Line 1,219: |
Line 1,338: |
| | Yes | | | Yes |
| | No | | | 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. | + | | Hangs the Arm9, using a code path similar to the one used on firmlaunch. Used by PTM on shutdown/reboot. |
| |- | | |- |
| | 9 | | | 9 |
| | Yes, implemented at some point after system-version v4.5. | | | Yes, implemented at some point after system-version v4.5. |
| | ? | | | ? |
− | | Unknown | + | | Argumens: <code>u64 titleID</code>. |
| + | 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 <code>true</code>. |
| + | Used by NS conditionally based on the contents of the [[NS CFA]]. |
| |- | | |- |
| | 10 | | | 10 |
| | Yes | | | 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 [[PDN_Registers|register]] for the flags listed [[NCCH/Extended_Header#Flag1|here]], among other code which uses the MPCore private memory region registers. | + | | Arguments: <code>u32 config</code> |
| + | 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. 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 [[PDN_Registers|register]] for the flags listed [[NCCH/Extended_Header#Flag1|here]], among other code which uses the MPCore private memory region registers. |
| |} | | |} |
| | | |
Line 1,283: |
Line 1,405: |
| ! Description | | ! Description |
| |- | | |- |
− | | 9-19 | + | | 0 |
| + | | |
| + | | Returns 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. |
| + | |- |
| + | | 1 |
| + | | |
| + | | Returns the amount of <related unused field> + total supervisor-mode stack size + page-rounded size of the external handle table |
| + | |- |
| + | | 2 |
| + | | |
| + | | Returns 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 |
| + | |- |
| + | | 3 |
| + | | |
| + | | Returns the amount of <related unused field> + total supervisor-mode stack size + page-rounded size of the external handle table |
| + | |- |
| + | | 4 |
| + | | |
| + | | Returns the amount of handles in use by the process. |
| + | |- |
| + | | 5 |
| + | | |
| + | | Returns the highest count of handles that have been open at once by the process |
| + | |- |
| + | | 6 |
| + | | |
| + | | Returns <code>*(u32*)(KProcess+0x234)</code> which is always 0 |
| + | |- |
| + | | 7 |
| + | | |
| + | | Returns the number of threads of the process |
| + | |- |
| + | | 8 |
| + | | |
| + | | Returns the maximum number of threads which can be opened by this process (always 0) |
| + | |- |
| + | | 9-18 |
| | [[8.0.0-18]] | | | [[8.0.0-18]] |
| | This only returns error 0xD8E007ED. | | | This only returns error 0xD8E007ED. |
| + | |- |
| + | | 19 |
| + | | Stub: [[8.0.0-18]]. Implementation: [[11.3.0-36|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. |
| |- | | |- |
| | 20 | | | 20 |
Line 1,291: |
Line 1,453: |
| | 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. | | | 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 | + | | 21 |
− | | [[8.0.0-18]] | + | | [[8.0.0-18]]. N3DS only. |
− | | This only returns error 0xE0E01BF4. | + | | 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 |
| + | |- |
| + | | 22 |
| + | | [[8.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 |
| + | |- |
| + | | 23 |
| + | | [[8.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 |
| |} | | |} |
| | | |
Line 1,306: |
Line 1,476: |
| |- | | |- |
| | 1 | | | 1 |
− | | Get internal refcount-1 for kernel object (u32), and also a boolean if the refcount-1 is negative (u32). | + | | Get internal refcount for kernel object (not counting the one this SVC adds internally to operate), sign-extended to 64 bits. |
| + | |- |
| + | | 2 |
| + | | Unimplemented, returns an uninitialized u64 variable (corresponding to r5-r6, which were not altered outside of userland). |
| |- | | |- |
| | 0x32107 | | | 0x32107 |
Line 1,314: |
Line 1,487: |
| = svc7B Backdoor = | | = 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). | | 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-36|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 "<nowiki>0x100 | <val></nowiki>" to [[CONFIG11_Registers#CFG11_GPUPROT|pdnregbase+0x140]], where val depends on input_flag and a kernel state field for [[Configuration_Memory|APPMEMTYPE]]. |
| + | |
| + | When input_flag is 0x1 val is fixed: |
| + | * Old3DS: 0x3 |
| + | * New3DS: 0x460 |
| + | |
| + | Otherwise, val depends on the kernel APPMEMTYPE state field: |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! FIRM |
| + | ! [[Memory_layout|APPMEMTYPE]] |
| + | ! val |
| + | |- |
| + | | Old3DS |
| + | | 2 |
| + | | 0x3 |
| + | |- |
| + | | Old3DS |
| + | | 3 |
| + | | 0x5 |
| + | |- |
| + | | Old3DS |
| + | | 4 |
| + | | 0x6 |
| + | |- |
| + | | Old3DS |
| + | | Non-value-{2/3/4} |
| + | | 0x7 |
| + | |- |
| + | | New3DS |
| + | | 7 |
| + | | 0x490 |
| + | |- |
| + | | New3DS |
| + | | Non-value-7 |
| + | | 0x4F0 |
| + | |} |
| + | |
| + | 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 = | | = Kernel error-codes = |