Interrupts are the mechanism by which hardware and software interact, the entire operating system, the entire architecture, is driven by interrupts. The initiation of an interrupt goes through three phases: the device generates the interrupt signal, the interrupt controller interprets the signal, and the CPU actually processes the signal.

The previous article mentioned some PIC, PIC only used for single processor, for today’s multi-core multi-processor era, PIC can not do much, so there is a more advanced interrupt controller APIC, APIC is divided into two parts, LAPIC and IOAPIC, the former LAPIC is located inside the CPU. Each CPU has a LAPIC, which the IOAPIC connects to peripherals. The interrupt signal sent by the peripheral is processed by the IOAPIC and then sent to one or more LAPics. Then the LAPIC decides whether to send the interrupt signal to the CPU for actual processing. The overall APIC of p6 family processor is as follows:

It can be seen that each CPU has a LAPIC, and the IOAPIC is a system chipset. Each interrupt message is sent and received through the bus. There are many and complex contents about APIC. For detailed description, please refer to the Intel manual. This article does not discuss the details, but only describes the process of interruption in the upper level at a more abstract level to clarify the process of interruption in APIC mode.

IOAPIC

The IOAPIC is mainly responsible for receiving external hardware interrupts, translating the interrupt signals generated by the hardware into messages with a certain format, and then sending the messages to one or more LAPics through the bus. IOAPIC has the following main components:

  • 24 interrupt pins, an IOAPIC supports 24 interrupts
  • A 24-item PRT (Programmable Redirection Table), each entry a 64-bit register
  • Some programmable registers, such as window registers, version registers, etc
  • An information unit that sends and receives APIC information through the APIC bus

Redirection Table Entry (RTE)

The most important thing to understand IOAPIC’s work is to understand the redirection entries/registers. Each pin corresponds to a 64-bit redirection entry.

This entry/register contains all the information about the properties of the interrupt, how the interrupt was triggered, the mode of transmission status, pin polarity, etc. This diagram is from Interrupt in Linux. It should be clear to explain each field.

  • The Destination field and Destination Mode fields determine which lapics or lapics the interrupt is sent to

  • An important part of the interrupt controller’s job is to translate the interrupt signal into an interrupt vector. The interrupt vector is the index of the IDT. The interrupt descriptor in the IDT contains the address of the interrupt handler. In PIC, vector= starting vector+IRQvector= starting vector+IRQvector= starting vector+IRQ, while in APIC mode, The VECotr corresponding to the IRQ is allocated by the operating system when the IOAPIC is initialized.

  • IOAPIC pins have no priority, unlike PIC’s IRQ0 which has a higher priority than IRQ1, and IOAPIC’s interrupt priority is determined by the vector field of the redirection entry corresponding to the pins.

When an IOAPIC pin receives an interrupt signal from a peripheral, it formats an interrupt message according to the corresponding redirect entry, and then sends it to the LAPIC listed in the Destination field.

LAPIC

LAPIC is much more complex than IOAPIC. Its main function is to receive interrupt messages and submit them to the CPU for processing. Moreover, LAPIC itself can also be used as an interrupt source to generate interrupts and send them to itself or other cpus. So LAPIC can actually receive outages from three sources:

  • Local interruption: clock, temperature monitoring, etc
  • External interrupt: from IOAPIC
  • IPI: Interprocessor interrupt, from another LAPIC

In the INEL manual, there are more sophisticated classifications, but I think it’s enough to understand these three categories. To understand LAPIC, start with some of its important registers, and see how LAPIC works through the functions of these registers:

Main register

IRR(Interrupt Request Register)

Interrupt request register, 256 bits, each representing an interrupt. When an interrupt message is sent, if the interrupt is not masked, set the IRR bit to 1, indicating that the interrupt request is received but not processed by the CPU.

ISR(In Service Register)

Registers in service, 256 bits, each representing an interrupt. When an interrupt request in the IRR is sent to a CPU, the BIT of the ISR is set to 1, indicating that the CPU is processing the interrupt.

EOI(End of Interrupt)

End interrupt register, 32 bits. Write EOI to indicate that interrupt processing is complete. Writing to the EOI register causes LAPIC to clean up the corresponding bit of the ISR. For level-triggered interrupts, an EOI message is sent to all ioAPics informing them that the interrupt processing is complete.

ID

It uniquely identifies a LAPIC. A LAPIC corresponds to a CPU one by one. Therefore, a CPU is also identified by its LAPIC ID.

TPR(Task Priority Register)

Task priority register, which determines what priority interrupts the current CPU can handle. The CPU only handles interrupts of higher priority than in TPR. Interrupts lower than this are temporarily blocked, i.e. continue to wait in the IRR.

In addition, the priority level is vector/16. The priority level is vector/16, and the vector is the interrupt vector sign for each interrupt.

PPR(Processor Priority Register)

Processor priority register, which indicates the priority of the interrupts currently being processed and is used to determine whether interrupts in the IRR are sent to the CPU. Interrupts in the IRR are sent to the processor only if their priority is higher than that of the processor. The value of PPR is the interruption with the highest priority of the positive service in ISR and the one with the highest priority of TPR. Therefore, TPR temporarily shields the interrupts with the lower priority than TPR by indirectly controlling PPR.

SVR(Spurious Interrupt Vector Register)

This register can be set To enable the APIC To work.

ICR(Interrupt Command Register)

Interrupt instruction register. When a CPU wants to send an interrupt to another CPU, it fills in the ICR with the corresponding interrupt vector and target LAPIC identifier, and then sends a message to the target LAPIC through the bus. The FIELDS in the ICR register are similar to the IOAPIC redirection entries, including Destination Field, Delivery Mode, Destination mode, level, and so on.

Here are some registers for local interrupts

Local interrupt

The Local Vector Table (LVT) is a configuration Table that acts as the interrupt source itself. It consists of 7 items (which may vary according to the architecture). Each item is 32 bits.

Where the clock interrupt, interrupt source for the APIC clock.

Temperature detection interrupt. The interrupt source is a small probe that detects the TEMPERATURE of the CPU. It is used to Monitor the temperature of the processor.

TM1 controls the processor’s temperature by modulating the duty cycle of the processor clock.

TM2 controls the core temperature of the processor by reducing the operating frequency and voltage of the processor and offers a higher performance level for a given level of power reduction than TM1.

For other interrupts of interest, refer to the Development manual for Intel 64 and IA-32, Volume 3 10.5.

LAPIC summary

If IOAPIC sends an interrupt message to you, you must first determine whether or not you have received the message. This is based on the destination field in the redirect entry. Destination mode:

If destination mode is 0, it indicates the physical mode. The destination field indicates an APIC ID. LAPIC compares the ID registers to determine whether the LAPIC will receive the APIC.

If destination mode is 1, it means the logical mode. LAPIC needs the other two registers LDR and DFR to help determine the logical mode. The specific judgment is very complicated. The cluster is divided into flat cluster and hierachical cluster. For details, see Interrupt in Linux 1.2.3.

Otherwise, IRR, ISR, TPR, PPR, EOI and other registers are used to determine whether to send interrupts to the CPU for processing. In addition, if the interrupt type is NMI and special interrupts are directly sent to the CPU for processing, the above steps are not required.

To implement inter-processor interrupts, when one processor wants to send an interrupt to another processor, it fills in the ICR with the corresponding interrupt vector and target LAPIC identifier, and then sends a message to the target LAPIC through the bus. LAPIC has its own clock for counting clock interrupts and temperature detection to control CPU temperature.

Finally, take a look at a structure diagram of the LAPIC from the Intel manual to get an idea of how its parts work together directly, as shown below:

APIC interrupts the process

With this understanding in mind, look at the interruption process in the APIC phase:

  1. The IOAPIC translates the interrupt signal into an interrupt message according to the PRT table and sends it to the LAPIC listed in the Destination field
  2. According to the destination mode, destination field, register ID, LDR and DFR in the message, LAPIC determines whether it receives the interrupt message. If not, it ignores the message
  3. If the interrupt is SMI/NMI/INIT/ExtINT/SIPI, send it directly to the CPU for execution, because these interrupts are responsible for special system administration tasks. Otherwise place the IRR at position 1.
  4. If the interrupt has a higher priority than the one being executed by the current CPU, and the current CPU does not mask the interrupt, interrupt the interrupt currently being processed. Process the higher-priority interrupt first, or wait
  5. When the next interrupt is ready to be processed, the interrupt with the highest priority is selected from the IRR, corresponding to position 0 and ISR corresponding to position 1, and then sent to the CPU for execution.
  6. Writing EOI after the interrupt processing is complete indicates that the interrupt processing is complete. Writing EOI causes the CORRESPONDING position of the ISR to be 0. For level-triggered interrupts, an EOI message is sent to all I/O APics to notify that the interrupt processing is complete.

To access the APIC

IOAPIC has two registers mapped to memory: IOREGSEL, address FEC0 xy00h; IOWIN, address FEC0 XY10h. IOREGSEL is used to specify which registers to read and write to, and then read and write from IOWIN.

There are many registers in LAPIC, such as IRR, ISR, etc., which are also memory mapped to address 0xFEE00xxx.

Therefore, access and configuration of APIC can directly read and write to the corresponding memory. And the so-called memory mapping, is to regard these registers as a part of memory, read and write memory, is read and write register, you can use memory access instructions such as MOV to access the register. There is also an IO port mapping, in which the peripheral’s registers (also called ports) are treated as a separate address space. This space is accessed not by memory instructions but by specialized in/out instructions.

Whether it is memory mapping or port mapping, the scope of mapping is actually very small. For example, x86’s IO space is only 64KB, but in fact, there are many peripheral registers, it is impossible to map all the registers, so basically many peripheral hardware to use this way to access all the registers: One register is used to select the other registers of the hardware, and the other register is used to actually read and write the selected register. Just like the hardware package out of a window, what to do to this window account, the actual things are handled by the hardware internal.

The initialization of APIC configuration is to configure IOAPIC and LAPIC by using the access method mentioned above, and set some relevant register values. Setting these up is not the end of the story, because APIC works with multi-core processors, and processors need to be configured to work with them.

These two aspects of the configuration of the corresponding documentation reference, the former is the Intel development manual, the MP Spec, you can have a look at the following. On this aspect of the system source Linux is really more complex, can first refer to reference xv6, XV6 is also a multi-core operating system, which has the APIC, MP configuration initialization operation, can first look at this clear ideas, here is not described.

CPU phase

The CPU phase of interrupts, also known as the working part of the software operating system, is roughly divided into two parts, namely the interrupt handler and the running interrupt handler. It has been said before, but here is a brief restatement:

  1. Interrupt the descriptor accordingly according to the vector to the IDT index
  2. Check whether the privilege level has changed. If the interrupt occurs in user mode, switch to kernel mode
  3. If the privilege level changes, you need to save user mode SS, ESP to the kernel stack, otherwise do not need to save, and then save eflags, CS, IP to the kernel stack, if there is an error code, but also push the error code into the stack
  4. According to the segment selector in the interrupt descriptor, index the corresponding segment descriptor in GDT to get the segment base address, and combine with the segment offset in the interrupt descriptor to find the entry of interrupt processing
  5. The CPU executes the interrupt handler
  6. After the execution, IRET returns, which is a series of procedures to exit the stack and restore the context.

Here is a previous picture of an interrupt service routine:

As for the configuration of THE CPU phase, the most important thing is to configure the IDT table. IDT can be regarded as a table of interrupt descriptors arranged in order by the size of the interrupt vector number. Therefore, configuring the initial IDT is mainly to set the interrupt descriptors. The interrupt descriptor consists of the segment selector, segment offset and related attributes where the corresponding interrupt handler resides. Setting the interrupt descriptor is to combine these information according to the format of the interrupt descriptor. After configuring the IDT table, load the IDT address bounds into the IDTR register so that the CPU knows where to find the IDT when it interrupts.

conclusion

Without going into the details of the APIC and the operating system part, the interrupt process using the interrupt controller APIC should be clear. The interrupt signal from the peripheral to the IOAPIC is encapsulated into a formatted interrupt message, which is sent to the corresponding LAPIC, which is then sent to the CPU by a series of decision mechanisms. CPU processing is roughly divided into two processes, locating and running interrupt handlers.

However, when it comes to the details, the whole mechanism of APIC is very complex, and there is very little information about it in Chinese. There is an article “Interrupt in Linux” written by a great writer. If you are interested in interrupt mechanism, it is highly recommended to read it. I read it a few times and got a good idea. I got a good idea of the interruption process and how the APIC works, but some parts of it were still very vague and I had to read the Intel development manual to understand it. Originally called Intel® 64 and Ia-32 Architectures Software Developer’s Manual, volume 3, chapter 10, describes APIC in great detail, in English, which I, being a bad English speaker, struggle to digest. I haven’t learned much about APIC in these days, but I feel my English ability has become stronger again. And in some fields, the English information is also more detailed and accurate.

In addition itself is not engaged in the research of this aspect of work, delve into the depth is not much significance, to understand this degree from the thought that can, useful when such as the need for system programming, such as the initial configuration of the operating system to interrupt APIC, then can turn over the manual on the line.

But back to that point, most of the details are in English, so this article summed up: must learn English well!!

This article ends here, have what mistake also please criticize and correct, also welcome everybody to come to exchange discussion with me common progress.