Interprocessor interrupts allow a CPU to send interrupt signals to any other CPU in the system. As explained in the section "The Advanced Programmable Interrupt Controller (APIC).
On multiprocessor systems, Linux makes use of three kinds of interprocessor interrupts
Sent to all CPUs but the sender, forcing those CPUs to run a function passed by the sender. The corresponding interrupt handler is named call_function_interrupt( )
. The function (whose address is passed in the call_data global variable) may, for instance, force all other CPUs to stop, or may force them to set the contents of the Memory Type Range Registers (MTRRs). Usually this interrupt is sent to all CPUs except the CPU executing the calling function by means of the smp_call_function( )
facility function.
When a CPU receives this type of interrupt, the corresponding handler — named reschedule_interrupt( )
— limits itself to acknowledging the interrupt. Rescheduling is done automatically when returning from the interrupt (see the section "Returning from Interrupts and Exceptions.
Sent to all CPUs but the sender, forcing them to invalidate their Translation Lookaside Buffers. The corresponding handler, named invalidate_interrupt( )
, flushes some TLB entries of the processor as described in the section "Handling the Hardware Cache and the TLB.
The assembly language code of the interprocessor interrupt handlers is generated by the BUILD_INTERRUPT macro: it saves the registers, pushes the vector number minus 256 on the stack, and then invokes a high-level C function having the same name as the low-level handler preceded by smp_. For instance, the high-level handler of the CALL_FUNCTION_VECTOR interprocessor interrupt that is invoked by the low-level call_function_interrupt( )
handler is named smp_call_function_interrupt( )
. Each high-level handler acknowledges the interprocessor interrupt on the local APIC and then performs the specific action triggered by the interrupt.
Thanks to the following group of functions, issuing interprocessor interrupts (IPIs) becomes an easy task:
send_IPI_all( )
Sends an IPI to all CPUs (including the sender)
send_IPI_allbutself( )
Sends an IPI to all CPUs except the sender
send_IPI_self( )
Sends an IPI to the sender CPU
send_IPI_mask( )
Sends an IPI to a group of CPUs specified by a bit mask[1]