Difference between revisions of "SceExcpmgr"

From Vita Development Wiki
Jump to navigation Jump to search
Line 1: Line 1:
SceExcpmgr is a kernel module that sets up exception handling. A version exists in both worlds. In non-secure world, after the kernel is booted up, the exception handlers pointed to by VBAR all jump into code in this module.
+
SceExcpmgr is a kernel module that sets up exception handling. A version exists in both non-secure and secure worlds. In non-secure world, after the kernel is booted up, the exception handlers pointed to by VBAR all jump into code in this module.
  
 
== Module ==
 
== Module ==
Line 8: Line 8:
 
! Version !! World !! Privilege
 
! Version !! World !! Privilege
 
|-
 
|-
| 1.69-3.65 || Non-secure || Kernel
+
| 0.931-3.65 || Non-secure || Kernel
 
|-
 
|-
| 1.69 || Secure || Kernel
+
| 0.931-1.69 || Secure || Kernel
 
|}
 
|}
  
Line 21: Line 21:
 
! Version !! Name !! World !! Visibility !! NID
 
! Version !! Name !! World !! Visibility !! NID
 
|-
 
|-
| 1.69-3.60 || [[SceExcpmgr#SceExcpmgrForKernel|SceExcpmgrForKernel]] || Non-secure || Kernel || 0x4CA0FDD5
+
| 0.931-3.60 || [[SceExcpmgr#SceExcpmgrForKernel|SceExcpmgrForKernel]] || Non-secure || Kernel || 0x4CA0FDD5
 
|-
 
|-
 
| 3.65 || [[SceExcpmgr#SceExcpmgrForKernel|SceExcpmgrForKernel]] || Non-secure || Kernel || 0x1496A5B5
 
| 3.65 || [[SceExcpmgr#SceExcpmgrForKernel|SceExcpmgrForKernel]] || Non-secure || Kernel || 0x1496A5B5
 
|-
 
|-
| 1.69-1.80 || [[SceExcpmgr#SceExcpmgrForTZS|SceExcpmgrForTZS]]|| Secure || Kernel || 0x8F526F35
+
| 0.931-1.80 || [[SceExcpmgr#SceExcpmgrForTZS|SceExcpmgrForTZS]] || Secure || Kernel || 0x8F526F35
 
|}
 
|}
  
 
== Types ==
 
== Types ==
 +
 
<source lang="C">
 
<source lang="C">
//All data in this structure are per-core (field_name[0] belongs to CPU0, field_name[1] to CPU1, etc)
+
// All data in this structure are per-core (field_name[0] belongs to CPU0, field_name[1] to CPU1, etc)
 
typedef struct _SceExcpmgrData {
 
typedef struct _SceExcpmgrData {
     //Incremented by the first exception handler, must be 1 when then decremented before returning from an exception.
+
     // Incremented by the first exception handler, must be 1 when then decremented before returning from an exception.
     //If not, raise a nested exception kpanic.
+
     // If not, raise a nested exception kernel panic.
     int nestedExceptionCount[4];
+
     SceUInt32 nestedExceptionCount[4];
     int unused[4]; //Seemingly unused
+
     int unused[4]; // Seemingly unused
     void *ExcpStackTop[4]; //Stack size is 0x1000
+
     void *ExcpStackTop[4]; // Stack size is 0x1000
 
     void *ExcpStackBottom[4];
 
     void *ExcpStackBottom[4];
 
} SceExcpmgrData;
 
} SceExcpmgrData;
  
//Exception handlers' prototype
+
// Exception handlers' prototype
 
typedef void(SceExcpmgrExceptionHandler)(SceExcpmgrExceptionContext* context, SceExcpmgrExceptionHandlingCode code);
 
typedef void(SceExcpmgrExceptionHandler)(SceExcpmgrExceptionContext* context, SceExcpmgrExceptionHandlingCode code);
  
//Parameter for the RegisterHandler/ReleaseHandler functions
+
// Parameter for the RegisterHandler/ReleaseHandler functions
 
typedef struct __attribute__((aligned(4))) _SceExcpmgrExceptionHandlerContext {
 
typedef struct __attribute__((aligned(4))) _SceExcpmgrExceptionHandlerContext {
     struct _SceExcpmgrExceptionHandlerContext *next; //Points to the next handler in the chain
+
     struct _SceExcpmgrExceptionHandlerContext *next; // Pointer to the next handler in the chain
     uint32_t must_be_zero; //Unused - probably required for alignement reasons
+
     SceUInt32 must_be_zero; // Unused - probably required for alignement reasons
     //ARM code of the exception handler goes here - exception handlers cannot be written in Thumb.
+
     // ARM code of the exception handler goes here. Exception handlers cannot be written in Thumb.
     //This must be the start of a SceExcpmgrExceptionHandler function.
+
     // This must be the start of a SceExcpmgrExceptionHandler function.
 
} SceExcpmgrExceptionHandlerContext;
 
} SceExcpmgrExceptionHandlerContext;
  
 
+
// Structure that holds the CPU's state at the moment when an exception was raised
//Structure that holds the CPU's state at the moment when an exception was raised
+
typedef struct _SceExcpmgrExceptionContext { // Size is 0x400 on FW 3.60
typedef struct _SceExcpmgrExceptionContext { //Size is 0x400 on FW 3.60
+
     SceUInt32 r0;
     uint32_t r0;
+
     SceUInt32 r1;
     uint32_t r1;
+
     SceUInt32 r2;
     uint32_t r2;
+
     SceUInt32 r3;
     uint32_t r3;
+
     SceUInt32 r4;
     uint32_t r4;
+
     SceUInt32 r5;
     uint32_t r5;
+
     SceUInt32 r6;
     uint32_t r6;
+
     SceUInt32 r7;
     uint32_t r7;
+
     SceUInt32 r8;
     uint32_t r8;
+
     SceUInt32 r9;
     uint32_t r9;
+
     SceUInt32 r10;
     uint32_t r10;
+
     SceUInt32 r11;
     uint32_t r11;
+
     SceUInt32 r12;
     uint32_t r12;
+
     SceUInt32 sp;
     uint32_t sp;
+
     SceUInt32 lr;
     uint32_t lr;
+
     void *address_of_faulting_instruction;
     uint32_t address_of_faulting_instruction;
+
     SceExcpmgrExceptionCode excode;
     uint32_t exception_code; //Set to 1 in UNDEFINED handler, 3 in PABT handler, 4 in DABT handler
+
     SceUInt32 SPSR;
     uint32_t SPSR;
+
     SceUInt32 CPACR;
     uint32_t CPACR;
+
     SceUInt32 FPSCR;
     uint32_t FPSCR;
+
     SceUInt32 FPEXC;
     uint32_t FPEXC;
+
     SceUInt32 CONTEXTIDR;
     uint32_t CONTEXTIDR;
+
     SceUInt32 TPIDRURW;
     uint32_t TPIDRURW;
+
     SceUInt32 TPIDRURO;
     uint32_t TPIDRURO;
+
     SceUInt32 TPIDRPRW;
     uint32_t TPIDRPRW;
+
     SceUInt32 TTBR1;
     uint32_t TTBR1;
+
     SceUInt32 unused_0x68; // Seemingly not populated
     uint32_t unused68; //Seemingly not populated
+
     SceUInt32 DACR;
     uint32_t DACR;
+
     SceUInt32 DFSR;
     uint32_t DFSR;
+
     SceUInt32 IFSR;
     uint32_t IFSR;
+
     SceUInt32 DFAR;
     uint32_t DFAR;
+
     SceUInt32 IFAR;
     uint32_t IFAR;
+
     SceUInt32 PAR;
     uint32_t PAR;
+
     SceUInt32 TEEHBR;
     uint32_t TEEHBR;
+
     SceUInt32 PMCR;
     uint32_t PMCR;
+
     SceUInt32 PMCNTENSET;
     uint32_t PMCNTENSET;
+
     SceUInt32 PMCNTENSET_2; // Second copy of PMCNTENSET
     uint32_t PMCNTENSET_2; //Second copy of PMCNTENSET
+
     SceUInt32 PMSELR;
     uint32_t PMSELR;
+
     SceUInt32 PMCCNTR;
     uint32_t PMCCNTR;
+
     SceUInt32 PMUSERENR;
     uint32_t PMUSERENR;
+
     SceUInt32 PMXEVTYPER0;
     uint32_t PMXEVTYPER0;
+
     SceUInt32 PMXEVCNTR0;
     uint32_t PMXEVCNTR0;
+
     SceUInt32 PMXEVTYPER1;
     uint32_t PMXEVTYPER1;
+
     SceUInt32 PMXEVCNTR1;
     uint32_t PMXEVCNTR1;
+
     SceUInt32 PMXEVTYPER2;
     uint32_t PMXEVTYPER2;
+
     SceUInt32 PMXEVCNTR2;
     uint32_t PMXEVCNTR2;
+
     SceUInt32 PMXEVTYPER3;
     uint32_t PMXEVTYPER3;
+
     SceUInt32 PMXEVCNTR3;
     uint32_t PMXEVCNTR3;
+
     SceUInt32 PMXEVTYPER4;
     uint32_t PMXEVTYPER4;
+
     SceUInt32 PMXEVCNTR4;
     uint32_t PMXEVCNTR4;
+
     SceUInt32 PMXEVTYPER5;
     uint32_t PMXEVTYPER5;
+
     SceUInt32 PMXEVCNTR5;
     uint32_t PMXEVCNTR5;
+
     SceUInt32 unused_0xD0;
     uint32_t unusedD0;
+
     SceUInt32 unk_0xD4;        // Comes from SceVfpIntRegs[localCore].field_0x100
     uint32_t unkD4;        //Comes from SceVfpIntRegs[localCore].field_0x100
+
     SceUInt32 DBGSCRext;
     uint32_t DBGSCRext;
+
     SceUInt32 unusedDC[9];  // Seemingly not populated
     uint32_t unusedDC[9];  //Seemingly not populated
+
     SceUInt64 VFP_registers[32]; // Content of registers d0-d31
     uint64_t VFP_registers[32]; //Content of registers d0-d31
+
     SceUInt32 unk_0x200[128];      // Comes from SceVfpIntRegs[localCore].field_0x200
     uint32_t unk200[128];      //Comes from SceVfpIntRegs[localCore].field_0x200
 
 
} SceExcpmgrExceptionContext;
 
} SceExcpmgrExceptionContext;
  
 
typedef enum {
 
typedef enum {
     //For all codes != 3, calling the last handler in the chain should call sceKernelSysrootReturnFromExcpToThreadForKernel and return properly
+
     // For all codes != 3, calling the last handler in the chain should call sceKernelSysrootReturnFromExcpToThreadForKernel and return properly
 
     SCE_EXCPMGR_EXCEPTION_HANDLING_CODE_0 = (int16_t)0,
 
     SCE_EXCPMGR_EXCEPTION_HANDLING_CODE_0 = (int16_t)0,
 
     SCE_EXCPMGR_EXCEPTION_HANDLING_CODE_1 = (int16_t)1,
 
     SCE_EXCPMGR_EXCEPTION_HANDLING_CODE_1 = (int16_t)1,
 
     SCE_EXCPMGR_EXCEPTION_HANDLING_CODE_2 = (int16_t)2,
 
     SCE_EXCPMGR_EXCEPTION_HANDLING_CODE_2 = (int16_t)2,
     //If this code reaches the last handler in the chain, calls SceDebugForKernel_082B8D6A then loops infinitely
+
     // If this code reaches the last handler in the chain, calls SceDebugForKernel_082B8D6A then loops infinitely
 
     SCE_EXCPMGR_EXCEPTION_NOT_HANDLED_FATAL = (int16_t)3,
 
     SCE_EXCPMGR_EXCEPTION_NOT_HANDLED_FATAL = (int16_t)3,
 
     SCE_EXCPMGR_EXCEPTION_HANDLING_CODE_4 = (int16_t)4
 
     SCE_EXCPMGR_EXCEPTION_HANDLING_CODE_4 = (int16_t)4
 
} SceExcpmgrExceptionHandlingCode;
 
} SceExcpmgrExceptionHandlingCode;
 +
 +
typedef enum {
 +
    SCE_EXCPMGR_EXCEPTION_CODE_RESET = 0, // Reset
 +
    SCE_EXCPMGR_EXCEPTION_CODE_UNDEF = 1, // Undefined Instruction
 +
    SCE_EXCPMGR_EXCEPTION_CODE_SVC = 2, // Supervisor Call
 +
    SCE_EXCPMGR_EXCEPTION_CODE_PABT = 3, // Prefetch Abort
 +
    SCE_EXCPMGR_EXCEPTION_CODE_DABT = 4, // Data Abort
 +
    SCE_EXCPMGR_EXCEPTION_CODE_RESERVED = 5, // Reserved
 +
    SCE_EXCPMGR_EXCEPTION_CODE_IRQ = 6, // Interrupt
 +
    SCE_EXCPMGR_EXCEPTION_CODE_FIQ = 7, // Fast Interrupt
 +
} SceExcpmgrExceptionCode;
 
</source>
 
</source>
  
 
== To find ==
 
== To find ==
 +
 
Functions with the following names may exist in SceExcpmgr :
 
Functions with the following names may exist in SceExcpmgr :
 
     sceKernelDefaultHandlerCfunc
 
     sceKernelDefaultHandlerCfunc
Line 149: Line 161:
 
Temp name was sceExcpmgrRegisterHandlerForKernel.
 
Temp name was sceExcpmgrRegisterHandlerForKernel.
  
Installs an exception handler.
+
Installs an exception handler. The exception handler must be ARM code, and not Thumb code. Allowed <code>priority</code> values are from 0 (most important) to 7 (least important), including them. Specifying priority 0 will install the handler directly in VBAR, which means its code will run directly when an exception raises (and as such needs to build the exception context itself).
  
<source lang="C">int sceKernelRegisterExceptionHandlerForKernel(int excpcode, int priority, SceExcpmgrExceptionHandlerContext *handler);</source>
+
The syscall handler in FW 1.50 is SceExcpmgr_func_0x81000E40.
 
 
The exception handler must be ARM code, and not Thumb code.
 
Allowed <code>priority</code> values are from 0 (most important) to 7 (least important), including them.
 
Specifying priority 0 will install the handler directly in VBAR, which means its code will run directly when an exception raises (and as such needs to build the exception context itself).
 
 
 
<code>excpcode</code> can be:
 
* Reset (RESET): 0
 
* Undefined Instruction (UNDEF): 1
 
* Supervisor Call (SVC): 2
 
* Prefetch Abort (PABT): 3
 
* Data Abort (DABT): 4
 
* Reserved (RESERVED): 5
 
* Interrupt (IRQ): 6
 
* Fast Interrupt (FIQ): 7
 
  
The syscall handler in FW 1.50 is SceExcpmgr_func_0x81000E40.
+
<source lang="C">int sceKernelRegisterExceptionHandlerForKernel(SceExcpmgrExceptionCode excode, SceUInt32 priority, SceExcpmgrExceptionHandlerContext *handler);</source>
  
 
=== sceKernelRegisterDefaultExceptionHandlerForKernel ===
 
=== sceKernelRegisterDefaultExceptionHandlerForKernel ===
Line 179: Line 177:
 
|}
 
|}
  
Installs an exception handler for all exceptions.
+
Installs an exception handler for all exceptions. If no exception handler is already installed for an exception, the handler will be installed in the VBAR. <code>handler</code> must be the same parameter that would be passed to [[SceExcpmgr#sceKernelRegisterExceptionHandlerForKernel|sceKernelRegisterExceptionHandlerForKernel]].
If no exception handler is already installed for an exception, the handler will be installed in the VBAR.
+
 
<code>handler</code> must be the same parameter that would be passed to [[SceExcpmgr#sceKernelRegisterExceptionHandlerForKernel|sceKernelRegisterExceptionHandlerForKernel]].
+
<source lang="C">int sceKernelRegisterDefaultExceptionHandlerForKernel(SceExcpmgrExceptionHandlerContext *handler);</source>
<source lang="C">SceInt32 sceKernelRegisterDefaultExceptionHandlerForKernel(SceExcpmgrExceptionHandlerContext *handler);</source>
 
  
 
=== sceKernelReleaseExceptionHandlerForKernel ===
 
=== sceKernelReleaseExceptionHandlerForKernel ===
Line 195: Line 192:
  
 
Pass the same arguments as provided to [[SceExcpmgr#sceKernelRegisterExceptionHandlerForKernel|sceKernelRegisterExceptionHandlerForKernel]].
 
Pass the same arguments as provided to [[SceExcpmgr#sceKernelRegisterExceptionHandlerForKernel|sceKernelRegisterExceptionHandlerForKernel]].
<source lang="C">int sceKernelReleaseExceptionHandlerForKernel (int excpcode, SceExcpmgrExceptionHandlerContext *handler);</source>
+
 
 +
<source lang="C">int sceKernelReleaseExceptionHandlerForKernel(SceExcpmgrExceptionCode excode, SceExcpmgrExceptionHandlerContext *handler);</source>
  
 
=== sceKernelReleaseDefaultExceptionHandlerForKernel ===
 
=== sceKernelReleaseDefaultExceptionHandlerForKernel ===
Line 215: Line 213:
 
|}
 
|}
  
Logs some information about the CPU state and backtrace then returns.
+
Logs some information about the CPU state and backtrace then returns. Freezes with an infinite loop if currentHandlerIndex is superior to 1.
Freezes on infinite loop if currentHandlerIndex is superior to 1.
+
 
<source lang="C">void sceKernelInitialHandlerDebugUndefCfuncForKernel (SceExcpmgrExceptionContext* context);</source>
+
<source lang="C">void sceKernelInitialHandlerDebugUndefCfuncForKernel(SceExcpmgrExceptionContext* context);</source>
  
 
=== sceKernelInitialHandlerDebugPabtCfuncForKernel ===
 
=== sceKernelInitialHandlerDebugPabtCfuncForKernel ===
Line 227: Line 225:
 
|}
 
|}
  
Logs some information about the CPU state and backtrace then returns.
+
Logs some information about the CPU state and backtrace then returns. Freezes with an infinite loop if currentHandlerIndex is superior to 1.
Freezes on infinite loop if currentHandlerIndex is superior to 1.
+
 
 
<source lang="C">void sceKernelInitialHandlerDebugPabtCfuncForKernel(SceExcpmgrExceptionContext* context);</source>
 
<source lang="C">void sceKernelInitialHandlerDebugPabtCfuncForKernel(SceExcpmgrExceptionContext* context);</source>
  
Line 239: Line 237:
 
|}
 
|}
  
Logs some information about the CPU state and backtrace then returns.
+
Logs some information about the CPU state and backtrace then returns. Freezes with an infinite loop if currentHandlerIndex is superior to 1.
Freezes on infinite loop if currentHandlerIndex is superior to 1.
+
 
 
<source lang="C">void sceKernelInitialHandlerDebugDabtCfuncForKernel(SceExcpmgrExceptionContext* context);</source>
 
<source lang="C">void sceKernelInitialHandlerDebugDabtCfuncForKernel(SceExcpmgrExceptionContext* context);</source>
  
Line 264: Line 262:
  
 
Returns a pointer to the handler previously registered by [[SceExcpmgr#sceKernelRegisterDefaultExceptionHandlerForKernel|sceKernelRegisterDefaultExceptionHandlerForKernel]].
 
Returns a pointer to the handler previously registered by [[SceExcpmgr#sceKernelRegisterDefaultExceptionHandlerForKernel|sceKernelRegisterDefaultExceptionHandlerForKernel]].
 +
 
<source lang="C">SceExcpmgrExceptionHandlerContext *sceKernelDefaultHandlerResetCfuncForKernel(void);</source>
 
<source lang="C">SceExcpmgrExceptionHandlerContext *sceKernelDefaultHandlerResetCfuncForKernel(void);</source>
  
Line 277: Line 276:
  
 
Returns the exception stack bottom for specified CPU core. The stack bottom is the highest address of the stack.
 
Returns the exception stack bottom for specified CPU core. The stack bottom is the highest address of the stack.
 +
 +
Reimplementation code:
 
<source lang="C">
 
<source lang="C">
 
void* sceKernelGetExcpStackBottomForKernel(int coreNum) {
 
void* sceKernelGetExcpStackBottomForKernel(int coreNum) {
Line 282: Line 283:
 
}
 
}
 
</source>
 
</source>
 +
 +
<source lang="C">void* sceKernelGetExcpStackBottomForKernel(int coreNum);</source>
  
 
=== sceExcpmgrGetDataForKernel ===
 
=== sceExcpmgrGetDataForKernel ===
Line 287: Line 290:
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 +
|-
 +
| 0.931-0.990 || not present
 
|-
 
|-
 
| 3.60 || 0x08CB30E6
 
| 3.60 || 0x08CB30E6
Line 292: Line 297:
  
 
Get exception data pointer (for use by handlers).
 
Get exception data pointer (for use by handlers).
 +
 
<source lang="C">SceExcpmgrData* sceExcpmgrGetDataForKernel(void);</source>
 
<source lang="C">SceExcpmgrData* sceExcpmgrGetDataForKernel(void);</source>
  
Line 298: Line 304:
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 +
|-
 +
| 0.931-0.990 || not present
 
|-
 
|-
 
| 3.60 || 0x3AE9AEE1
 
| 3.60 || 0x3AE9AEE1
Line 303: Line 311:
  
 
Sets a callback function ran by the default UNDEF exception handler before calling the next handler in the chain.
 
Sets a callback function ran by the default UNDEF exception handler before calling the next handler in the chain.
 +
 
<source lang="C">
 
<source lang="C">
//NOTE : context passed to callback lacks VFP registers
+
// NOTE : context passed to callback lacks VFP registers
 
void SceExcpmgrForKernel_3AE9AEE1(void (*callback)(SceExcpmgrExceptionContext*));
 
void SceExcpmgrForKernel_3AE9AEE1(void (*callback)(SceExcpmgrExceptionContext*));
 
</source>
 
</source>
Line 313: Line 322:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 0.990 - 3.60 || 0x4FF90618
+
| 0.990-3.60 || 0x4FF90618
 
|}
 
|}
  
 
Sets whether or not watchpoint control debug registers (DBGWCR0-DBGWCR4) should be left untouched by the UNDEF/DABT/PABT handlers. Registers are otherwise zero'ed out.
 
Sets whether or not watchpoint control debug registers (DBGWCR0-DBGWCR4) should be left untouched by the UNDEF/DABT/PABT handlers. Registers are otherwise zero'ed out.
 +
 
<source lang="C">void SceExcpmgrForKernel_4FF90618(SceBool keepRegisters);</source>
 
<source lang="C">void SceExcpmgrForKernel_4FF90618(SceBool keepRegisters);</source>
  
Line 323: Line 333:
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 +
|-
 +
| 0.931-0.990 || not present
 
|-
 
|-
 
| 3.60 || 0x7ADF11DB
 
| 3.60 || 0x7ADF11DB
Line 328: Line 340:
  
 
Sets a callback function ran by the default DABT exception handler before calling the next handler in the chain.
 
Sets a callback function ran by the default DABT exception handler before calling the next handler in the chain.
 +
 
<source lang="C">
 
<source lang="C">
//NOTE : context passed to callback lacks VFP registers
+
// NOTE : context passed to callback lacks VFP registers
 
void SceExcpmgrForKernel_7ADF11DB(void (*callback)(SceExcpmgrExceptionContext*));
 
void SceExcpmgrForKernel_7ADF11DB(void (*callback)(SceExcpmgrExceptionContext*));
 
</source>
 
</source>
Line 337: Line 350:
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 +
|-
 +
| 0.931-0.990 || not present
 
|-
 
|-
 
| 3.60 || 0x8D223205
 
| 3.60 || 0x8D223205
Line 344: Line 359:
  
 
Sets a callback function ran by the default PABT exception handler before calling the next handler in the chain.
 
Sets a callback function ran by the default PABT exception handler before calling the next handler in the chain.
 +
 
<source lang="C">
 
<source lang="C">
//NOTE : context passed to callback lacks VFP registers
+
// NOTE : context passed to callback lacks VFP registers
 
void SceExcpmgrForKernel_8D223205(void (*callback)(SceExcpmgrExceptionContext*));
 
void SceExcpmgrForKernel_8D223205(void (*callback)(SceExcpmgrExceptionContext*));
 
</source>
 
</source>
Line 365: Line 381:
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 +
|-
 +
| 0.931-0.990 || not present
 
|-
 
|-
 
| 3.60 || 0xC45C0D3D
 
| 3.60 || 0xC45C0D3D
Line 370: Line 388:
  
 
Set the "memory access error range". If a DABT exception occurs and PC is located in the range (inclusive) provided by this function, a subroutine of the default DABT handler will return <code>SCE_KERNEL_ERROR_INVALID_MEMORY_ACCESS</code> which in turn makes the handler return to the instruction right after the faulting one.
 
Set the "memory access error range". If a DABT exception occurs and PC is located in the range (inclusive) provided by this function, a subroutine of the default DABT handler will return <code>SCE_KERNEL_ERROR_INVALID_MEMORY_ACCESS</code> which in turn makes the handler return to the instruction right after the faulting one.
 +
 
<source lang="C">void SceExcpmgrForKernel_C45C0D3D(uintptr_t rangeStart, uintptr_t rangeStop);</source>
 
<source lang="C">void SceExcpmgrForKernel_C45C0D3D(uintptr_t rangeStart, uintptr_t rangeStop);</source>
  
Line 377: Line 396:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xD464A9A7
+
| 0.990-3.60 || 0xD464A9A7
 
|}
 
|}
  
 
Returns the current nested exception count, or 0 if current TPIDRPRW is non-NULL.
 
Returns the current nested exception count, or 0 if current TPIDRPRW is non-NULL.
 +
 
<source lang="C">int SceExcpmgrForKernel_D464A9A7(void);</source>
 
<source lang="C">int SceExcpmgrForKernel_D464A9A7(void);</source>
  
Line 392: Line 412:
 
| 0.931-1.80 || 0x07A5790B
 
| 0.931-1.80 || 0x07A5790B
 
|}
 
|}
 +
 +
<source lang="C">void *SceExcpmgrForTZS_get_default_excp_handler(void);</source>
  
 
=== sceKernelReleaseExceptionHandlerForTZS ===
 
=== sceKernelReleaseExceptionHandlerForTZS ===
Line 400: Line 422:
 
| 0.931-1.80 || 0x166C9362
 
| 0.931-1.80 || 0x166C9362
 
|}
 
|}
 +
 +
<source lang="C">int sceKernelReleaseExceptionHandlerForTZS(SceExcpmgrExceptionCode excode, SceExcpmgrExceptionHandlerContext *handler)</source>
  
 
=== sceKernelReleaseDefaultExceptionHandlerForTZS ===
 
=== sceKernelReleaseDefaultExceptionHandlerForTZS ===
Line 408: Line 432:
 
| 0.931-1.80 || 0x6282E52C
 
| 0.931-1.80 || 0x6282E52C
 
|}
 
|}
 +
 +
<source lang="C">int sceKernelReleaseDefaultExceptionHandlerForTZS(SceExcpmgrExceptionHandlerContext *handler)</source>
  
 
=== sceKernelRegisterDefaultExceptionHandlerForTZS ===
 
=== sceKernelRegisterDefaultExceptionHandlerForTZS ===
Line 416: Line 442:
 
| 0.931-1.80 || 0xA0434735
 
| 0.931-1.80 || 0xA0434735
 
|}
 
|}
 +
 +
<source lang="C">int sceKernelRegisterDefaultExceptionHandlerForTZS(SceExcpmgrExceptionHandlerContext *handler)</source>
  
 
=== sceKernelRegisterMonitorEntryForTZS ===
 
=== sceKernelRegisterMonitorEntryForTZS ===
Line 425: Line 453:
 
|}
 
|}
  
<source lang="C">
+
<source lang="C">int sceKernelRegisterMonitorEntryForTZS(SceExcpmgrExceptionCode excode, SceExcpmgrExceptionHandlerContext *handler);</source>
// some_id must be in the 0-7 range
 
int sceKernelRegisterMonitorEntryForTZS(int some_id, void *pParam);
 
</source>
 
  
 
=== sceKernelRegisterExceptionHandlerForTZS ===
 
=== sceKernelRegisterExceptionHandlerForTZS ===
Line 437: Line 462:
 
| 0.931-1.80 || 0xDD4C680D
 
| 0.931-1.80 || 0xDD4C680D
 
|}
 
|}
 +
 +
<source lang="C">int sceKernelRegisterExceptionHandlerForTZS(SceExcpmgrExceptionCode excode, SceUInt32 priority, SceExcpmgrExceptionHandlerContext *handler);</source>
  
 
== Exceptions ==
 
== Exceptions ==
Line 501: Line 528:
 
|}
 
|}
  
The SMC interface is very similar to SVC interface. The SMC handler and MVBAR is set up in [[Secure World]] by [[#SceExcpmgrForTZS|SceExcpmgrForTZS]].
+
The SMC interface is very similar to the SVC interface. The SMC handler and MVBAR is set up in [[Secure World]] by [[#SceExcpmgrForTZS|SceExcpmgrForTZS]].
  
 
0x0 - 0xFF are fast service calls. 0x100 - 0xFFF are normal service calls ran with IRQs masked.
 
0x0 - 0xFF are fast service calls. 0x100 - 0xFFF are normal service calls ran with IRQs masked.
Line 761: Line 788:
 
=== Aborts ===
 
=== Aborts ===
  
On development units, data and prefetch aborts can handle BKPT instruction for software breakpoints. [[SceDebug]] uses this to handle usermode breakpoints. There is no built-in support for BKPT in kernel code.
+
On development units, data and prefetch aborts can handle <code>BKPT</code> instruction for software breakpoints. [[SceDebug]] uses this to handle usermode breakpoints. There is no built-in support for <code>BKPT</code> in kernel code.
  
 
[[SceSysmem]] uses data aborts with the <code>LDRT</code> and <code>STRT</code> instructions to implement user pointer checking. When LDRT/STRT throws a MMU data exception because of an invalid access and the exception came from [[SceSysmem#sceKernelCopyFromUserForDriver]] or [[SceSysmem#sceKernelCopyToUserForDriver]] or related functions, the data abort handler will resume execution.
 
[[SceSysmem]] uses data aborts with the <code>LDRT</code> and <code>STRT</code> instructions to implement user pointer checking. When LDRT/STRT throws a MMU data exception because of an invalid access and the exception came from [[SceSysmem#sceKernelCopyFromUserForDriver]] or [[SceSysmem#sceKernelCopyToUserForDriver]] or related functions, the data abort handler will resume execution.

Revision as of 00:27, 31 December 2021

SceExcpmgr is a kernel module that sets up exception handling. A version exists in both non-secure and secure worlds. In non-secure world, after the kernel is booted up, the exception handlers pointed to by VBAR all jump into code in this module.

Module

This module exists in both non-secure and secure world. The non-secure world SELF can be found in os0:kd/excpmgr.skprx.

Version World Privilege
0.931-3.65 Non-secure Kernel
0.931-1.69 Secure Kernel

Libraries

This module only exports kernel libraries.

Known NIDs

Version Name World Visibility NID
0.931-3.60 SceExcpmgrForKernel Non-secure Kernel 0x4CA0FDD5
3.65 SceExcpmgrForKernel Non-secure Kernel 0x1496A5B5
0.931-1.80 SceExcpmgrForTZS Secure Kernel 0x8F526F35

Types

// All data in this structure are per-core (field_name[0] belongs to CPU0, field_name[1] to CPU1, etc)
typedef struct _SceExcpmgrData {
    // Incremented by the first exception handler, must be 1 when then decremented before returning from an exception.
    // If not, raise a nested exception kernel panic.
    SceUInt32 nestedExceptionCount[4];
    int unused[4]; // Seemingly unused
    void *ExcpStackTop[4]; // Stack size is 0x1000
    void *ExcpStackBottom[4];
} SceExcpmgrData;

// Exception handlers' prototype
typedef void(SceExcpmgrExceptionHandler)(SceExcpmgrExceptionContext* context, SceExcpmgrExceptionHandlingCode code);

// Parameter for the RegisterHandler/ReleaseHandler functions
typedef struct __attribute__((aligned(4))) _SceExcpmgrExceptionHandlerContext {
    struct _SceExcpmgrExceptionHandlerContext *next; // Pointer to the next handler in the chain
    SceUInt32 must_be_zero; // Unused - probably required for alignement reasons
    // ARM code of the exception handler goes here. Exception handlers cannot be written in Thumb.
    // This must be the start of a SceExcpmgrExceptionHandler function.
} SceExcpmgrExceptionHandlerContext;

// Structure that holds the CPU's state at the moment when an exception was raised
typedef struct _SceExcpmgrExceptionContext { // Size is 0x400 on FW 3.60
    SceUInt32 r0;
    SceUInt32 r1;
    SceUInt32 r2;
    SceUInt32 r3;
    SceUInt32 r4;
    SceUInt32 r5;
    SceUInt32 r6;
    SceUInt32 r7;
    SceUInt32 r8;
    SceUInt32 r9;
    SceUInt32 r10;
    SceUInt32 r11;
    SceUInt32 r12;
    SceUInt32 sp;
    SceUInt32 lr;
    void *address_of_faulting_instruction;
    SceExcpmgrExceptionCode excode;
    SceUInt32 SPSR;
    SceUInt32 CPACR;
    SceUInt32 FPSCR;
    SceUInt32 FPEXC;
    SceUInt32 CONTEXTIDR;
    SceUInt32 TPIDRURW;
    SceUInt32 TPIDRURO;
    SceUInt32 TPIDRPRW;
    SceUInt32 TTBR1;
    SceUInt32 unused_0x68; // Seemingly not populated
    SceUInt32 DACR;
    SceUInt32 DFSR;
    SceUInt32 IFSR;
    SceUInt32 DFAR;
    SceUInt32 IFAR;
    SceUInt32 PAR;
    SceUInt32 TEEHBR;
    SceUInt32 PMCR;
    SceUInt32 PMCNTENSET;
    SceUInt32 PMCNTENSET_2; // Second copy of PMCNTENSET
    SceUInt32 PMSELR;
    SceUInt32 PMCCNTR;
    SceUInt32 PMUSERENR;
    SceUInt32 PMXEVTYPER0;
    SceUInt32 PMXEVCNTR0;
    SceUInt32 PMXEVTYPER1;
    SceUInt32 PMXEVCNTR1;
    SceUInt32 PMXEVTYPER2;
    SceUInt32 PMXEVCNTR2;
    SceUInt32 PMXEVTYPER3;
    SceUInt32 PMXEVCNTR3;
    SceUInt32 PMXEVTYPER4;
    SceUInt32 PMXEVCNTR4;
    SceUInt32 PMXEVTYPER5;
    SceUInt32 PMXEVCNTR5;
    SceUInt32 unused_0xD0;
    SceUInt32 unk_0xD4;         // Comes from SceVfpIntRegs[localCore].field_0x100
    SceUInt32 DBGSCRext;
    SceUInt32 unusedDC[9];  // Seemingly not populated
    SceUInt64 VFP_registers[32]; // Content of registers d0-d31
    SceUInt32 unk_0x200[128];       // Comes from SceVfpIntRegs[localCore].field_0x200
} SceExcpmgrExceptionContext;

typedef enum {
    // For all codes != 3, calling the last handler in the chain should call sceKernelSysrootReturnFromExcpToThreadForKernel and return properly
    SCE_EXCPMGR_EXCEPTION_HANDLING_CODE_0 = (int16_t)0,
    SCE_EXCPMGR_EXCEPTION_HANDLING_CODE_1 = (int16_t)1,
    SCE_EXCPMGR_EXCEPTION_HANDLING_CODE_2 = (int16_t)2,
    // If this code reaches the last handler in the chain, calls SceDebugForKernel_082B8D6A then loops infinitely
    SCE_EXCPMGR_EXCEPTION_NOT_HANDLED_FATAL = (int16_t)3,
    SCE_EXCPMGR_EXCEPTION_HANDLING_CODE_4 = (int16_t)4
} SceExcpmgrExceptionHandlingCode;

typedef enum {
    SCE_EXCPMGR_EXCEPTION_CODE_RESET = 0, // Reset
    SCE_EXCPMGR_EXCEPTION_CODE_UNDEF = 1, // Undefined Instruction
    SCE_EXCPMGR_EXCEPTION_CODE_SVC = 2, // Supervisor Call
    SCE_EXCPMGR_EXCEPTION_CODE_PABT = 3, // Prefetch Abort
    SCE_EXCPMGR_EXCEPTION_CODE_DABT = 4, // Data Abort
    SCE_EXCPMGR_EXCEPTION_CODE_RESERVED = 5, // Reserved
    SCE_EXCPMGR_EXCEPTION_CODE_IRQ = 6, // Interrupt
    SCE_EXCPMGR_EXCEPTION_CODE_FIQ = 7, // Fast Interrupt
} SceExcpmgrExceptionCode;

To find

Functions with the following names may exist in SceExcpmgr :

   sceKernelDefaultHandlerCfunc
   sceKernelDefaultHandlerSvcCfunc
   sceKernelDefaultHandlerIrqCfunc
   sceKernelDefaultHandlerReservedCfunc
   sceKernelPanicHandlerUndefCfunc
   sceKernelPanicHandlerDabtCfunc
   sceKernelPanicHandlerPabtCfunc

SceExcpmgrForKernel

sceKernelRegisterExceptionHandlerForKernel

Version NID
0.990-3.60 0x03499636
3.65 0x00063675

Temp name was sceExcpmgrRegisterHandlerForKernel.

Installs an exception handler. The exception handler must be ARM code, and not Thumb code. Allowed priority values are from 0 (most important) to 7 (least important), including them. Specifying priority 0 will install the handler directly in VBAR, which means its code will run directly when an exception raises (and as such needs to build the exception context itself).

The syscall handler in FW 1.50 is SceExcpmgr_func_0x81000E40.

int sceKernelRegisterExceptionHandlerForKernel(SceExcpmgrExceptionCode excode, SceUInt32 priority, SceExcpmgrExceptionHandlerContext *handler);

sceKernelRegisterDefaultExceptionHandlerForKernel

Version NID
0.990-3.60 0xFFCCB5F9
3.65 0x416C0E20

Installs an exception handler for all exceptions. If no exception handler is already installed for an exception, the handler will be installed in the VBAR. handler must be the same parameter that would be passed to sceKernelRegisterExceptionHandlerForKernel.

int sceKernelRegisterDefaultExceptionHandlerForKernel(SceExcpmgrExceptionHandlerContext *handler);

sceKernelReleaseExceptionHandlerForKernel

Version NID
0.990-3.60 0xE04AE286

Uninstalls an exception handler.

Pass the same arguments as provided to sceKernelRegisterExceptionHandlerForKernel.

int sceKernelReleaseExceptionHandlerForKernel(SceExcpmgrExceptionCode excode, SceExcpmgrExceptionHandlerContext *handler);

sceKernelReleaseDefaultExceptionHandlerForKernel

Version NID
0.990 0x917A6D2B
3.60 not present

sceKernelInitialHandlerDebugUndefCfuncForKernel

Version NID
0.990-3.60 0xB77DCBD6

Logs some information about the CPU state and backtrace then returns. Freezes with an infinite loop if currentHandlerIndex is superior to 1.

void sceKernelInitialHandlerDebugUndefCfuncForKernel(SceExcpmgrExceptionContext* context);

sceKernelInitialHandlerDebugPabtCfuncForKernel

Version NID
0.990-3.60 0x25C0C91B

Logs some information about the CPU state and backtrace then returns. Freezes with an infinite loop if currentHandlerIndex is superior to 1.

void sceKernelInitialHandlerDebugPabtCfuncForKernel(SceExcpmgrExceptionContext* context);

sceKernelInitialHandlerDebugDabtCfuncForKernel

Version NID
0.990-3.60 0xFFFA3353

Logs some information about the CPU state and backtrace then returns. Freezes with an infinite loop if currentHandlerIndex is superior to 1.

void sceKernelInitialHandlerDebugDabtCfuncForKernel(SceExcpmgrExceptionContext* context);

sceKernelPanicHandlerReturnFromNestedExceptionCfuncForKernel

Version NID
0.990-3.60 0xD17EEE40
void sceKernelPanicHandlerReturnFromNestedExceptionCfuncForKernel(SceExcpmgrExceptionContext* context);

sceKernelDefaultHandlerResetCfuncForKernel

Version NID
0.990-3.60 0xA90AC525
3.65 0x4337DD78

Returns a pointer to the handler previously registered by sceKernelRegisterDefaultExceptionHandlerForKernel.

SceExcpmgrExceptionHandlerContext *sceKernelDefaultHandlerResetCfuncForKernel(void);

sceKernelGetExcpStackBottomForKernel

Version NID
0.990-3.60 0x4C603645
3.65 0x5420ED8F

Returns the exception stack bottom for specified CPU core. The stack bottom is the highest address of the stack.

Reimplementation code:

void* sceKernelGetExcpStackBottomForKernel(int coreNum) {
    return sceExcpmgrGetDataForKernel()->ExcpStackBottom[coreNum];
}
void* sceKernelGetExcpStackBottomForKernel(int coreNum);

sceExcpmgrGetDataForKernel

Version NID
0.931-0.990 not present
3.60 0x08CB30E6

Get exception data pointer (for use by handlers).

SceExcpmgrData* sceExcpmgrGetDataForKernel(void);

SceExcpmgrForKernel_3AE9AEE1

Version NID
0.931-0.990 not present
3.60 0x3AE9AEE1

Sets a callback function ran by the default UNDEF exception handler before calling the next handler in the chain.

// NOTE : context passed to callback lacks VFP registers
void SceExcpmgrForKernel_3AE9AEE1(void (*callback)(SceExcpmgrExceptionContext*));

SceExcpmgrForKernel_4FF90618

Version NID
0.990-3.60 0x4FF90618

Sets whether or not watchpoint control debug registers (DBGWCR0-DBGWCR4) should be left untouched by the UNDEF/DABT/PABT handlers. Registers are otherwise zero'ed out.

void SceExcpmgrForKernel_4FF90618(SceBool keepRegisters);

SceExcpmgrForKernel_7ADF11DB

Version NID
0.931-0.990 not present
3.60 0x7ADF11DB

Sets a callback function ran by the default DABT exception handler before calling the next handler in the chain.

// NOTE : context passed to callback lacks VFP registers
void SceExcpmgrForKernel_7ADF11DB(void (*callback)(SceExcpmgrExceptionContext*));

SceExcpmgrForKernel_8D223205

Version NID
0.931-0.990 not present
3.60 0x8D223205
3.65 0x58F7212B

Sets a callback function ran by the default PABT exception handler before calling the next handler in the chain.

// NOTE : context passed to callback lacks VFP registers
void SceExcpmgrForKernel_8D223205(void (*callback)(SceExcpmgrExceptionContext*));

SceExcpmgrForKernel_A66DDFA3

Version NID
0.990-3.60 0xA66DDFA3

Sets whether or not breakpoint control debug registers (DBGBCR0-DBGBCR5) should be left untouched by the UNDEF/DABT/PABT handlers. Registers are otherwise zero'ed out.

void SceExcpmgrForKernel_A66DDFA3(SceBool keepRegisters);

SceExcpmgrForKernel_C45C0D3D

Version NID
0.931-0.990 not present
3.60 0xC45C0D3D

Set the "memory access error range". If a DABT exception occurs and PC is located in the range (inclusive) provided by this function, a subroutine of the default DABT handler will return SCE_KERNEL_ERROR_INVALID_MEMORY_ACCESS which in turn makes the handler return to the instruction right after the faulting one.

void SceExcpmgrForKernel_C45C0D3D(uintptr_t rangeStart, uintptr_t rangeStop);

SceExcpmgrForKernel_D464A9A7

Version NID
0.990-3.60 0xD464A9A7

Returns the current nested exception count, or 0 if current TPIDRPRW is non-NULL.

int SceExcpmgrForKernel_D464A9A7(void);

SceExcpmgrForTZS

SceExcpmgrForTZS_get_default_excp_handler

Version NID
0.931-1.80 0x07A5790B
void *SceExcpmgrForTZS_get_default_excp_handler(void);

sceKernelReleaseExceptionHandlerForTZS

Version NID
0.931-1.80 0x166C9362
int sceKernelReleaseExceptionHandlerForTZS(SceExcpmgrExceptionCode excode, SceExcpmgrExceptionHandlerContext *handler)

sceKernelReleaseDefaultExceptionHandlerForTZS

Version NID
0.931-1.80 0x6282E52C
int sceKernelReleaseDefaultExceptionHandlerForTZS(SceExcpmgrExceptionHandlerContext *handler)

sceKernelRegisterDefaultExceptionHandlerForTZS

Version NID
0.931-1.80 0xA0434735
int sceKernelRegisterDefaultExceptionHandlerForTZS(SceExcpmgrExceptionHandlerContext *handler)

sceKernelRegisterMonitorEntryForTZS

Version NID
0.931-3.60 0xAC297406
int sceKernelRegisterMonitorEntryForTZS(SceExcpmgrExceptionCode excode, SceExcpmgrExceptionHandlerContext *handler);

sceKernelRegisterExceptionHandlerForTZS

Version NID
0.931-1.80 0xDD4C680D
int sceKernelRegisterExceptionHandlerForTZS(SceExcpmgrExceptionCode excode, SceUInt32 priority, SceExcpmgrExceptionHandlerContext *handler);

Exceptions

SVC

SVC (Supervisor Call), more commonly called Syscalls (system calls), is what allows to interact with non-secure kernel from usermode.

The SVC interface is defined in non-secure kernel as:

Register Value
R0 First argument
R1 Second argument
R2 Third argument
R3 Fourth argument
R12 Syscall number

On return, R1-R3 and R12 are cleared to 0x0 or 0xDEADBEEF to prevent any data leaks. All user pointers passed to syscalls are accessed with ARM instructions LDRT and STRT for hardware forced permission checks. Syscalls 0x0 - 0xFF are likely a "fastcall" interface that do not mask interrupts or set the DACR, however currently are no such fastcalls defined. Syscalls 0x100 - 0xFFF are made with IRQ interrupts masked and DACR set to 0xFFFF0000 (to prevent access to certain memory domains). Any other syscall numbers are invalid.

System calls are handled in "system" mode defined in ARMv7 (mode 0b11111).

User exported functions loaded by SceKernelModulemgr are exported as syscalls. The number assigned to the syscall are randomized with respect to each library but not within a library. That means, for example, two functions exported by a library will always be some syscall number apart even though that number will change on each boot.

There is no SVC in secure world because all code in secure world is running as kernel.

SMC

SMC (Secure Monitor Call) is what allows to interact with ARM TrustZone from non-secure kernel.

The SMC interface for making a non-secure kernel call to secure kernel is:

Register Value
R0 First argument
R1 Second argument
R2 Third argument
R3 Fourth argument
R12 SMC number

The SMC interface is very similar to the SVC interface. The SMC handler and MVBAR is set up in Secure World by SceExcpmgrForTZS.

0x0 - 0xFF are fast service calls. 0x100 - 0xFFF are normal service calls ran with IRQs masked.

Secure services are ran in ARM system processor mode (0b11111) in the Secure World.

SMC calls are registered by SceIntrmgrForTZS functions.

SMC calls

Number Module Arguments Notes
0x101
int AllocSharedMemory_S(void *pPA, SceSize size);
0x103
int FreeSharedMemory_S(void);
Frees the allocation of virtual ranges: 0x40000000-0x40100000, 0x50000000-0x51000000 and 0x51000000-0x52000000 with UID 0x10007. This is SKBL only and does not affect NSKBL.
0x104
int PervasiveAccessMode(int mode, SceBool cmd);
cmd: 0 clear, 1 set
0x105
int TASAccessMode(int mode, SceBool cmd);
cmd: 0 clear, 1 set
0x106
int Pervasive2AccessMode(int mode, SceBool cmd);
cmd: 0 clear, 1 set
0x107
int RegbusAccessMode(int mode, SceBool cmd);
cmd: 0 clear, 1 set
0x10A
int GetGrabCmpMap(int index);
Gets GRAB Compatibility Map.
0x10B
int SetGrabCmpMap(int index, int map);
Sets GRAB Compatibility Map.
0x10C SceKernelBusError
int BusErrorDump(void);
Used by SceKernelBusError when a bus error is handled, just before getting bus error info. Writes bus registers to (shared memory + 0x4000).
0x10D SceKernelBusError
int BusErrorDump2(void);
Used by SceKernelBusError when a bus error is handled, just before getting bus error info. Writes bus registers to (shared memory + 0x6000). Replacement of SMC 0x10C that writes to offset 0x6000 instead of 0x4000 and calls sceKernelDcacheCleanInvalidateRange before returning.
0x10E SceKernelBusError
int BusErrorClear(void);
On FW 0.931, prints a tree of all bus states. On FW 3.60, does nothing and return 0.
0x10F
int smc_ple_flush_kill_and_l1_dcache_clean_invalidate_all(void);
Flushes (and kills if there is activity) the PLE (Preload Engine) and then cleans and invalidates all the L1 Dcache.
0x110 SceDriverTzs
int smc_bus_set_state(int bus, int command);
bus: 1 -> used by SceEnumWakeUp, 2 -> used to enable/disable some things used by the PSP Emulator; maybe CPU, or memory for example. Command: 0 (stop), 1 (start), 2 (LCD DMAC init).
0x111 SceDriverTzs Related to bus.
0x113 SceDriverTzs Related to bus.
0x114 SceDriverTzs
int smc_bus_freq_op(SceUInt32 op, SceUInt32 freq_level);
op: 0 - Set bus frequency, 1 - Get bus frequency, 2 - Set GPU Xbar frequency, 3 - Get GPU Xbar frequency
0x117 SceDriverTzs
int smc_cdram_enable(void);
Seems to enable the CDRAM (by using the SceEmcTop registers).
0x118 SceDriverTzs
int smc_0x118(void);
Seems to enable something CDRAM related.
0x119 SceDriverTzs
int smc_0x119(void);
Seems to disable something CDRAM related.
0x11A SceDriverTzs
int sceSysconSetPowerMode(int type, int mode);
Set power mode. See sceSysconSetPowerModeForDriver.
0x11B SceDriverTzs
int smc_0x11B(int mode, SceBool cmd);
mode: must be < 0x1000, cmd: 0 set, 1 clear
0x11C SceDriverTzs
int smc_0x11C(SceUInt32 handle, SceInt32 value);
Used by SceLowio#SceGrabForDriver_188BBCC8.
0x11D SceDriverTzs
int smc_compat_set_memory_bank_start_paddr(int bank, void *pPA);
Valid banks: 0-7, and physical addresses: 0x20000000-0x2FFFFFFF and 0x42800000-0x7FFFFFFF.
0x11E SceDriverTzs
int smc_compat_set_state_ex(int command, int ex);
Replacement for SMC 0x110. Used to enable/disable some things used by the PSP Emulator. Maybe the CPU, or memory for example. Command: 0 (stop), 1 (start), 2 (LCD DMAC init). Ex is only used for start (maybe for resume/suspend).
0x11F SceDriverTzs
int smc_0x11F(int unk);
Valid unk: 1-3. Waits something like a semaphore.
0x120 SceDriverTzs
int smc_compat_get_memory_bank_start_paddr(int bank);
Valid banks 0-7.
0x121 SceDriverTzs
int smc_0x121(int bank1, int bank2);
Valid banks 0-7.
0x122 SceDriverTzs
int smc_intr_crash(int type, void *pTTBR0, void *pVBAR, void *pSysbase);
type: 0 (exception), 1 (panic_or_assertion_failed)
0x12D
int sceSblSmSchedInvoke(SceBool priority, void *sm_self_paddr, SceUInt32 num_pa_range, SceSblTzsBridgeArgArea area);
Used by sceSblSmSchedProxyInvokeForKernel.
0x12E
int sceSblSmSchedWait(SceSmSchedRequestId req_id, SceSblTzsBridgeArgArea area);
Used by sceSblSmSchedProxyWaitForKernel.
0x12F
int sceSblSmSchedGetStatus(SceSmSchedRequestId req_id, SceSblTzsBridgeArgArea area);
Used by sceSblSmSchedProxyGetStatusForKernel.
0x130
int sceSblSmSchedKill(SceSmSchedRequestId req_id);
Used by sceSblSmSchedProxyKillForKernel.
0x131 Reserved (on FWs 0.931-3.60).
0x132 Reserved (on FWs 0.931-3.60).
0x133
int smc_sm_sched_proxy_call_func(SceSmSchedRequestId req_id, int mailbox_id, SceUInt32 mailval);
Used by sceSblSmSchedProxyCallFuncForKernel. mailval is paddr(SceSblSmschedCallFuncCommand) | 1.
0x134
int sceSblSmSchedReadArm2Cry(SceSmSchedRequestId req_id, int mailbox_id, SceUInt32 *pMailval);
Used by sceSblSmSchedProxyReadArm2CryForKernel.
0x135
int sceSblSmSchedWriteArm2Cry(SceSmSchedRequestId req_id, int mailbox_id, SceUInt32 mailval);
Used by sceSblSmSchedProxyWriteArm2CryForKernel.
0x136
int sceSblSmSchedWriteCry2Arm(SceSmSchedRequestId req_id, int mailbox_id, SceUInt32 mailval);
Used by sceSblSmSchedProxyWriteCry2ArmForKernel.
0x137
int sceSblSmSchedReadCry2Arm(SceSmSchedRequestId req_id, int mailbox_id, SceUInt32 *pMailval);
Used by sceSblSmSchedProxyReadCry2ArmForKernel.
0x138
int sceSblSmSchedRegisterIntrHandler(SceSmSchedRequestId req_id, int mailbox_id);
Used by sceSblSmSchedProxyRegisterIntrHandlerForKernel.
0x139
int sceSblSmSchedReleaseIntrHandler(SceSmSchedRequestId req_id, int mailbox_id);
Used by sceSblSmSchedProxyReleaseIntrHandlerForKernel.
0x13A
int smc_sm_sched_proxy_enable_all_cry2arm_interrupts(SceSmSchedRequestId req_id, int mailbox_id, SceSblTzsBridgeArgArea area);
Interrupt Cry2Arm set enable.
0x13B
int smc_sm_sched_proxy_uninitialize(void);
Interrupt Cry2Arm clear enable. Used by sceSblSmSchedProxyUninitializeForKernel.
0x13C
int smc_sm_sched_proxy_execute_sk_command(sk_cmd_index cmd_index);
Executes a Secure Kernel command. Used by sceSblSmSchedProxyExecuteSKCommandForKernel.
0x168
int smc_0x168_dmac(int index, int value);
SceDmacmgrDmac related. Writes value to SceDmacmgrDmacN + 0x100. Maybe key_id related.
0x169
int smc_0x169_dmac(int index, int value);
SceDmacmgrDmac related. Writes value to SceDmacmgrDmacN + 0x104. Maybe key_id related.
0x16A
int smc_l2_write_control_register(int value);
Flushes and invalidates the entire L2 Cache (Clean and Invalidate by Way with way = 0xFFFF, offset 0x7FC), then performs an L2 Cache Sync (offset 0x730), and finally writes value to the L2 Control Register (offset 0x100).
0x16B
int smc_l2_write_auxiliary_control_register(int value);
Writes value to the L2 Auxiliary Control Register (offset 0x104).

Aborts

On development units, data and prefetch aborts can handle BKPT instruction for software breakpoints. SceDebug uses this to handle usermode breakpoints. There is no built-in support for BKPT in kernel code.

SceSysmem uses data aborts with the LDRT and STRT instructions to implement user pointer checking. When LDRT/STRT throws a MMU data exception because of an invalid access and the exception came from SceSysmem#sceKernelCopyFromUserForDriver or SceSysmem#sceKernelCopyToUserForDriver or related functions, the data abort handler will resume execution.

IRQ

IRQs are only handled in non-secure world. An IRQ in secure world is fatal. See SceKernelIntrMgr.

FIQ

FIQs are only handled in secure world because of the bit set in the SCR. Because of this, it is likely that secure devices such as the F00D Processor use FIQs to communicate with the Cortex A9 cores. See SceKernelIntrMgr.