Interrupts

Interrupt priority is 0-0xF

Private Interrupts

Each CPU core has 32 software interrupts that are private and belong to that core. These interrupts are numbers 0-0x1F for each core. The hardware interrupts are not core-specific and start at interrupt ID 0x20.

IRQ Listener Description
0-0x5 MPCore software-interrupt.
0x6 Kernel MPCore software-interrupt.
0x7 MPCore software-interrupt.
0x8 Kernel MPCore software-interrupt. Used for scheduling.
0x9-0xE MPCore software-interrupt.
0xF dmnt/debugger MPCore software-interrupt. Used to abstract FIQ (debug).
0x1D Kernel MPCore timer.
0x1E Kernel MPCore watchdog - set when the watchdog counter reaches 0 in timer mode, causes interrupt 30 to set as pending. Only set on core 1 as core 1's timer is used for everything.

Hardware Interrupts

There are 0x60 hardware interrupts starting at 0x20 and continuing up to 0x7F. These are not private and are accessible from any core.

IRQ Listener Description
0x28 gsp, TwlBg PSC0?
0x29 gsp, TwlBg PSC1?
0x2A gsp, TwlBg PDC0?
0x2B gsp, TwlBg PDC1?
0x2C gsp, TwlBg PPF?
0x2D gsp, TwlBg ?
0x30 Kernel ?
0x39 Kernel DMA
0x3A Kernel DMA
0x3B Kernel DMA
0x40 nwm WIFI SDIO Controller @ 0x10122000
0x41 nwm ?
0x42 nwm_dev? WIFI SDIO Controller @ 0x10100000
0x45 mvd (New3DS) ?
0x46 mvd (New3DS) ?
0x48 camera ?
0x49 camera ?
0x4A dsp ?
0x4B camera Y2R Conversion Finished
0x4C TwlBg ?
0x4D TwlBg ?
0x4E mvd (New3DS) ?
0x4F mvd (New3DS) ?
0x50 pxi, TwlBg Sync
0x51 pxi, TwlBg ?
0x52 pxi, TwlBg Send Fifo Empty
0x53 pxi, TwlBg Receive Fifo Not Empty
0x54 i2c, TwlBg ?
0x55 i2c, TwlBg ?
0x56 spi, TwlBg ?
0x57 spi, TwlBg ?
0x58 Kernel PDN
0x59 TwlBg ?
0x5A mic ?
0x5C i2c, TwlBg ?
0x60 gpio, TwlBg Asserted when shell is opened?
0x62 gpio, TwlBg Asserted when shell is closed?
0x63 gpio, TwlBg Touchscreen
0x64 gpio, TwlBg Headphone jack plugged in
0x66 gpio, TwlBg ?
0x68 gpio, TwlBg IR?
0x69 gpio, TwlBg ?
0x6A gpio, TwlBg ?
0x6B gpio, TwlBg ?
0x6C gpio, TwlBg ?
0x6D gpio, TwlBg ?
0x6E gpio, TwlBg ?
0x6F gpio, TwlBg ?
0x70 gpio, TwlBg Headphone jack plugged out
0x71 gpio, TwlBg MCU (HOME/POWER pressed)
0x72 gpio, TwlBg ?
0x73 TwlBg ?
0x74 ? Gamecard related
0x75 ? Gamecard inserted


There are 2 tables in the ARM11 kernel: the first has 32 * 2(or 32 * 4) 8-byte entries. This table is for the private interrupts that belong to each core. The data for each interrupt can be found by doing table_base + (core_num * 0x100) + (intr_num * 8). The second table is for public hardware interrupts and the data for each interrupt can be retrieved by doing table_base + (intr_num * 8).

InterruptData

Offset Type Description
0x0 InterruptEvent * Pointer to the InterruptEvent object for that interrupt
0x4 u8 Interrupt will be masked by the IRQ handler as soon as it is acknowledged
0x5 u8 Interrupt is masked
0x6 u8 Interrupt priority
0x7 u8 Unused, alignment

Interrupt Table (New3DS)

(0xFFF318F4 in 10.3)

Offset Type Description
0x0 InterruptData[224] Data for all hardware and software interrupts
0x700 KThread* Thread currently acting on the interrupt table
0x704 s16 Error tracker for thread above
0x706 u16 Alignment

InterruptEvent

Base class for interrupt events.

Offset Type Description
0x0 void ** Pointer to vtable
0x4 u32 Unknown

The first method in the table is KInterruptEvent* InterruptEvent::getKInterruptEvent(u32 interruptID). It's actually the function called by the IRQ handler, which returns a KInterruptEvent to signal. If NULL or 1 is returned, no event will be signaled. If NULL is returned, no post-interrupt rescheduling will be done.

The second method is void InterruptEvent::signalEvent(void), which signals the associated KEvent object.

The kernel uses the KInterruptEvent field of a KEvent when binding public interrupts per svcBindInterrupt request, whereas it internally uses a static object of another subclass to bind interrupt 0x0F (FIQ abstraction).