From IRQ to IRQL (APIC Edition)
Release Date: 2005-01-24 Abstract:
Abstract: https://www.xfocus.net/bbs/index.php? ACT = St & F = 2 & T = 45502 From IRQ to IRQL (APIC Edition) SobeIT in fact, the old PIC is eliminated very early before Instead, the APIC is replaced. Since the APIC can be compatible with the PIC, we see the PIC we have seen on many single-processor systems is actually a compatible PIC mode of the APIC. APIC is primarily applied to multiprocessor operating systems, to solve the IRQ minimum and processor interrupts, of course, single processor operating systems can also use APIC (not analog PIC). APIC's HAL and PIC have a great difference. One of the highlighted features is that the APIC's HAL does not have to virtualize an interrupt controller like the PIC's HAL. The concept of IRQL has been able to be supported by an interrupt vector. In fact, because of the APIC, IRQL's implementation in APIC HAL is much simpler than the PIC HAL. Now let's briefly introduce the structure of the APIC (for detailed description of APIC, please refer to IA-32 INEL Architecture Software Developer's Manual Volume 3 Chapter 8 "). The entire APIC system consists of local APIC, IO APIC, and APIC serial bus (after Pentium 4 and Xeon, the APIC bus is placed in the system bus). A local APIC is integrated in each processor, and IO APIC is part of the system chipset, and the APIC bus is responsible for connecting to IO APICs and various local APICs. Local APIC receives local interrupts such as clock interrupts generated by the processor, and interrupts between the processor generated, and receive messages from the IO APIC from the APIC Serial bus; IO APIC is responsible for receiving all external hardware interrupts, and Translation into a message Select the processor issued to the received interrupt, and the interrupt message interrupt from the local APIC reception processor. Like the PIC, the method of controlling the local APIC and IO APIC is to read the associated register in the unit. However, the PIC is not the same, Intel maps the registers of the local APIC and IO APICs to the physical address space, and the local APIC default mapped to the physical address 0xffe00000, IO APIC default mapped to physical address 0xFEC00000. Windows Hal further maps the local APIC to the virtual address 0xffe0000, maps the IO APIC to the virtual address 0xffd06000, that is, the reading and writing of the address is actually reading and writing of the register, and several important storage in the local APIC has an EOI register. , Task Priority Register (TPR), Processor Priority Register (PPR), Interrupt Command Register (ICR, 64-bit), Interrupt Request Register (IRR, 256 Bits, One Volume 1), Interrupt in Service Register ( ISR, 256-bit), etc. Several important registers in the IO APIC have version registers, I / O Register Select Registers, I / O Window Registers (Use Address I / O Register Select Registers to Access I / O Register I / O Register, Access I / O Window Register is access to selected registers) It is also important to have an IO redirect table, each entry is a 64-bit register, including related bits of vector and target mode, transmission mode, etc., each entry connection A number of IRQ lines, the number of items with the version of the processor, and 24 items on Pentium 4. The number of entry is stored in the [16:23] bit of the IO APIC version register.
The APIC system supports 255 interrupt vectors, but Intel retains 0-15 vectors, and the vector available is 16-255. And introduce a concept called task priority = interrupt vector / 16, because 16 vector, the available priority is 2-15. When setting the task priority register TPR in the local APIC with a specified priority, all priorities below the TPR are shielded, is it very similar to the mechanism of IRQL? In fact, the IRQL mechanism in Apic HAL is also achieved by this task priority register. The same task priority includes 16 interrupt vectors that can further finely grade the priority of interrupts. Although HalbeginsystemInterrupt is still an IRQL mechanism engine, because there is APIC support, it is much more simpler than the functionality of IRQL than the corresponding functionality in PIC HAL. HalbeginsystemInterrupt Gets the IRQL corresponding task priority by using IRQL to get the task priority of the IRQL, with this priority setting task priority register TPR, and the original task priority / 16 in the TPR is used as an index to get the corresponding correspondence in the HalpvectorToiRQL array. The original IRQL then returns. If IRQL is upgraded from below Dispatch_level to higher than DISPATCH_LEVEL, it is also necessary to set KPCR 0x95 (0xFFDFF095) to dispatch_level (0x2), indicating that the IRQL is increased from DISPATCH_LEVEL below. HalendsystemInterruPt transmits 0 to the EOI registration of the local APIC, indicating that the interrupt is completed, and new interrupts can be received. It is also necessary to determine if the IRQL to be reduced is smaller than the dispatch_level. If it is less than, the KPCR 0x96 (0xFFDFF096) is further determined, if the position is set, there is a DPC interrupt waiting (at IRQL above Dispatch_level being triggered, then waiting until IRQL drops below dispatch_level, then the KPCR 0x95 and KPCR 0x96 clearance is then called the KidispatchInterRupt response to the DPC soft interrupt. Otherwise, the job is the same as the HalbeginsystemInterrupt: convert the IRQL to the task priority to set the TRP, and turn the long task priority to IRQL returns. KfraiseiRQL, KfloweriRQL and other functions are also like this, modify the TPR to the current IRQL to task priority, and turn the value of the original TPR into the original IRQL and return. The generation of soft interrupts also has an APIC support. APIC can generate a soft interrupt by generating an interrupt between a handleable processor, because the vector can specify the interrupt, so the soft interrupt can distinguish the priority level, such as APC_LEVEL DISPATCH_LEVEL. Producing a soft-interrupt function or a HALREQUESTSOFTWAREINTERRUPT, which will first determine if the KPCR 0x95 is the same as the soft interrupt IRQL to be generated. If it is, set KPCR 0x96 and returns, indicating that IRQL is greater than dispatch_level, so the DPC interrupt is not processed. Otherwise, the corresponding task priority is taken from Halpirqltotprha by the IRQL to which the soft interrupt to be generated is removed from the Halpirqltotprha, and the 0x4000 is indicated as the fixed processing interrupt in which it is, and the upper 32 bit of the interrupt command register ICW is set, and then read Take the lower 32 bits of the interrupt command register ICW to be 0x1000, determine that the interrupt message has been returned, and the soft interrupt has been generated. It is worth noting that there is no HalendsoftwareIinterRupt this in Apic HAL.
HAL provides a fixed interrupt vector for the soft interrupt IRQL: #define ZERO_VECTOR 0x00 // IRQL 00 #define APC_VECTOR 0x3D // IRQL 01 # define DPC_VECTOR 0x41 // IRQL 02 # define APIC_GENERIC_VECTOR 0xC1 // IRQL 27 # define APIC_CLOCK_VECTOR 0xD1 // IRQL 28 # define apic_synch_vector 0xd1 // IRQL 28 # define apic_ipi_vector 0xe1 // IRQL 29 # define powerfail_vector 0xef // IRQL 30 # define apic_profile_vector 0xFD // IRQL 31 Now look at some important data:
This is the IO APIC redirection table I have written: redirect table index: 0x17redirect table [0]: ffredirect table [1]: b3redirect table [2]: ffredirect table [3]: 51redirect table [4]: ffredirect TABLE Table [5]: ffredirect table [6]: ffredirect table [8]: d1redirect table [9]: b1redirect table [A]: ffredirect table [b]: ffredirect table [c]: 52redirect table [C]: 52redirect table [C]: 52redirect table [C]: 52Redirect Table [ D]: ffredirect table [f]: 92red reference Table [10]: ffredirect table [11]: a3redirect table [12]: 83redirect table [13]: 93redirect table [14]: ffredirect table [15] : Ffredirect table [17]: ff This is a registered vector in the IDT table: 1F: 80064908 (Hal! HalpapicsPuriousservice) 37: 800640B8 (HAL! PICSPURIOSERVICE37) 3D: 80065254 (Hal! Halpapcinterrupt) 41: 800650C8 (Hal! HalpdispatchInterrupt) 50: 80064190 (Hal! HalpapicrebootService) 51: 817F59E4 (Vector: 51, IRQL: 4, SynciRQL: 4, Connected: true, no: 0, Sharevector: false, Mode: Latch ed, ISR: serial SerialCIsrSw (f3c607c7)) 52:! 817f5044 (Vector: 52, Irql: 4, SyncIrql: a, Connected: TRUE, No: 0, ShareVector: FALSE, Mode: Latched, ISR: i8042prt I8042MouseInterruptService (f3c57a2c! ))) 83: 817D2D44 (Vector: 83, IRQL: 7, SynciRQL: 7, Connected: True, No: 0, Sharevector: True, Mode: LevelSensitive, ISR: NDIS! NDISMISR (BFF1B794)) 92: 81821384 (Vector: 92 , Irql: 8, SyncIRQL: 8, Connected: True, No: 0, Sharevector: False, Mode: Latch, ISR: ATAPI! SCSIPORTINTERRUPT (BFF892BE)) 93: 8185ed64 (Vector: 93, IRQL: 8, SyncIRQL: 8, Connected: TRUE, No: 0, ShareVector: TRUE, Mode: LevelSensitive, ISR: uhcd UHCD_InterruptService (f3f0253e)) a3:! 8186cdc4 (Vector: a3, Irql: 9, SyncIrql: 9, Connected: TRUE, No: 0, ShareVector : True, Mode: LevelSensitive, ISR: SCSIPORT!
ScsiPortInterrupt (bff719f0)) b1: 818902e4 (Vector: b1, Irql: a, SyncIrql: a, Connected: TRUE, No: 0, ShareVector: TRUE, Mode: LevelSensitive, ISR:! ACPI ACPIInterruptServiceRoutine (bffe14b4)) b3: 81881664 ( Vector: b3, Irql: a, SyncIrql: a, Connected: TRUE, No: 0, ShareVector: FALSE, Mode: Latched, ISR:! i8042prt I8042KeyboardInterruptService (f3c51918)) c1: 800642fc (hal HalpBroadcastCallService) d1:! 80063964 (hal ! HalpClockInterrupt) e1: 80064858 (hal HalpIpiHandler) e3:! 800645d4 (hal HalpLocalApicErrorService) fd:! 80064d64 (hal HalpProfileInterrupt) fe:!! 80064eec (hal HalpPerfInterrupt) as a3, b1 output of such content is a lot of hardware registration Interrupt vector,
And like D1, E3 This output content is to register for the interrupt vector and local APIC interrupt vector for the HAL inside. This is a few important arrays: HalvectorToirql (this array is from 16 indexes): 8006A304 00 FF FF 01 02 04 05 06-07 08 09 0A 1B 1D 1EHALPIRQLTOTPR: 8006A1E4 00 3D 41 41 51 61 71 81-91 A1 B1 B1 B1 B1 B1 B1 B1 B1 B1-B1 B1 B1 C1 D1 E1 EF FHALPINTITOVECTOR: 8006ADA0 00 B3 61 51 A2 B2 62 91 - A1 B1 71 81 52 82 72 928006ADB0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 006A204 FF FF FF FF FF FF FF FF FF8006A214 FF FF8006A214 FF FF FF FF FF FF FF FF FF FF FF FF FF FF8006A224 FF FF FF FF FF FF FF FF FF FF FF FF FF FF8006A234 FF FF FF FF8006A234 FF FF FF FF FF FF FF- FF FF8006A244 FF FF FF FF FF FF FF FF FF FF FF FF FF FF8006A254 FF FF FF FF8006A254 FF 03 0C FF FF FF FF FF FF FF FF FF FF FF8006A264 FF FF FF FF8006A264 FF 02 06 FF FF FF FF FF -FF FF FF FF FF FF FF8006A274 FF 0A 0E FF FF FF FF FF FF FF FF FF FF FF FF8006A284 FF 0B 0D 12 FF FF FF-FF FF FF FF FF FF FF8006A294 FF FF FF FF8006A294 FF 07 0F 13 FF FF FF FF-FF FF FF FF FF FF FF8006A2A4 F f 08 04 11 ff ff ff ff-ff ff ff ff ff ff ff ff8006a2b4 ff 09 05 01 ff ff ff ff-ff ff ff ff ff ff ff ff8006a2c4 ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff8006a2d4 ff 08 ff ff ff ff ff ff-ff ff ff ff ff ff ff ff8006a2e4 ff ff ff ff ff ff ff ff-ff ff ff ff ff ff ff ff8006a2f4 ff ff ff ff ff ff ff ff-ff ff ff ff ff ff FF vbucket: 8006ae30 02 02 02 03 03 03 03 To explain, IRQ of SCSI Controller in my virtual machine is 17 (note, it has been greater than 16), find 177 in the redirect table, get an interrupt The vector is 0xA3, then look at the IDT, 0xA3 correspondence routine is SCSIPORT! SCSIPORTINTERRUPT. VBucket array dry? It is used to assign new vectors.