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
|