查看原文
其他

详解计算机中断路由:INTx、PIRQx、IRQx的区别和联系是什么?Swizzling和Straight又是什么?

wolf uefiblog UEFI社区 2023-12-29
点击上方“公众号” 可以订阅哦!

中断体系和PCI/PCIe是现代计算机系统构成要件中最重要的两大部分。二者的交集:PCI/PCIe设备的中断,它的使能和正确配置,尤其是中断路由的正确汇报,是设备能够正常工作甚至是主板能够启动的前提条件。这个过程中会涉及大量概念,如INTx、PIRQx、IRQx和Vector等中断相关术语,它们既不同又紧密相关;基于传统8259的PIC模式和新的APIC模式处理有所不同;桥片内部设备和桥片外部设备的处理有所不同;甚至PCI Slot和PCIe Slot的处理都有区别。厘清它们的区别和了解工作原理,是BIOS从业者的基本功之一。正确设置它,可以让主板顺利启动,各个设备正常工作;更进一步,优化的配置更能摊平中断的压力,让计算机系统性能更好。对于操作系统底层驱动程序员和计算机硬件工程师来讲,相关知识也非常重要。

遗憾的是,相关详细资料非常匮乏,尤其是中文资料几乎找不到,让很多人不得其门而入,成为了很多初级BIOS程序员的拦路虎。我曾在四五年前写过一篇文章:老狼:计算机中断体系三:中断路由,很多读者表示不过瘾,好像都讲了,又似乎什么都没说清楚,有隔靴挠痒之感,不能实操。俗话说有图有真相,这次我们就从网上一篇Intel的ppt【1】 中的两张图入手,来详细梳理相关概念和设置,并在最后结合代码进行一下分析:

来源:参考资料1

来源:参考资料1

需要说明的是,资料比较陈旧,发布于2008年,当时的南桥甚至是ICH9,十几年过去了,尽管南桥从ICH变成了PCH,还有些SOC甚至没有南桥,但相关基本概念却几乎完全没有改变,还能适用于今天的系统。如果能接触到Intel的最新PCH手册,可以自行查看BIOS Spec相关部分,也有类似图片。在我们开始今天的旅行之前,我希望读者能阅读过前面几篇介绍PCI/PCIe和中断的文章,以便能有个共同的讨论基础。如果你还没有看过,下面是传输门:

深入PCI与PCIe之二:软件篇

计算机中断体系一:历史和原理

计算机中断体系二:中断处理

计算机中断体系三:中断路由

INTx、PIRQx和IRQx

PCI spec为每个PCI设备定义了四个中断请求信号线,分别是INTA#,INTB#,INTC#和INTD#,如图:

如果PCI设备为单功能设备,则必须使用INTA#,对于多功能设备,各设备功能可任意接至PCI 总线的四条中断申请线INTA# 到INTD# 。PCI设备借助这些中断请求信号,通过电平触发方式向CPU发出中断请求。一个PCI设备可以有多个func,一个PCI Bus下可以有31个设备,一个PCI树下可有256个PCI Bus,才四条中断请求线,不可避免要进行中断共享。电平触发的方式让中断共享十分方便,INTx采取低电平触发方式,某个设备发生中断后,驱动某个INTx为低,触发中断,中断处理完毕后不再驱动该请求线。因为INTx信号线为开漏线路,只要上面所有的设备都不驱动它的时候,上拉电阻会自动将其置高。理论上来讲,INTx的共享是采取线与的方式,有一个为低,即为低,会触发中断。

计算机系统中的设备很多,它们各自用了哪些INTx?各个设备的INTx是如何线与的?这些线与后的结果是如何连接CPU的中断请求引脚?有没有设备直接将INTx连接CPU中断引脚?这些变量信息PCI Spec并未规定,各个平台和主板需要根据实际情况进行设计,而操作系统需要准确知道这些信息才能正确处理中断。这些变量信息就是中断路由表,它由主板硬件抽象层:BIOS,来提供。

古老的计算机主板上有两颗级联的8259芯片,级联后通过CPU的INTR引脚告诉CPU发生了中断。每个8259提供8个IRQ引脚,两个有15个IRQ引脚(级联用了一个,16-1=15),它们就是IRQx。级联的8259逻辑后来被整合进入南桥的LPC中,IRQx引脚不再引出,与之对应的是,南桥(ICH/PCH)提供8个PIRQ(PCI IRQ)引脚,它们就是PIRQx(PIRQA#到PIRQH#),负责连接外部PCI中断请求。与传统的PIC模式的IRQx对应,APIC模式的IO APIC也有数量不等的中断入口INTINx,每个IO APIC常见的中断入口是24个,通常CPU和桥片上都有各自的IO APIC。INTINx并不是物理引脚或者硬件连线,而是通过message的软方式存在。

从PCI设备的INTx,到南桥的PIRQx引脚,再到LPC中的IRQx逻辑(或者IO APIC的INTINx),一个中断从源头到最后落地,经历了三级两层映射:INTx -> PIRQx -> IRQx。这个映射关系是中断路由的精髓,那么它们是硬连线的,还是可以自由配置的呢?这要分芯片内部设备和外部设备两种情况来讲。

极大灵活度的内部设备中断路由

Intel为桥片中或者CPU中的设备,提供了最大程度的灵活度,方便整机厂商根据实际情况来平衡中断请求。三级两层映射关系都可以自由调节。我们一层层剥开来看,先看前端:INTx -> PIRQx的映射。

来源:参考资料1

注意红框部分,南桥内部设备(都在Bus 0上),几乎每个设备的每个Func,都通过两组寄存器(IP和IR寄存器),来灵活配置,几乎做任何映射。如LPC设备(Device 31,Func 0),可以通过D31IP寄存器,控制其中的每个Func使用INTx中的任何一个(当然只有一个Func的话,必须用INTA#),之后可以通过D31IR,来控制31号设备的四个INTx虚拟连接到八个PIRQx中的任意四个。可谓是提供了最大的灵活性。

后端PIRQx -> IRQx的连接可以通过LPCBR来自由调节:

来源:参考资料1

图中黄色的部分,就是PIRQx可以配置的IRQx,注意IRQx的范围有限制,不能被配置到Legacy保留的IRQx上。PIRQx和IO APIC的INTINx关系则是固定的一一对应(想想为什么从16开始?),不能配置。

桥片中设备通过三级两层映射,三组寄存器,来提供了极大的灵活性。那么主板上的其他外部设备呢?

外部设备和Swizzling

PCI和PCIe的外部设备,包括固定连线和Slot扩展槽,在PCI和PCIe的Spec中有推荐中断路由,也在图中有所表示:

来源:参考资料1

这里PCI设备和PCIe的情况有所不同,我们分成两部分来讲。

1

外部PCI设备

对主板上的PCI扩展插槽,用户插入什么设备,插在哪个槽内都不能在出厂时确定。我们这里要尽量考虑平衡原则和效率原则。我们将所有插槽的INTA#~INTD#分成四组串联起来如何?这样离得最近的Slot 1高兴了,每个都是我优先!万一有个用户把重要的网卡插在slot 4,效率会严重下降。在充分考虑到PCI设备绝大多数都是单功能设备(仅使用INTA#信号,很少使用INTB#和INTC#信号,而INTD#信号更是极少使用),PCI SIG推荐PCI to PCI bridge后slot连接关系应该组成如下图:

即Slot1 INTA#->Slot2 INT B#->Slot3 INTC#->Slot4 INTD#。这种交错叫做Swizzling,也就是上上图中的黄框部分。Swizzling交错之后的INTx,再经过Straight映射,即红框部分的直接映射方法变成PIRQx。

2

外部PCIe设备

PCIe的设备有一个PCI设备没有的问题,每个PCIe链路下只有一个EP(End Point)设备,这个设备的中断请求信号(当然是虚拟的)一般是INTA#,如果RC下面的所有链路都采用Straight方式,即INTA#都连接PIRQA,则PIRQA的负担过重。于是PCIe采取一种类似PCI Slot插槽Swizzling的方式,不过是经过PCIe Root Port的软转换的方式,也就是上上图中的INTx Mapping Swizzling:

结合

经过这层Swizzling交错,再通过Straight方式映射到PIRQx,即可。

转成PIRQx之后,PIRQx和IRQx或者INTINx的映射关系,和内部设备相同。

A Case Study

我们来实际看看一些代码,Intel Purley服务器的代码已经开源:https://github.com/tianocore/edk2-platforms/blob/master/Platform/Intel/PurleyOpenBoardPkg

我们可以在代码里面寻找对PCH内部设备的INTx -> PIRQx的映射关系的Program,如寻找D31IP和D31IR。完毕后对照ACPI table:

https://github.com/tianocore/edk2-platforms/blob/master/Platform/Intel/PurleyOpenBoardPkg/Acpi/BoardAcpiDxe/Dsdt/PlatformPciTree_WFP.asi

来交叉验证。因为篇幅的关系,这里不再累述,我们来看一下一个片段,PCIe Root Port下面设备的Swizzling:

结合PCIe的Swizzling规则:

先映射INTx,之后通过Straight规则映射到PIRQx

之后到IOAPIC的INTINx一一映射(从16开始):

因为这是第一个IOAPIC,所以GSI(详见ACPI Spec)和INTINx数字是一致的。

我想通过这些讲解,PCH内部和外部的PCIe设备的中断路由应该很清楚了。最后给大家留个思考题:大家知道,尽管少了一些,但CPU里面也有一些PCIe设备(和有些Root Port),它们INTx、PIRQx和IRQx的映射关系是如何呢?如我们的Purley平台支持多路CPU,在路由文件PlatformPciTree_WFP.asi中能不能找到对应的关系呢?同样的文件中,问什么GSI有大于24的,甚至上百的数字呢?ARxx和AHxx的区别是什么呢?

知道的同学可以在评论区留言,相互探讨一下。

参考资料

[1] interrupt-in-sandy-bridge-and-x86-platform: https://www.slideserve.com/abra/interrupt-in-sandy-bridge-and-x86-platform-taeweon-suh


继续滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存