Interruption is a more difficult and important part of the Linux kernel. Understanding these things is the first and foremost step. The so-called difficulties and new knowledge, if fully understanding the principles, are at least equivalent to mastering 80%. This is the same for any knowledge. The so-called true understanding is to fully understand this thing, the reason for the introduction and how to introduce it, especially the relationship with other modules, as well as many ideas contained in it.
The Linux kernel serves as a bridge between upper-layer software and underlying hardware. For the upper layer, providing system calls (of course, it is an interrupt, that is, the 128 or 0x80 vector). For the hardware, providing the interrupt mechanism is an important part. Of course, there are other aspects, I will not talk about it for the moment.
0. Interrupt Overview:
In short, the CPU is busy doing its own thing. At this time, the hardware (for example, the keyboard pressed) triggers an electrical signal, which is broken through to reach the interrupt controller 8259a, the 8259a receives this signal, sends an int signal to the CPU to request the CPU to perform the hardware operation just now, and sends the interrupt type number to the CPU. At this time, the CPU will leave what it is doing, however, instead of just throwing it aside, we saved the relevant information about the current task and processed the application, find its interrupt vector (that is, the address of the interrupt program in the memory) based on the interrupt type number, and then execute this program (this program is already written in the memory ), after the execution, send an INTA signal to 8259a, indicating that I have processed your application. This time
The CPU can continue to do what it was just interrupted. At this time, the information saved just now will help the CPU to execute the following program, instead of forgetting what it was just doing.
There are four keywords mentioned above:
Interrupt source: here the interrupt source refers to the CPU interruption event, which cannot be discussed without interruption in the source. It can be either hardware or software.
CPU: Needless to say, the interruption is to use the CPU to handle some things.
Interrupt Controller 8259a: a bridge between the hardware interrupt source and the CPU. The CPU cannot be known without interruption.
Service interruption program: If you interrupt the CPU, the CPU will have to work for you according to this program.
1. Let's talk about 8259a.
On our common X86 platform, 8259a is a chip designed specifically to interrupt control of 8085a and 8086/8088. It is an interrupt controller that can be controlled by a program. I thought that when I learned 8086, the teacher also talked about. At that time, it was just a matter of learning, mechanical memory, and why I didn't understand it. Looking back, a single 8259a can manage eight-Level Vector priority interruptions. When other circuits are not added, a maximum of 64-Level Vector Optimization interrupt systems can be connected. The 8259a works in multiple ways and can be used in various systems. Various work methods are set through software during initialization.
Under the control of the bus controller, the 8259a chip can be in the programming and operation state. The programming State is the State where the CPU uses the in or out command to initialize the 8259a chip.
For example, an 8259a chip chart:
The main function of 8259a is to accept external interrupt requests in a system with multiple interrupt sources and make judgments, and select the interrupt requests with the highest priority currently, send the request to the intr end of the CPU. When the CPU responds to the interrupt and enters the processing process of the interrupt subroutine, the interrupt controller is still responsible for managing the external interrupt requests.
2. 8259a and how it communicates with the CPU
An external interrupt request signal is transmitted to the IMR (Interrupt shield register) through the interrupt request line IRQ. The IMR determines whether to discard or accept the preset interrupt shield word (ocw1. If acceptable, 8259a indicates the position of the IRQ In the IRR (interrupt request storage register) to indicate that the IRQ has an interrupt request signal, at the same time, a signal is sent to the intr (interrupt request) pin of the CPU. However, the CPU may be executing a command, so the CPU does not respond immediately. When the CPU is busy executing a certain command, there may be other IRQ lines sending interruptions. Please, these requests will accept the selection of IMR. If the request is not blocked, these requests will also be put in IRR, that is, the corresponding bit representing their IRQ in IRR will be set to 1.
The figure consists of two 8259a cascade units, which can respond to 15 interrupt sources. The figure shows that the hardware is connected to the 8259a interrupt request line.
[Illustration 8259a interrupt controller]
When the CPU executes a command, it checks whether the intr pin has a signal. If a signal is found, the service will be switched to the interrupted service. At this time, the CPU will immediately send a signal to the INTA (interrupt response) pin of the 8259a chip. When the chip receives this signal, the tuning component starts to work. In IRR, it selects the highest-priority interrupt and sends the interrupt request to the ISR (interrupt service register ), this means that the IRQ position is represented in ISR, and the corresponding position in IRR is zero, indicating that the interrupt is being processed by the CPU. At the same time, write its number to the lower three digits of the interrupt vector register IVR (IVR is specified by icw2. Do you still remember that the lowest three digits of icw2 are 0 at the specified time, here, they are used !) At this time, the CPU sends a second INTA signal. After receiving this signal, the chip sends the content in the IVR, that is, the interrupt number, to the data line leading to the CPU.
This content seems very complicated, but it would be easy to understand if we use a simple metaphor. The CPU is equivalent to the boss of a company, and the 8259a chip is equivalent to the secretary of the boss. Now many people want to see the boss, but the boss is making a phone call, so he is handed over to the Secretary for reception. Every person who wants to see the boss needs to hand over his/her business card to the secretary. The secretary should first look at the business card. Is there anyone who explicitly says he/she doesn't want to see? If not, put it in a box. At this time, the boss's phone number is not complete yet, but some people keep handing the business card to the boss to see the boss, the Secretary will put all the cards that meet the requirements in the box. The boss called me and asked the Secretary: do anyone want to see me? At this time, the secretary selects the highest level from the box and puts his name
The film is handed over to the boss.
Here, we need to understand that interruption blocking is not the same as priority determination. If it is blocked, there will be no chance to participate in the determination. By default, irq0 has the highest priority and irq7 has the lowest priority. Of course, we can change this setting, which is described in detail below.
When the chip sends the interrupt number to the data line to the CPU, it checks whether EOI in icw4 is set. If EOI is set to a bit, it indicates that the interrupt request signal needs to be cleared automatically, and the chip automatically clears the corresponding bit in ISR. If EOI is not set, interrupt the processing program to send The EOI message to the chip. After receiving the EOI message, the chip clears the corresponding bits in the ISR.
The authorities here exist in such a place. Priority determination exists in the 8259a chip. If the CPU is processing an irq1 disconnection, the bit corresponding to irq1 in ISR is set to 1. In this case, an irq2 interrupt request is sent. The 8259a will compare it with the bits in the ISR and find that the bits corresponding to irq1 higher than it are set, so 8259a will regret to tell irq2: you should wait in IRR first. If irq0 comes at this time, the chip will immediately let it into the ISR, that is, the position corresponding to irq0 In the ISR, and send the interrupt request to the CPU. At this time, because irq1 is still being processed by the CPU, the irq1 bit in ISR is still set.
The priority of irq0 is high, so the bit of irq0 is also set and a new interrupt request is sent to the CPU. At this time, the irq0 and irq1 bits in ISR are both set. This often happens during multiple interruptions and is normal.
If EOI is set to automatic, the bits in ISR are always cleared (when EOI is set to automatic, 8259a clears the corresponding bits in ISR as long as the interrupt number is sent to the CPU. That is, if there is an interrupt, the chip will immediately send an interrupt request to the CPU, even if the CPU is processing irq0 interruption, the CPU does not know who has a high priority. It simply responds to the interruption sent by 8259a. Therefore, in this case, a low-priority interrupt may interrupt the high-priority interrupt service program. Therefore, in the PC, we always clear The EOI bit, and send the EOI message only when the interrupted service program ends.
Next, let's take a look at the Linux interruptions. The results will be better.
3. Categories of interruptions
In the early stage and in general, what we call an interruption refers to the interruption caused by peripherals. With the rapid development of the computer, the interruption is no longer limited to external devices, and the CPU itself will interrupt, but we call this interruption an exception.
For the X86 architecture, there are two types of interruptions: Synchronous interruption and asynchronous interruption. Synchronization interruption is the exception we mentioned above. It is generated when the CPU executes an invalid command. Synchronization is called because the interrupt request signal is synchronized with the code command. That is to say, the CPU will interrupt the execution of a command only after it is executed, rather than during the execution of the Code command. Asynchronous interruption is the interruption caused by external devices, which can occur at any time. In our habit, asynchronous interruption is still called an interruption.
Interruptions can be divided into Maskable Interrupt and nomaskable interrupt ). Exceptions can be divided into fault, trap, and abort.
Blocked interruptions are mainly the interruption signals generated by external devices. unshielded interruptions generally refer to interruptions caused by hardware in the computer. The exception is the interrupt signal sent by the CPU and has nothing to do with the interrupt controller (as described below). Therefore, the exception cannot be blocked. There are some similarities between exceptions and unshielded interruptions: they are not related to external devices and cannot be blocked.
The interrupt mentioned above is only one of the interrupt families called hardware interrupt. In general, the interrupt can be divided into internal interrupt and External Interrupt. The internal interrupt is also called an exception, which is generated by the CPU, when the processor executes a wrong command caused by programmer programming, such as a division of 0, these will cause internal interruption, and external interruption (hardware interruption) it is generally caused by hardware interruptions, such as the keyboard.
Here we will summarize the categories to avoid confusion.
The first classification method:
Hardware interruption: Also called asynchronous interruption.
Software interruption: Also called an exception, synchronous interruption
Method 2:
Shielded interrupt: the interrupt signal generated by an external device
Unblocking interruption: interruption of computer hardware
4. Interrupt number
In this example, the interrupt number refers to the number of the external interrupt, that is, the hardware interrupt. The system allocates a number for each "interrupt request line", and x86 uses two 8259a, there are a total of 15 interrupt numbers, but with the increase of peripherals, these certainly cannot meet the needs, so multiple peripherals share an interrupt number. The interrupt number is used to indicate that the device has an interruption, for example, the irq0 that is used as a clock interruption. In this way, the CPU can know that the device has encountered an interruption and then process it.
5. interrupt vector
Inter x86 supports a total of 256 vector interruptions. to easily identify each type of interrupt source and number them from 0 to 255, Inter calls this integer the interrupt vector, linux allocates the 256 interrupt vectors as follows:
0 ~ 31 indicates abnormal and unshielded interruptions.
32 ~ 47 shielded interrupt (Hardware Interrupt)
48 ~ 255 is used to indicate soft interruptions. in Linux, only one of the 128 or 0x80 vectors is used as the system call.
The relationship between the interrupt number and the interrupt vector is: interrupt number + 32 = interrupt vector. The functions of the interrupt vector are described below.
Interrupt Descriptor Table (IDT): A table, also called an interrupt vector table. Each table item is called a gate descriptor, which occupies 8 bytes, simply put, it is used to store the endpoint function address of the interrupt handler. Of course, it includes some other information. When an interrupt occurs, we determine the break Vector Based on its break number, and then find its entry function in this table to execute it. How can we find this table in a memory area? This requires a system register Interrupt Descriptor register idtr. during system initialization, an assembly command LIDT can load the address of the Interrupt Descriptor Table into idtr, with the idtr48 bit, the field is installed in Low-text (16-bit low)
Limited. The base address is installed in high dual-text (32-bit high.
6. service interruption routine
In response to a specific interrupt, the kernel executes a function called the interrupt service routine (interrupt service routine, ISR ). Related interrupt service routines are defined in the driver of each device. The following code shows that the interrupt service routine has two parameters: int type and void type. And the returned value is irqreturn_t.
//linux/include/linux/interrupt.htypedef irqreturn(*irq_handler_t)(int,void*) //linux/include/linux/irqreturn.henum irqreturn {IRQ_NONE, IRQ_HANDLED, IRQ_WAKE_THREAD, }; typedef enum irqreturn irqreturn_t;
Irqreturn_t is an enumeration type, so it is essentially an integer. In addition, the values of irq_none, irq_handled, and irq_wake_thread are 0, 1, and 2 at a time. Irq_none indicates that the received interrupt request is not processed; irq_handled indicates that a valid interrupt request is received and processed correctly (this is discussed in detail later ).
It should be noted that when an interrupt service routine is being executed, all the processors on which the interrupt is located will be blocked to avoid continuing to accept another interruption on the same interrupt line.
The above are the basic concepts of interruptions. After understanding them, it is easy to analyze the interruptions.
[Reference]
1. Baidu documentation
2. 8086/88 Assembly Language
3. Chen Lijun's blog