Interrupt classification
In Linux systems, interrupts are divided into:
? Soft interrupts are the bottom-half processing part of the Linux system interrupt processing and are interrupts of the Linux simulation. In order to speed up the processing of hardware interrupt, to prevent the loss of data, Linux interrupt processing is divided into the top half processing and the bottom half processing two parts, the top half processing program to quickly deal with hardware events, not so urgent logic in the end of the semi-processing program, you can simply think that the hard terminal processing program is the top half processing program, The soft interrupt handler is the bottom half handler. Soft interrupts are typically performed only after the hard interrupt handler is executed. However, when the hard interrupt is nested, the soft interrupt will be processed after all the hard interrupts are processed, and when the soft interrupt is too much, it will be processed in the KSOFTIRQD thread.
Kernel Initialization-Interrupt
Intel processors have 256 hard interrupt numbers. The first 32 interrupt numbers are used for exceptions and are initialized when the kernel is initialized. The kernel initialization code flow is as follows:
You can see that exception handling is initialized first, partial external interrupts are initialized, and part of the soft interrupt processing is initialized.
void __init start_kernel(void){ lock_kernel(); ... //初始化调度模块 sched_init(); ... sort_main_extable(); // 初始化异常处理。 trap_init(); ... // 初始化外部中断 init_IRQ(); ... // 初始化定时器模块,同时,会注册定时器的软中断处理函数。 init_timers(); // 初始化软中断) softirq_init(); time_init(); ... // 初始化 acpi_early_init();}
Exception Interrupt Initialization
An exception interrupt is called a trap in the kernel, and the exception interrupt initialization code is
//Gate initialization. Initializes the interrupt vector table. The system has a fixed 256 hardware interrupt vector. void__init Trap_init (void) {Set_intr_gate (0, ÷_error); Set_intr_gate_ist (1, &debug,debug_stack); Set_intr_gate_ist (2, &nmi,nmi_stack); Set_intr_gate (3, &INT3); Set_system_gate (4, &overflow);/ * int4-5 can called from all */Set_system_gate (5, &bounds); Set_intr_gate (6, &INVALID_OP); Set_intr_gate (7, &device_not_available); Set_intr_gate_ist (8, &double_fault, Doublefault_stack); Set_intr_gate (9, &coprocessor_segment_overrun); Set_intr_gate (Ten, &INVALID_TSS); Set_intr_gate ( One, &segment_not_present); Set_intr_gate_ist ( A, &stack_segment,stackfault_stack); Set_intr_gate ( -, &general_protection); Set_intr_gate ( -, &page_fault); Set_intr_gate ( the, &spurious_interrupt_bug); Set_intr_gate ( -, &coprocessor_error); Set_intr_gate ( -, &alignment_check);#ifdef CONFIG_X86_MCESet_intr_gate_ist ( -, &machine_check, Mce_stack);#endifSet_intr_gate ( +, &simd_coprocessor_error);#ifdef config_ia32_emulationSet_system_gate (Ia32_syscall_vector, Ia32_syscall);#endifSet_intr_gate (Kdb_vector, call_debug);/** Should is a barrier for any external CPU state. */Cpu_init ();}
Summarized as follows:
Interrupt Vector Number |
Exception Events |
Linux Processing program |
0 |
Division Error |
Divide_error |
1 |
debugging exceptions |
Debug |
2 |
NMI Interrupt |
Nmi |
3 |
Single byte, int 3 |
Int3 |
4 |
Overflow |
Overflow |
5 |
Boundary monitoring interrupted |
Bounds |
6 |
Invalid operation code |
Invalid_op |
7 |
Device Not available |
Device_not_available |
8 |
Double fault |
Double_fault |
9 |
Coprocessor Segment Overflow |
Coprocessor_segment_overrun |
10 |
Invalid TSS |
Incalid_tss |
11 |
Missing segment Interruption |
Segment_not_present |
12 |
Stack exception |
Stack_segment |
13 |
General Protection exceptions |
General_protection |
14 |
Page exception |
Page_fault |
15 |
|
Spurious_interrupt_bug |
16 |
Coprocessor Error |
Coprocessor_error |
17 |
Alignment Check Interrupt |
Alignment_check |
0x80 |
System calls |
Ia32_syscall |
0xf9 |
Kernel debugging |
Call_debug |
The above interrupt processing functions are written in assembly language. Part of the assembly is processed directly, and part of it is handled by invoking the C function.
Assembly code in linux/arch/x86_64/entry.S
, most of the call C function do_中断处理函数名
processing.
Tidy up as follows:
Interrupt Vector Number |
Exception Events |
Linux Compilation |
Call C function |
Processing Results |
0 |
Division Error |
Divide_error |
Do_divide_error |
Send SIGFPE Signal |
1 |
debugging exceptions |
Debug |
Do_debug |
Send Sigtrap Signal |
2 |
NMI Interrupt |
Nmi |
Do_nmi |
|
3 |
Single byte, int 3 |
Int3 |
Do_int3 |
Send Sigtrap Signal |
4 |
Overflow |
Overflow |
Do_overflow |
Send SIGSEGV Signal |
5 |
Boundary monitoring interrupted |
Bounds |
Do_bounds |
Send SIGSEGV Signal |
6 |
Invalid operation code |
Invalid_op |
Do_invalid_op |
Send Sigill Signal |
7 |
Device Not available |
Device_not_available |
Math_state_restore |
Send SIGSEGV Signal |
8 |
Double fault |
Double_fault |
Do_double_fault |
|
9 |
Coprocessor Segment Overflow |
Coprocessor_segment_overrun |
Do_coprocessor_segment_overrun |
Send SIGFPE Signal |
10 |
Invalid TSS |
Invalid_tss |
Do_invalid_tss |
Send SIGSEGV Signal |
11 |
Missing segment Interruption |
Segment_not_present |
Do_segment_not_present |
Send Sigbus Signal |
12 |
Stack exception |
Stack_segment |
Do_stack_segment |
|
13 |
General Protection exceptions |
General_protection |
Do_general_protection |
|
14 |
Page exception |
Page_fault |
Do_page_fault |
Handling Missing pages interrupts |
15 |
|
Spurious_interrupt_bug |
Do_spurious_interrupt_bug |
|
16 |
Coprocessor Error |
Coprocessor_error |
Do_coprocessor_error |
Send SIGFPE Signal |
17 |
Alignment Check Interrupt |
Alignment_check |
Do_alignment_check |
Send Sigbus Signal |
0x80 |
System calls |
Ia32_syscall |
|
|
0xf9 |
Kernel debugging |
Call_debug |
Do_call_debug |
|
External interrupt Initialization
中断控制器硬件APIC分为两种:本地APIC和全局APIC。本地APIC集成在CPU内部,每个CPU都有一个,用于处理本地中断请求,CPU可以通过APIC向其他CPU发送中断,现在主要用于CPU之间的通信(IPI)。全局APIC主要是连接外部设备,用于外部设备的中断。在内核中断初始化的时候,会初始化三个与IPI相关中断。
void__init INIT_IRQ (void){intI/*** This function is mainly to initialize the hardware* 1. Initialize the local APIC control chip* 2. Initialize 8259A chip /Init_isa_irqs (); /** Empty the interrupt vector table after 32. (except for system calls and interrupt numbers for kernel debugging) */ for(i =0; I < (nr_vectors-first_external_vector); i++) {intVector = First_external_vector + i;if(I >= Nr_irqs) Break;if(Vector! = ia32_syscall_vector && vector! = kdb_vector) {set_intr_gate (vector, interrupt[i]); } }//Multi-processor communication interrupt#ifdef CONFIG_SMPSet_intr_gate (First_device_vector, interrupt[0]); Set_intr_gate (Reschedule_vector, reschedule_interrupt); Set_intr_gate (Invalidate_tlb_vector, invalidate_interrupt); Set_intr_gate (Call_function_vector, call_function_interrupt);#endif//local APIC Interrupt#ifdef config_x86_local_apic / * Self generated IPI for local APIC timer * /Set_intr_gate (Local_timer_vector, apic_timer_interrupt); Set_intr_gate (Spurious_apic_vector, spurious_interrupt); Set_intr_gate (Error_apic_vector, error_interrupt);#endifSetup_timer ();if(!acpi_ioapic) Setup_irq (2, &IRQ2);}
Summarized as follows:
Interrupt Vector Number |
Interrupt Name |
Exception Events |
Interrupt handler function |
Call C function |
Processing Results |
0xFC |
Reschedule_vector |
Interrupts between processors, for classmates between CPUs, other CPUs require re-scheduling |
Reschedule_interrupt |
Smp_reschedule_interrupt |
Set the thread dispatch flag to be re-dispatched. The thread is then re-dispatched when the kernel checks for flags |
0xfd |
Invalidate_tlb_vector |
Interrupts between processors for inter-CPU communication, and other CPUs require TLB cache invalidation |
Invalidate_interrupt |
Smp_invalidate_interrupt |
CPU Flush TLB |
0xfa |
Call_function_vector |
Interrupts between processors for communication between CPUs, allowing additional CPUs to call a function |
Call_function_interrupt |
Smp_call_function_interrupt |
The function data is passed through call_data_struct, and the CPU calls the function |
0xEF |
Local_timer_vector |
APIC Timer Interrupt |
Apic_timer_interrupt |
Smp_apic_timer_interrupt |
Soft Interrupt for Trigger timer |
0xFF |
Spurious_apic_vector |
Pseudo Interrupt |
Spurious_interrupt |
Smp_spurious_interrupt |
Ignore |
0xFE |
Error_apic_vector |
APIC Error |
Error_interrupt |
Smp_error_interrupt |
Print error |
0XFA Interrupt Description:
When the CPU needs another CPU to execute a function, it only needs to initialize
struct call_data_struct { void (*func) (void *info); void *info; atomic_t started; atomic_t finished; int wait;};
Structure, then issue a 0XFA interrupt.
Soft interrupt Initialization
Soft interrupt initialization is divided into two parts:
- When the timer is initialized, the TIMER_SOFTIRQ soft interrupt is turned on and the interrupt handler is set to RUN_TIMER_SOFTIRQ.
- The Softirq_init function executes, and the TASKLET_SOFTIRQ and HI_SOFTIRQ are opened, and the processing functions are tasklet_action and tasklet_hi_action respectively.
The threading mechanism for soft interrupts is not said.
Linux x86_64 Kernel Interrupt initialization