Linux kernel analysis-interrupt classification

Source: Internet
Author: User
Tags 0xc0
Preface: This article provides a broad description of interruptions, including the definition of interruptions, the classification of interruptions, the process of hardware interruptions in the computer, and

Preface: This article provides a broad description of interruptions, including the definition of interruptions, the classification of interruptions, the process of hardware interruptions in the computer, and the future prospects of interruptions. However, the interrupt handling process is not described in detail.

What is interruption?

The Linux kernel needs to manage all the hardware devices connected to the computer, which is undoubtedly part of it. To manage these devices, you must first communicate with them. Generally, there are two solutions to achieve this function:

Round Robin (Polling)Let the kernel regularly query the status of the device and then make corresponding processing; Interrupt (Interrupt)Enable the hardware to send signals to the kernel as needed (change the kernel to active hardware ).

The first solution will make the kernel do a lot of useless work, because round robin will always be executed cyclically repeatedly, consuming a lot of CPU time, so the efficiency is low, so the second solution is generally used.

For interrupt understanding, let's first look at a common example in our life: QQ. First, you are working, and your friends suddenly send you a window jitter, interrupting your ongoing work. The second case: of course, you may also check QQ every five minutes to see if there are friends looking for you, although this is a waste of your time. Here, a window jitter can be equivalent to a hardware interruption, and you are equivalent to a CPU. your job is to execute the CPU process. The scheduled query is equivalent to CPU polling. Here we can see that, as a way of communication between CPU and hardware, interruption is an active way of hardware, which is more effective than polling (CPU active, it's impossible for us to go through the friend list every few minutes.

CPU has a lot of work to deal with, not to do this a lot of useless. Of course, this is only common. Well, there is another problem here. every hardware device is interrupted. how can we differentiate different hardware? How do I know which one is from the hard disk and which one is from the network card when the device is interrupted at the same time? It's easy. isn't every QQ number different? Similarly, each hardware device in the system is assigned an IRQ number. this unique IRQ number can be used to distinguish between James and James.

From the perspective of physics, interruption is an electrical signal generated by hardware devices and directly sent to the input pin of the interrupt controller (such as 8259A, then the interrupt controller sends the corresponding signal to the processor. Once the processor detects this signal, it will interrupt the work it is currently processing and then process the interruption. After that, the processor will notify the OS that an interruption has occurred. In this way, the OS can properly handle this interrupt. Different devices have different interruptions, and each interruption is identified by a unique number. these values are generally called the interrupt request line.

APIC vs 8259A

The CPU of the X86 computer provides only two external pins for interruption: NMI and INTR. Among them, NMI is an unshielded interrupt, which is usually used for power loss and physical memory parity checks; INTR is a shielded interrupt, which can be blocked by setting the interrupt shielding bit, it is mainly used to receive interrupt signals from external hardware, which are transmitted to the CPU by the interrupt controller.

There are two common interrupt controllers:

1. programmable interrupt controller 8259A

Traditional PIC (Programmable Interrupt ControllerTwo 8259A external chips are connected in Cascade mode. Each chip can process up to 8 different IRQ. Since the INT output line of the PIC is connected to the IRQ2 pin of the main PIC, the number of available IRQ lines reaches 15, as shown in 1.

Figure 1: 8259A cascade schematic

2. Advanced Programmable Interrupt Controller (APIC)

The 8259A is only applicable to a single CPU. in order to fully explore the concurrency of the SMP architecture, it is critical to transmit the interruption to each CPU in the system. For this reason, Intel introduced a new component named I/O Advanced Programmable Controller to replace the older 8259A programmable interrupt controller. This component consists of two components: a local APIC, which is used to transmit interrupt signals to a specified processor. for example, a machine with three processors, it must have three local APIC pairs. Another important part is the I/o apic, which collects Interrupt signals from the I/O device and sends signals to the local APIC when those devices need to be interrupted, the system can have up to 8 I/O APIC.

Each local APIC has a 32-bit register, an internal clock, a local scheduled device, and two additional IRQ lines LINT0 and LINT1 reserved for local interruptions. All local APICS are connected to I/O APIC to form a multi-level APIC system, as shown in figure 2.

Figure 2: multi-level I/O APIC system

Currently, most single-processor systems contain an I/O APIC chip. you can configure this chip in two ways:

1) as a standard 8259A working method. The local APIC is disabled. the external I/O APIC is connected to the CPU, and the two LINT0 and LINT1 are connected to the INTR and NMI pins respectively.

2) as a standard external I/O APIC. The local APIC is activated, and all external interruptions are received by I/O APIC.

To identify whether a system is using an I/O APIC, run the following command on the command line:

# cat /proc/interrupts           CPU0         0:      90504    IO-APIC-edge  timer  1:        131    IO-APIC-edge  i8042  8:          4    IO-APIC-edge  rtc  9:          0    IO-APIC-level  acpi 12:        111    IO-APIC-edge  i8042 14:       1862    IO-APIC-edge  ide0 15:         28    IO-APIC-edge  ide1177:          9    IO-APIC-level  eth0185:          0    IO-APIC-level  via82cxxx...

If the IO-APIC is listed in the output, your system is using APIC. If you see a XT-PIC, it means your system is using an 8259A chip.

In the CPU integrated APIC, on SMP, there is a motherboard (at least one, some Motherboard has multiple IO-APIC, for better distribution of interrupt signal) global APIC, it receives interrupt signals from peripherals and distributes them to the CPU. The global APIC is called IO-APIC. Another part is the "local APIC", which is mainly responsible for transmitting the interrupt signal to the specified processor. for example, a machine with three processors, it must have three local APIC pairs.

Interrupt category

Interruption, in a broad sense, is usually defined as an event that triggers a change in the order in which the processor executes commands. In a narrow sense, for the 80x86 system, interruptions are divided into interruptions and exceptions, also known as synchronous interruptions and asynchronous interruptions. Do not confuse interrupt in the broad sense with interrupt in the narrow sense. in my post, all the so-called "interrupt" characters refer to the narrow sense of interrupt, that is, the details of Linux's 80x86 asynchronous interrupt processing. First, we must clarify the 80x86 system,

Interruption can be divided into synchronization (Synchronous) Interrupt and asynchronous (Asynchronous) Interruption:

1. synchronization interruption occurs when the command is executed by the CPU control unit. it is called synchronization because the CPU is interrupted only after the execution of a command is completed, rather than during the execution of the code command, for example, system call.

2. asynchronous interruption refers to the random generation by other hardware devices according to the CPU clock signal, that is, the interruption can occur between commands, such as keyboard interruption.

(PS: In summary, the asynchronous interrupt generated by the hardware during the interrupt, and the exception is the synchronous interrupt generated by the processor)

According to Intel official information, synchronization interruption is called an exception (ExceptionAsynchronous interrupt is called an interrupt (Interrupt).

Interruptions can be divided into shielded interruptions (Maskable interrupt) And unshielded interrupt (Nomaskable interrupt). Exceptions can be divided into faults (Fault), Traps (Trap), Terminate (Abort.

In a broad sense, interruptions can be divided into four categories:Interrupted,Fault,Traps,Termination. For the similarities and differences between these categories, see Table 1.

Table 1: interrupt categories and behaviors
Category Cause Asynchronous/synchronous Returned behavior
Interrupted Signals from I/O devices Asynchronous Always return to the next command
Traps Intentional exceptions Synchronization Always return to the next command
Fault Potential recoverable errors Synchronization Return to current command
Termination Unrecoverable errors Synchronization Not returned

Each interruption of the X86 architecture is assigned a unique number or vector (an 8-bit unsigned integer ). The unshielded interrupt and exception vectors are fixed, while the shielded interrupt vectors can be changed by programming the interrupt controller.

Interruption:
1. blocked interrupt: When the interrupt is blocked, the CPU control unit ignores it. All IRQ interruptions can be blocked.
2. unshielded interrupt: the CPU identifies and processes the interrupt. Therefore, it is a very urgent hardware fault.

Vector interrupt: the endpoint address of the interrupt service program provided by the hardware. when the interrupt is a vector interrupt, the system directly jumps to the pre-provided interrupt service program for execution. this processing method responds quickly.
Non-vector interrupt-the entry address of the interrupt service program provided by the software component. When an interrupt is a non-vector interrupt, the cpu jumps to a specified program for execution (called the interrupt parsing program) regardless of the External Interrupt source. in the parsing program, find the corresponding interrupt source by judging the corresponding interrupt status register and jump to the corresponding interrupt execution program. It is similar to the software interrupt processing method, but the soft interrupt (SWI) is different from the non-vector interrupt, and its entry is 0 x. After a soft interrupt occurs, the system changes to the management mode. The non-vector interrupt entry is 0 x. It directs the system to the fiq/irq mode. This processing method is simple, but the software query is used to determine the specific interrupted service program. all delays are long.

Vector interrupt mode is used for RESET, NMI, and exception handling. When a vector is interrupted, the controller directly assigns a value to the PC, for example, jump to 0x0000000d, and usually places the ISR service program address ldr pc, = ISR_HANDLER at the 0x0000000d address.
In non-vector interrupt mode, there is a register identifier to jump to a unified function address, which is used to identify the Register identifier and priority relationship for interrupt processing. In vector interrupt mode, when the CPU reads the IRQ interrupt command at 0x18, the system automatically reads the command at the address determined by the interrupt source to replace the command at 0x18, the jump command system directly jumps to the corresponding address function, saving the interrupt processing time and improving the interrupt processing speed. For example, if the vector address of the ADC interrupt is 0xC0, run the following code at 0xC0: ldr PC, = HandlerADC. when the ADC is interrupted, the system automatically jumps to the HandlerADC function to handle the interrupt.
The non-vector interrupt mode is a traditional interrupt processing method. when the system is interrupted, the system maps the Mark location in the INTPND register, then jump to the unified interrupt function at 0x18, which reads the corresponding flag in the INTPND register to determine the interrupt source, based on the priority relationship, jump to the processing code of the corresponding interrupt source to process the interrupt.

Introduction to Linux 2.6 interrupt handling principles

Interrupt Descriptor Table (Interrupt Descriptor Table, IDTIs a system table that is associated with every interrupt or exception vector. each vector is stored in the table as the entry address of the corresponding interrupt or exception handling program. Before the kernel can interrupt, that is, during system initialization, the initialization address of the IDT table must be loaded into the idtr register to initialize each item in the table.

In real mode, the IDT is initialized and used by the BIOS program. However, once Linux starts to take over, the IDT is moved to another ARM region and initialized for the second time because Linux does not use any BIOS program, use your own specialized interrupt service program (routine )(Interrupt service routine, ISR). Interrupt and exception handling programs are similar to conventional C functions.

There are three main data structures that contain all IRQ-related information: hw_interrupt_type, irq_desc_t, and irqaction, which explain how they are associated.

Figure 3 relationship between IRQ structures

In X86 systems, for different types of interrupt controllers 8259A and I/O APIC, the hw_interrupt_type struct is assigned different values,

In the interrupt initialization phase, call the hw_interrupt_type variable to initialize the handle member in the irq_desc_t structure. In earlier systems, the 8259A cascade is used, so i8259A_irq_type is used for initialization. for SMP systems, the handle variable is either initialized using ioapic_edge_type or ioapic_level_type.

For each peripheral, you can register an interrupt handler with the Linux kernel either statically (declared as a global variable of the static type) or dynamically (calling the request_irq function. Regardless of the registration method, an irqaction structure (handler points to the interrupted service program) is declared or assigned, and then the setup_irq () function is called to associate irq_desc_t with irqaction.

When an interrupt occurs, the interrupt service program entry address is obtained through the interrupt descriptor table IDT. for the interrupt vector between 32 ≤ I ≤ 255 (I =128), a push $ i-256 is executed, jmp common_interrupt command. The do_IRQ () function will be called to obtain the action pointer using the break vector as the subscript of the irq_desc [] structure, and then call the interrupt service program pointed to by handler.

From the above description, we can easily see the entire interrupted process, as shown in 4:

Figure 4: X86 disconnection

 

Thread interruption

Thread interruption is an important step to achieve real-time Linux. in the standard Linux kernel, the execution unit with the highest priority during interruption, no matter what the kernel code is processing at the time, as long as there is an interruption event, the system will immediately respond to the change event and execute the corresponding interrupt processing code, unless the interrupt is disabled at that time. Therefore, if the system has serious network or I/O loads, the interruption will be very frequent, and real-time tasks will be difficult to run. that is to say, there is no real-time performance.

Application background

Linux real-time requirements. after the thread is interrupted, the interrupt will run as the kernel thread and give different real-time priorities. the real-time task can have a higher priority than the interrupt thread. in this way, real-time tasks can be run as execution units with the highest priority, even under severe loads.

Another important reason for thread interruption is that the spin lock is replaced by mutex. In the interrupt processing code, the spinlock is used in a large amount. when the spinlock is replaced by mutex, the interrupt processing code may be attached to the waiting queue because the lock is not obtained, however, only the scheduling process can do this. if the interrupt processing code still uses the original spinlock, the efforts of replacing the mutex with the spinlock will be greatly reduced. therefore, to meet this requirement, the interrupt must be threaded, including IRQ and softirq.

Implementation principle

Now the thread is implemented as the kernel R-T Patch, not the mainstream, is a real-time Patch. Let's take a brief look at the entire implementation process. [4] [5]

Interrupt initialization: the initialization of the vector table started during system boot. By calling setupIdt initializes each item in the table to the default interrupt service routine ignoreInt. This default routine only prints the interrupt vector number, so further initialization is required.When the kernel () function initializes the kernel, it calls the initThe IRQ () function initializes the interrupt for the second time.Set the IDT table item corresponding to I to interrupt.I. This part is already running in protection mode. In startCall our thread initialization function init at the end of the kernel.Hardirqs, which creates a kernel thread for each IRQ. The highest real-time priority is 50, and so on until 25, so the lowest real-time priority of any IRQ thread is 25.

Interrupt handling process: if the IRQIf NODELAY is set, the interrupt cannot be made thread-based. In the interrupt processing phase, the similarities and differences between the two are mainly reflected in: the same part of the two is that when the interrupt occurs, the CPU will call doIRQ () function to handle the corresponding interrupt, doIRQ () calls _ do after necessary processing.IRQ (). The biggest difference between the two is thatDoIn the IRQ () function, it determines whether the interrupt has been threaded (if the status field of the interrupt descriptor does not contain IRQThe NODELAY flag indicates that the interrupt is threaded.) handle is called directly for non-threaded interruptions.IRQ_event () function.

For a thread-based situation, call wakeUpThe process () function wakes up the interrupt processing thread and starts running. the kernel thread will call doHardirq () to handle the corresponding interrupt. This function will determine whether there is an interrupt to be processed. If yes, it will call handle.IRQEvent. HandleIRQ_event () directly calls the corresponding interrupt processing function to complete the interrupt processing.

Problems that need to be considered after the thread is made

Once the thread is interrupted, the interrupt will run in the process context, and all the constraints of the interrupt context will no longer exist here. We can also dynamically set a priority level for thread-based interruptions. So what should we think about the revolutionary change that interrupts the world:

Do I need the lower half?

After the thread is interrupted, the interrupt can run with the process context, without the constraint of the interrupt context. So we still need the lower half, because all the things we can do in the lower half can now be implemented through thread-based interruption. In my personal opinion, I don't think that the lower half can be easily eliminated at this time. First, the thread-based interruption must be improved and standardized. Now it is only provided as a patch in the kernel, but it still needs to be tested. Secondly, thread interruption is not omnipotent. many of our tasks cannot be implemented by thread interruption. we will discuss it later. In addition, the lower half is used as an auxiliary interrupt processing program to complete the push-back execution. in some cases, it still plays an irreplaceable role.

Combined with CPU affinity

Like interrupt affinity, CPU also has affinity. The so-called CPU affinity means to bind one or more processes to one or more processors by setting CPU affinity. Once the thread is interrupted, the thread can be viewed from the process (or thread) point of view, which makes it possible to combine thread interruption with CPU affinity. For thread-based interruptions, we can set CPU affinity to limit thread migration and optimize CPU Cache usage. Of course, there may be many applications, which is also the research direction. Threading may not always be good

Not all interruptions can be made thread-based, such as clock interruption, which is mainly used to maintain the system time and timer. the timer is the pulse of the operating system, it may be suspended, and the consequences will be unimaginable, so it should not be threaded. There are also serial ports. So even if we can thread our interrupt, it doesn't mean we should all thread our interrupt.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.