SceKernelIntrMgr is a kernel module that is primary responsible for setting up external and internal interrupts. Notably, it facilitates communication with the Cmep processor.
Module
This module exists in both non-secure and secure world. The non-secure world SELF can be found in os0:kd/intrmgr.skprx. It also can be found in the Boot Image (SKBL).
| Version |
World |
Privilege
|
| 1.69-3.60 |
Non-secure |
Kernel
|
| 1.69 |
Secure |
Kernel
|
Libraries
This module only exports kernel libraries.
Known NIDs
Interrupt
Context
PMCNTENCLR <- PMCNTENSET
TPIDRPRW <- 0
CONTEXTIDR <- 0
TTBR1 <- ?
CONTEXTIDR <- ? (could be restore)
DACR <- 0x15450000
PMSELR <- 0
PMXEVTYPER <- unknown
PMXEVCNTR <- unknown
PMSELR <- 1
PMXEVTYPER <- unknown
PMXEVCNTR <- unknown
PMSELR <- 2
PMXEVTYPER <- unknown
PMXEVCNTR <- unknown
PMSELR <- 3
PMXEVTYPER <- unknown
PMXEVCNTR <- unknown
PMSELR <- 4
PMXEVTYPER <- unknown
PMXEVCNTR <- unknown
PMSELR <- 5
PMXEVTYPER <- unknown
PMXEVCNTR <- unknown
CPACR <- 0xF00000
fpexc <- 0x40000000
DBGBVR2 <- unknown
DBGBCR2 <- unknown
DBGBVR3 <- unknown
DBGBCR3 <- unknown
DBGBVR4 <- unknown
DBGBCR4 <- unknown
DBGWVR1 <- unknown
DBGWCR1 <- unknown
DBGWVR2 <- unknown
DBGWCR2 <- unknown
DBGWVR3 <- unknown
DBGWCR3 <- unknown
TPIDRURO <- 0
Data segment layout
| Static VA |
Offset |
Length |
Description
|
| 0x81004000 |
0x0 |
0x842F8 |
entire
|
| 0x81004000 |
0x0 |
0x40 * 0x100 |
Intr entry info
|
| 0x81008000 |
0x4000 |
0x80 * 4 |
Intr nest info
|
| 0x81008200 |
0x4200 |
0x80(?) |
some memblock/misc info
|
| 0x81008280 |
0x4280 |
0x2000 * 0x10 * 4 |
Intr register store area
|
| 0x81088280 |
0x84280 |
0x78 |
Something
|
SceIntrmgrForDriver
sceKernelIsSubInterruptOccurredForDriver
| Version |
NID
|
| 0.990-3.60 |
0x950B864B
|
int sceKernelIsSubInterruptOccurredForDriver(int intr_code, int subinterrupt_code);
sceKernelRegisterIntrHandlerForDriver
| Version |
NID
|
| 0.990-3.60 |
0x5C1FEB29
|
typedef struct SceKernelRegisterInterruptOptionsExtended
{
unsigned int size;
unsigned int unk_4;
unsigned int unk_8;
SceKernelIntrOptParam2Callback1 *release_subintr_cb;
SceKernelIntrOptParam2Callback1 *fptr0;
SceKernelIntrOptParam2Callback1 *enable_subintr_cb;
SceKernelIntrOptParam2Callback1 *disable_subintr_cb;
SceKernelIntrOptParam2Callback2 *fptr3;
unsigned int unk_20;
unsigned int unk_24;
} SceKernelRegisterInterruptOptionsExtended; /* size = 0x28 */
typedef struct SceKernelRegisterInterruptOptions
{
unsigned int size;
unsigned int num;
SceKernelRegisterInterruptOptionsExtended *opt2;
unsigned int flags; /* 0b1 = use sensitivity param */
unsigned int sensitivity;
} SceKernelRegisterInterruptOptions; /* size = 0x14 */
typedef int (SceKernelIntrHandler)(int intr_code, void* userCtx);
int sceKernelRegisterIntrHandlerForDriver(int code, const char *name, int interrupt_type, SceKernelIntrHandler *handler, void* userCtx, int priority, int targetcpu, SceKernelRegisterInterruptOptions *opt);
sceKernelReleaseIntrHandlerForDriver
| Version |
NID
|
| 0.990-3.60 |
0xD6009B98
|
This function first performs a disable and then removes the current interrupt handler associated with the interrupt intr_code.
int sceKernelReleaseIntrHandlerForDriver(int intr_code);
sceKernelDisableIntrForDriver
| Version |
NID
|
| 0.990-3.60 |
0x180435EC
|
int sceKernelDisableIntrForDriver(int intr_code);
This function writes 1 << (intr_code % 32) to the Interrupt Disable Registers (offset 0x180 from the Interrupt Distributor registers) at 0x180 + (intr_code / 32) * 4.
sceKernelEnableIntrForDriver
| Version |
NID
|
| 0.990-3.60 |
0x7117E827
|
int sceKernelEnableIntrForDriver(int intr_code);
This function writes 1 << (intr_code % 32) to the Interrupt Enable Registers (offset 0x100 from the Interrupt Distributor registers) at 0x100 + (intr_code / 32) * 4.
sceKernelResumeIntrForDriver
| Version |
NID
|
| 0.990-3.60 |
0xA4C772AF
|
int sceKernelResumeIntrForDriver(int intr_code, int enabled);
Enables or disables an interrupt. If a 0 is passed to enabled, it acts as sceKernelDisableIntrForDriver, and if a 1 is passed, it acts as sceKernelEnableIntrForDriver.
sceKernelSuspendIntrForDriver
| Version |
NID
|
| 0.990-3.60 |
0x6EC07C56
|
int sceKernelSuspendIntrForDriver(int intr_code, SceBool *enabled);
This function returns whether the interrupt intr_code is enabled or not. If it's enabled, a 1 will be written to enabled and a 0 otherwise.
To check the enable status, the function checks the bit number intr_code % 32 of the Interrupt Enable register (offset 0x100 from the Interrupt Distributor registers) at 0x100 + (intr_code / 32) * 4.
sceKernelSetIntrPriorityForDriver
| Version |
NID
|
| 0.990-3.60 |
0x71020E29
|
int sceKernelSetIntrPriorityForDriver(int intr_code, unsigned char priority);
This function writes priority to the Interrupt Priority Registers (offset 0x400 from the Interrupt Distributor registers) at 0x400 + intr_code.
sceKernelGetIntrPriorityForDriver
| Version |
NID
|
| 0.990-3.60 |
0xE427D050
|
int sceKernelGetIntrPriorityForDriver(int intr_code, int *priority);
sceKernelSetIntrTargetCpuForDriver
| Version |
NID
|
| 0.990-3.60 |
0x973BACCC
|
int sceKernelSetIntrTargetCpuForDriver(int intr_code, int target_cpu);
This function writes the bits 0-8 or 16-24 of target_cpu, depending on whether the mask is in former or the latter bits, to the Interrupt Processor Targets Registers (offset 0x800 from the Interrupt Distributor registers) at 0x800 + intr_code
sceKernelGetIntrTargetCpuForDriver
| Version |
NID
|
| 0.990-3.60 |
0x353CFAAE
|
int sceKernelGetIntrTargetCpuForDriver(int intr_code, int *cpu_mask);
sceKernelGenerateSoftIntrForDriver
| Version |
NID
|
| 0.990-3.60 |
0x29F62500
|
int sceKernelGenerateSoftIntrForDriver(int intr_code, unsigned int target_list_filter, unsigned int cpu_target_list);
This function triggers a SGI (software generated interrupt) by writing (target_list_filter << 24) | (cpu_target_list << 16) | intr_code to the Software Generated Interrupt Register (offset 0xF00 from the Interrupt Distributor registers, physical address 0x1A001F00).
Note: intr_code must be between 0x0 and 0xF.
sceKernelIsIntrContextForDriver
| Version |
NID
|
| 0.931-3.60 |
0x182EE3E3
|
Indicates whether or not the thread is currently handling an interrupt.
SceBool sceKernelIsIntrContextForDriver(void);
Returns SCE_FALSE if the current TPIDRPRW (PL1-only Thread ID Register, holds a pointer to the current ThreadCB) is non-NULL, or if an internal structure field is not set for the current CPU.
sceKernelRegisterSubIntrHandlerForDriver
| Version |
NID
|
| 0.990-3.60 |
0x96576C18
|
int sceKernelRegisterSubIntrHandlerForDriver(int intr_code, int subintr_code, const char *name, void *handler, void *register_arg);
sceKernelReleaseSubIntrHandlerForDriver
| Version |
NID
|
| 0.990-3.60 |
0x7B9657B3
|
int sceKernelReleaseSubIntrHandlerForDriver(int intr_code, int subintr_code);
sceKernelCallSubIntrHandlerForDriver
| Version |
NID
|
| 0.990-3.60 |
0xCC94B294
|
Triggers a subinterrupt by directly calling it.
int sceKernelCallSubIntrHandlerForDriver(int intr_code, int subintr_code, void *subintr_arg);
sceKernelEnableSubIntrForDriver
| Version |
NID
|
| 0.990-3.60 |
0x901E41D8
|
It also calls fptr1 of the registered reg_intr_opt2 as: reg_intr_opt2.fptr1(intrcode, subintr_code).
int sceKernelEnableSubIntrForDriver(unsigned int intrcode, unsigned int subintr_code);
sceKernelDisableSubIntrForDriver
| Version |
NID
|
| 0.990-3.60 |
0x259C6D9E
|
Calls fptr2 of the registered reg_intr_opt2 as: reg_intr_opt2.fptr2(intr_code, subintr_code).
int sceKernelDisableSubIntrForDriver(int intr_code, int subintr_code);
sceKernelSuspendSubIntrForDriver
| Version |
NID
|
| 0.990-3.60 |
0x3A9EA7D1
|
Calls fptr3 of the registered reg_intr_opt2 as: reg_intr_opt2.fptr3(intr_code, subintr_code, arg).
int sceKernelSuspendSubIntrForDriver(int intr_code, int subintr_code, void *arg);
sceKernelResumeSubIntrForDriver
| Version |
NID
|
| 0.990-3.60 |
0x957023D0
|
int sceKernelResumeSubIntr(int intr_code, int subinterrupt_code, int enabled);
sceKernelRegisterIntrHookHandlerForDriver
| Version |
NID
|
| 0.990-3.60 |
0x99048AEC
|
int sceKernelRegisterIntrHookHandler(int intr_code, void *new_handler, void **old_handler);
sceKernelReleaseIntrHookHandlerForDriver
| Version |
NID
|
| 0.990-3.60 |
0xA0B7F44E
|
int sceKernelReleaseIntrHookHandler(int intr_code);
invoke_callback_842B45DC
| Version |
NID
|
| 0.990 |
not present
|
| 3.60 |
0xC568F145
|
invoke callback that was set with 0x842B45DC
int invoke_callback_842B45DC(int arg1);
SceIntrmgrForKernel
sceKernelEnableCoreIntr_SceIntrmgrForKernel_A60D79A4
| Version |
NID
|
| 0.940-3.60 |
0xA60D79A4
|
| 3.65 |
0xBCD3BB05
|
Enables interrupts (cpsie i).
void SceIntrmgrForKernel_A60D79A4(void);
sceKernelGetIntrPendingStatusForDebuggerForKernel
| Version |
NID
|
| 0.990-3.60 |
0xA269003D
|
int sceKernelGetIntrPendingStatusForDebuggerForKernel(int intr_code);
This function returns whether the interrupt intr_code is pending or not. If it's pending, a 1 will be returned, and a 0 will be returned otherwise.
To check the pending status, the function checks the bit number intr_code % 32 of the Interrupt Set-Pending Registers (offset 0x200 from the Interrupt Distributor registers) at 0x200 + (intr_code / 32) * 4.
sceKernelClearIntrPendingStatusForDebuggerForKernel
| Version |
NID
|
| 0.990-3.60 |
0x4DC48A01
|
int sceKernelClearIntrPendingStatusForDebuggerForKernel(int intrcode);
This function writes 1 << (intr_code % 32) to the Interrupt Clear-Pending Registers (offset 0x280 from the Interrupt Distributor registers) at 0x280 + (intr_code / 32) * 4.
sceKernelAllocSystemCallTableForKernel
| Version |
NID
|
| 0.990-3.60 |
0xB60ACF4B
|
| 3.65 |
0xB5A665C7
|
Temp name was sceKernelAllocSyscallTableForKernel.
Calls sceKernelAllocPartitionMemBlockForKernel(0x10009, "SceSyscallTable", 0x1020D006, 4 * numSyscalls, 0).
0x10009 is the UID of the "SceKernelRoot" partition.
/**
* @brief Allocates the system call table.
*
* @param[in] numSyscalls Number of syscalls the allocated table should be able to hold
* @param[in,out] ppTableBase Pointer to a variable that will recieve the syscall table's base address (must not be NULL)
* @retval (-1) numSyscalls is 0, or the table has already been allocated
* @retval (<0) Error code
* @retval (>0) UID of the syscall table memory block
*/
SceUID sceKernelAllocSystemCallTableForKernel(SceUInt32 numSyscalls, void** ppTableBase);
sceKernelQueryIntrHandlerInfoForKernel
| Version |
NID
|
| 0.990-3.60 |
0xB5AFAE49
|
int sceKernelQueryIntrHandlerInfoForKernel(unsigned int intr_code, unsigned int a2, int a3);
SceIntrmgrForKernel_01E5233E
| Version |
NID
|
| 3.60 |
0x01E5233E
|
Copy data to dst from src.
void SceIntrmgrForKernel_01E5233E(void *dst, const void *src);
SceIntrmgrForKernel_37F4627B
| Version |
NID
|
| 3.60 |
0x37F4627B
|
Register sceKernelRegisterIntrHandler/sceKernelReleaseIntrHandler exit callback.
void SceIntrmgrForKernel_37F4627B(void *a1, void *a2);
SceIntrmgrForKernel_4F611A63
| Version |
NID
|
| 3.60 |
0x4F611A63
|
Register irq complete callback.
void SceIntrmgrForKernel_4F611A63(void *a1);
SceIntrmgrForKernel_4F890B0C
| Version |
NID
|
| 3.60 |
0x4F890B0C
|
Guessed name : sceKernelSetIrqDBGBVRSaveContext
void SceIntrmgrForKernel_4F890B0C(void *a1);
SceIntrmgrForKernel_53DD3BF5
| Version |
NID
|
| 3.60 |
0x53DD3BF5
|
Register irq `setupNextContext_intr` function.
void SceIntrmgrForKernel_53DD3BF5(void *a1);
sceKernelIntrmgrRegisterIntrTraceHookForKernel
| Version |
NID
|
| 3.60 |
0x6FAC5DEF
|
void sceKernelIntrmgrRegisterIntrTraceHookForKernel(void *a1, void *a2);
SceIntrmgrForKernel_772BE54F
| Version |
NID
|
| 3.60 |
0x772BE54F
|
Register irq `callThreadmgrBeforeIntrHandler` function.
void SceIntrmgrForKernel_772BE54F(void *a1);
SceIntrmgrForKernel_82ADA185
| Version |
NID
|
| 3.60 |
0x82ADA185
|
Register sceKernelTriggerSubIntr's enter/leave callback.
void SceIntrmgrForKernel_82ADA185(void *a1, void *a2);
SceIntrmgrForKernel_842B45DC
| Version |
NID
|
| 3.60 |
0x842B45DC
|
Register svc invalid call (?) callback.
void SceIntrmgrForKernel_842B45DC(void *a1);
SceIntrmgrForKernel_89E47181
| Version |
NID
|
| 3.60 |
0x89E47181
|
Guessed name : sceKernelSetIrqDBGWVRSaveContext
void SceIntrmgrForKernel_89E47181(void *a1);
SceIntrmgrForKernel_8ED485C0
| Version |
NID
|
| 3.60 |
0x8ED485C0
|
Like setjmp->longjmp
SceIntrmgrForKernel_CAAC949E
| Version |
NID
|
| 3.60 |
0xCAAC949E
|
Set 16-bytes to global variable.
void SceIntrmgrForKernel_CAAC949E(void *a1);
sceKernelIntrmgrRegisterSyscallTraceHookForKernel
| Version |
NID
|
| 3.60 |
0xCE553E9C
|
void sceKernelIntrmgrRegisterSyscallTraceHookForKernel(void *a1, void *a2);
SceIntrmgrForKernel_EE4CE1DB
| Version |
NID
|
| 3.60 |
EE4CE1DB
|
Like setjmp->setjmp
SceIntrmgrForKernel_EF1D3865
| Version |
NID
|
| 3.60 |
0xEF1D3865
|
Return to SceInterruptControllerReg + 0x100 address
void *SceIntrmgrForKernel_EF1D3865(void);
SceIntrmgrForKernel_F281330D
| Version |
NID
|
| 3.60 |
0xF281330D
|
Guessed name : sceKernelGetIrqNestCB
void *SceIntrmgrForKernel_F281330D(SceUInt32 core, SceUInt32 nest);
get_intr_logs
| Version |
NID
|
| 0.990 |
0xB04086C6
|
| 3.60 |
not present
|
Read Physical_Memory#Interrupt_registers and writes logs to str_buf.
int get_intr_logs(char *str_buf, unsigned int max_len);
sceKernelPMonSetThreadModeMaskForKernel
| Version |
NID
|
| 0.990 |
0x730CB409
|
| 3.60 |
not present
|
int sceKernelPMonSetThreadModeMaskForKernel(unsigned int mask);
sceKernelGetVfpIntRegsAddrForKernel
SceIntrmgrForTZS
sceKernelUsleepForTZS
| Version |
NID
|
| 0.931 |
0xC0908EA9
|
sceKernelRegisterMonitorCallHandlerForTZS
| Version |
NID
|
| 0.931-1.80 |
0xC188114F
|
Register a SMC (secure only).
int sceKernelRegisterMonitorCallHandlerForTZS(int smc_id, void **func);
sceKernelRegisterIntrHandlerForTZS
| Version |
NID
|
| 0.931-1.80 |
0x6B84DA8F
|
typedef struct SceKernelRegisterInterruptOptionsExtended { // size is 0x28
unsigned int size;
unsigned int unk_4;
unsigned int unk_8;
SceKernelIntrOptParam2Callback1 *release_subintr_cb;
SceKernelIntrOptParam2Callback1 *fptr0;
SceKernelIntrOptParam2Callback1 *enable_subintr_cb;
SceKernelIntrOptParam2Callback1 *disable_subintr_cb;
SceKernelIntrOptParam2Callback2 *fptr3;
unsigned int unk_20;
unsigned int unk_24;
} SceKernelRegisterInterruptOptionsExtended;
typedef struct SceKernelRegisterInterruptOptions { // size is 0x14
unsigned int size;
unsigned int num;
SceKernelRegisterInterruptOptionsExtended *opt2;
unsigned int flags; /* 0b1 = use sensitivity param */
unsigned int sensitivity;
} SceKernelRegisterInterruptOptions;
typedef int (SceKernelIntrHandler)(int intr_code, void* userCtx);
int sceKernelRegisterIntrHandlerForTZS(int code, const char *name, int interrupt_type, SceKernelIntrHandler *handler, void* userCtx, int priority, int targetcpu, SceKernelRegisterInterruptOptions *pOpt);
sceKernelReleaseIntrHandlerForTZS
| Version |
NID
|
| 0.931 |
0x75A0F189
|
sceKernelSetIntrPriorityForTZS
| Version |
NID
|
| 0.931 |
0x9168E78E
|
sceKernelGetIntrPriorityForTZS
| Version |
NID
|
| 0.931 |
0xFEAC9841
|
sceKernelSetIntrTargetCpuForTZS
| Version |
NID
|
| 0.931 |
0xAA3C4787
|
sceKernelGetIntrTargetCpuForTZS
| Version |
NID
|
| 0.931 |
0xF3B92D98
|
sceKernelDisableIntrForTZS
| Version |
NID
|
| 0.931 |
0x4F39B381
|
sceKernelEnableIntrForTZS
| Version |
NID
|
| 0.931 |
0x98E38390
|
sceKernelResumeIntrForTZS
| Version |
NID
|
| 0.931 |
0x92DE2E92
|
sceKernelSuspendIntrForTZS
| Version |
NID
|
| 0.931 |
0xBFBEAB5C
|
sceKernelIsIntrContextForTZS
| Version |
NID
|
| 0.931 |
0x636F4549
|
sceKernelGenerateSoftIntrForTZS
| Version |
NID
|
| 0.931 |
0x28BBA975
|
int sceKernelGenerateSoftIntrForTZS(SceUInt32 intr_code, SceUInt32 filter, SceUInt32 target);
Controller
The interrupt controller is defined in the MPCore TRM [1]. The PERIPHBASE address (physical) is 0x1A000000.
Registered Interrupts
As specified in the GIC Architecture Specification, interrupt IDs 0 to 15 are reserved for Software Generated Interrupts (SGIs), while interrupt IDs 16 to 31 are reserved for Private Peripheral Interrupts (PPIs). There are no private peripherals on the PS Vita so PPIs are unused.
It appears the PS Vita's GIC implements priority bits [7:1] i.e. it only supports 128 priority levels. This means all values in the Priority column should be divided by 2.
The Target CPU indicates the CPU(s) the exception can be signaled to - "All" means it can be signaled to any CPU and 0x-prefixed values are masks.
Secure Interrupts
Those interrupts are marked as Secure using the GIC's ICDISR by SKBL. It also marks interrupts 96-111 as Secure; however, those IDs have never been seen in use. All other interrupts are marked as Non-Secure.
| Code |
Name |
Target CPU |
Priority |
Module
|
| 11 |
ScePervasive |
All |
80 |
SceDriverTzs
|
| 33 |
SceBusErrorSecure |
All |
16 |
SceKernelBusError
|
| 34 |
SceEmcTop |
All |
80 |
SceDriverTzs
|
| 135 |
SceTimerForUsleep |
All |
128 |
SceKernelIntrMgr
|
| 200 |
SceSblSmSchedCry2Arm0 |
3 |
128 |
SceSblSmsched
|
| 201 |
SceSblSmSchedCry2Arm123 |
3 |
128 |
SceSblSmsched
|
| 202 |
SceSblSmSchedCry2Arm123 |
3 |
128 |
SceSblSmsched
|
| 203 |
SceSblSmSchedCry2Arm123 |
3 |
128 |
SceSblSmsched
|
Non-Secure Interrupts
Registered Subinterrupts
Non-secure
| Interrupt code |
Subinterrupt code |
Name
|
| 8 |
2 |
SceDispalyVblank
|
| 8 |
3 |
SceCtrlVblank
|
| 8 |
5 |
SceTouchVblank
|
| 8 |
24 |
SceHprmVblank
|
| 8 |
25 |
SceLedVblank
|
| 8 |
26 |
ScePowerVblank
|
| 15 |
0 |
SceSdstorCardInsert
|
| 15 |
1 |
SceSdstorCardRemove
|
| 60 |
0 |
SceSdstorCardInsert
|
| 60 |
1 |
SceSdstorCardRemove
|
| 166 |
0 |
SceCif0Camera
|
| 168 |
0 |
SceCif1Camera
|
| 210 |
1 |
SceDisplayVbStartHDMI
|
| 213 |
1 |
SceDisplayVbStartMainLCD
|
| 221 |
0 |
SceSdstorCardInsert
|
| 221 |
1 |
SceSdstorCardRemove
|
| 222 |
2 |
SceWlanBtRobinWlan
|
| 222 |
3 |
SceBtIntr
|
| 248 |
4 |
SceSysconCmdclr
|
| 249 |
13 |
SceHdmiIntr
|