本文介绍了x86系统中来自外部设备的中断传递过程。 它尝试回答以下问题:
- 图片是什么,它有什么用?
- APIC是什么?它有什么用? LAPIC和I / O APIC的目的是什么?
- APIC,xAPIC和x2APIC之间有什么区别?
- 什么是MSI? MSI和MSI-X有什么区别?
- $ PIR,MPtable和ACPI表的作用是什么?
如果您想知道这些问题之一的答案,或者只是想了解中断控制器的发展,欢迎您。
引言
对于那些不知道中断是什么的人,以下是维基百科的引文:
在系统编程中,中断是硬件或软件向处理器发出的信号,指示需要立即注意的事件。 中断会警告处理器处于高优先级状态,要求中断处理器正在执行的当前代码。 处理器通过暂停当前活动,保存其状态并执行称为中断处理程序(或中断服务程序,ISR)的功能来处理该事件来作出响应。 此中断是暂时的,在中断处理程序完成后,处理器将恢复正常活动。
有两种类型的中断:硬件中断和软件中断(softirqs):
- 设备使用硬件中断来传达需要操作系统引起注意的信息。 在内部,使用从外部设备发送到处理器的电子警报信号来实现硬件中断,该外部设备可以是计算机本身的一部分,例如磁盘控制器,也可以是外围设备。 例如,按键盘上的键或移动鼠标会触发硬件中断,从而导致处理器读取按键或鼠标位置。 启动硬件中断的操作称为中断请求(IRQ)。
- 软件中断是由处理器本身的特殊情况或指令集中的特殊指令引起的,该特殊指令在执行时会引起中断。 前者通常被称为陷阱或异常,用于处理程序执行期间发生的错误或事件,这些错误或事件非常特殊,无法在程序本身中进行处理。 例如,如果命令处理器的算术逻辑单元将数字除以零,则将抛出“除零”异常,因为该指令是错误且不可能的。
本文是关于硬件/外部中断IRQ的。
中断的目的是什么? 例如,我们要对来自网络卡的传入数据包一到达就执行操作。 如果您不想连续询问网卡“我的数据包到达了吗?” 并且浪费您的处理器时间,您可以使用外部硬件中断IRQ。 来自设备的中断线应连接到CPU的INTR线,并且在接收到每个数据包后,网卡将通过该线发出信号。 CPU将检测到该信号,并知道网卡具有该信息。 只有在那之后,CPU才会读取传入的数据包。
但是,如果有很多外部设备,我们该怎么办? 在所有CPU上制造大量的INTR引脚将是非常无用的。

为了解决这个问题,发明了一种特殊的芯片-中断控制器。
图片
(
Wiki /
osdev )
第一个中断控制器芯片是
Intel 8259 PIC 。 它有8条输入线(IRQ0-7)和1条输出线(将中断控制器与CPU的INTR线连接起来)。 当输入线路上的其中一个设备发生中断时,8259将通过INTR线路发出信号。 之后,CPU会知道某些设备需要立即处理,处理器将询问PIC 8条输入线(IRQx)中的哪一条是此中断的源。 轮询有一些开销,但是现在我们有8条中断线,而不是1条。

很快8行还不够。 为了增加中断线的总数,两个8259控制器(主机和从机)以级联方式(双PIC)连接。
第一个Intel 8259 PIC(主)处理从0到7的IRQ,第二个Intel 8259 PIC(主)处理从8到15的IRQ。 只有主站连接到CPU,并且可以发出有关传入中断的信号。 如果在线8-15上有一个中断,则第二个PIC(从站)将通过IRQ2线将其发送给主站,然后主站将向CPU发出信号。 此级联中断占用了16条线中的1条,但对所有外部设备总共进行了15条中断。

该方案已被社区采用,现在当有人谈论PIC(程序中断控制器)时,它们的意思是该双PIC系统。 一段时间后,对8259控制器进行了改进,并获得了新名称:8259A。 有了这些控制器,DUAL PIC系统就包含在芯片组中。 当用于外部设备连接的主要总线是ISA时,此系统就足够了。 由于ISA中断是不可共享的,因此仅需要使不同的设备不连接到同一IRQ线路即可。
设备中断映射几乎是标准的:
示例(从
此处开始 ):
IRQ 0-系统计时器
IRQ 1-键盘控制器
IRQ 2-级联(从控制器中断)
IRQ 3-串行端口COM2
IRQ 4-串行端口COM1
IRQ 5-并行端口2和3或声卡
IRQ 6-软盘控制器
IRQ 7-并行端口1
IRQ 8-RTC计时器
IRQ 9-ACPI
IRQ 10-打开/ SCSI / NIC
IRQ 11-打开/ SCSI / NIC
IRQ 12-鼠标控制器
IRQ 13-数学协处理器
IRQ 14-ATA通道1
IRQ 15-ATA通道2
使用8259芯片的配置和工作是通过I / O端口进行的:
有关8259A的完整文档,请参见
此处 。
PCI总线后来替换了ISA总线。 不幸的是,设备的数量开始超过了15。此外,PCI总线中的设备可以代替静态ISA总线而动态添加到系统中,这有可能导致更多问题。 但幸运的是,PCI总线中的中断可以共享,因此可以将许多设备连接到一条中断线IRQ。 最后,为了解决缺少中断线的问题,决定将所有PCI设备的中断分组到PIRQ线(可编程中断请求)。
例如,假设我们在PIC控制器和20个PCI设备上有4条空闲中断线。 我们可以将5个设备的中断组合到一条PIRQx线中,然后将这些PIRQx线连接到PIC控制器。 在这种情况下,如果一条PIRQx线路上存在一个中断,则处理器将不得不询问与该线路有关的所有设备有关该中断的信息,以了解是谁对该中断负责,但最终它解决了该问题。 将PCI中断线连接到PIRQ线的设备通常称为PIR路由器。
使用这种方法,必须确保PIRQx线不连接到具有ISA中断的线(因为这会产生冲突),并且PIRQx线是平衡的(我们连接到一条线的设备越多,CPU需要的设备越多)在需要检查哪个设备负责中断时进行轮询)。
注意 :在图像上,PCI设备-> PIR的映射被抽象地描绘,因为在实际情况下,它有点复杂。 在现实世界中,每个PCI设备都有4条中断线(INTA,INTB,INTC,INTD)和多达8个功能,其中每个功能只能具有这些INTx中断之一。 每个功能将使用哪条INTx线由芯片组配置决定。
就其性质而言,功能是单独的逻辑块。 例如,一个PCI设备可以具有Smbus控制器功能,SATA控制器功能和LPC桥功能。 从操作系统(OS)的角度来看,每个功能就像一个单独的设备,具有自己的配置空间(PCI config)。
关于PIC控制器中断路由的信息由BIOS在$ PIR表的帮助下通过寄存器3Ch(INT_LN中断线(R / W))和3Dh(INT_PN中断针(RO))发送到OS。每个功能的PCI配置空间。
$ PIR表的规范最近
在Microsoft网站上发布 ,但目前不可用。 可以从
PCI BIOS规范 [4.2.2]了解该表的内容。 [获取PCI中断路由选项]或从
此处获取 (最后一个链接是俄语,但是您可以尝试搜索“ PCI IRQ路由表规范”)
阿皮
(
Wiki ,
osdev )
最后一种方法有效,直到多处理器系统出现。 从本质上讲,PIC只能将中断发送到一个CPU,并且在多处理器系统中,希望以平衡的方式加载CPU。 解决此问题的方法是新的APIC接口(高级PIC)。
为每个处理器添加了一个称为LAPIC(本地APIC)的特殊控制器,以及用于路由来自外部设备的中断的
I / O APIC控制器。 所有这些控制器都在名称为APIC的公共总线中组合(请注意,现代系统使用标准系统总线而不是单独的APIC总线来完成此任务)。
当外部中断到达I / O APIC输入时,控制器将向系统CPU之一的LAPIC发送中断消息。 这样,I / O APIC控制器有助于平衡处理器之间的中断负载。
第一个APIC芯片是
82489DX ,它是一个单独的芯片,内部具有连接的LAPIC和I / O APIC。 对于双处理器系统,需要三个这样的芯片:两个用于LAPIC,一个用于I / O APIC。 后来LAPIC功能直接包含在处理器中,并且I / O APIC部分被分离到了82093AA芯片上。
I / O APIC
82093AA具有24个输入,并且APIC架构最多可支持16个CPU。 剩下的0-15中断留给了旧的ISA中断,以便与旧的系统兼容,而中断16-23则留给了所有PCI设备。 通过这种划分,可以轻松避免ISA和PCI中断之间的所有冲突。 随着空闲中断线数量的增加,也有可能增加PIRQx线的数量。

I / O APIC和LAPIC编程是在MMIO的帮助下完成的。 LAPIC寄存器通常放置在地址0xFEE00000上,而I / O APIC寄存器放置在地址0xFE0000上,尽管可以对其进行重新配置。
与PIC情况一样,开始时单独的芯片后来成为芯片组的一部分。
APIC体系结构后来进行了现代化,其新变体名为xAPIC(x-扩展)。 通过完全向后兼容,系统中可能的CPU总数增加到256。
架构开发的下一步名为
x2APIC 。 系统中可能的CPU数量增加到2 ^ 32。 这些控制器可以在与xAPIC的向后兼容模式下工作,或者可以在新的x2APIC模式下工作。 在这种新模式下,控制器编程不是通过MMIO进行的,而是通过MSR寄存器(速度更快)进行的。 根据
此链接 ,此模式需要IOMMU支持。
值得注意的是,系统中可能有多个I / O APIC控制器。 例如,一个在南桥中发生24次中断,另一个在北桥中发生32次中断。 在I / O APIC的上下文中,中断通常称为GSI(全局系统中断)。 因此,上述系统具有GSI 0-55。
我们如何确定CPU是否具有内部LAPIC及其支持的APIC体系结构? 可以通过检查CPUID中的位标志来回答这些问题。
为了帮助操作系统发现LAPIC和I / O APIC,BIOS应该通过MPtable(旧方法)或ACPI表(在这种情况下为MADT表)显示有关它们的信息。 除了公共信息外,MPtable和ACPI(在本例中为DSDT表)都应包含有关中断路由的信息。 这意味着有关哪个设备使用哪个中断线的信息(类似于$ PIR表)。
您可以在官方
规范中阅读有关MPtable的信息。 以前该规范位于Intel网站上,但目前只能在存档版本中找到它。 可以在UEFI网站上找到ACPI规范(当前版本是
6.2 )。 值得注意的是,使用ACPI,可以为没有APIC的系统声明中断路由(而不是提供单独的$ PIR表)。
微星
(
维基 )
APIC的最后一个变种很好,但并非没有缺点。 来自设备的所有中断线都使系统变得非常复杂,从而增加了错误概率。 PCI Express总线取代了PCI总线,从而完全简化了所有中断系统。 它根本没有中断线。 为了向后兼容,中断信号(INTx#)用单独的消息类型进行仿真。 对于PCI中断线,它们的连接是通过物理线进行的。 使用PCI Express中断线,连接是合乎逻辑的,并由PCI Express桥接器建立。 但是,仅对于与PCI总线的向后兼容,才存在对传统INTx中断的支持。 PCI Express引入了一种全新的中断传递方法-MSI(消息信号中断)。 在这种方法中,设备仅通过写入CPU LAPIC的MMIO区域中的特殊位置即可发出有关中断的信号。

以前,单个PCI设备(这意味着其所有功能)只能有4个中断,但是现在可以处理多达32个中断。
对于MSI,没有共享中断线:每个中断自然都对应于其设备。
MSI中断还解决了另一个问题。 例如,让我们想象一下这样一种情况,其中一个设备进行了一次存储器写事务,并希望通过中断来告知其完成情况。 但是在总线传输过程中,写事务可能会在总线上延迟(设备无法得知)。 在这种情况下,有关中断的信号将首先到达CPU,因此处理器将读取尚未有效的数据。 如果使用MSI,则有关MSI的信息将以与数据消息相同的方式传输,因此不会早于此。
值得注意的是,如果没有LAPIC,MSI中断将无法工作,但是MSI可以代替I / O APIC(又是一个简化的设计)。
一段时间后,MSI方法扩展到了MSI-X。 现在每个设备最多可以有2048个中断。 现在也可以指定哪个CPU应该处理哪个中断。 这对于高负载设备(例如网卡)非常有用。
MSI支持不需要单独的BIOS表。 但是设备应通过其PCI Config空间中的功能之一来表明其对MSI的支持。 另外,设备驱动程序应包括使用MSI的所有必要支持。
结论
在本文中,我们研究了有关中断控制器发展的信息,并获得了有关x86系统中外部设备进行中断传递的一般理论知识。
在下一部分中,我们将进行练习,并了解如何使用Linux中的上述每个中断控制器。
在第三部分中,我们将研究coreboot代码,并查看芯片组中需要哪些设置才能正确进行中断路由。
友情链接:
确认的细分
特别感谢
coreboot社区的Jacob Garber帮助我完成本文翻译。