如果你以前没接触过中断,也许你会认为中断是一件特容易的事。但一旦你接触中断,并且想弄明白前因后果时,你就会改变观点,并且大发感慨:这是什么鬼东西?
是的,X86的中断就是这么麻烦。在操作系统下,一个中断从产生到中断服务程序的确定要经历N个步骤。首先,你要知道中断源。有了中断源,就要确定中断号。有了中断号,还要对应一个中断向量。有了中断向量,还需要注册中断服务程序和设定这个中断的优先等级。现在的架构都是支持中断共享的,所以如果牵涉到中断共享,还会有几个中断服务程序对应一个中断向量的事情。
1. 中断源触发类型
对于外部设备触发的中断,可以通过中断控制器设为电平触发模式或者边沿触发模式。
2. 中断号
对于BIOS工程师来讲,做中断这一块的重点在于中断号的确定。在这一点,ISA中断和PCI中断的确定是不同的。
ISA中断:ISA时代已经成为历史,但现在的计算机平台还保留着对ISA设备的兼容,LPC总线就是干这种事的。要想使能ISA的某个中断,要完成两个事情。首先,要在逻辑设备的SIO配置空间中填写中断号。然后还要在ASL中设置好_CRS,将其中断号宣告出来和设置MP表的IO Interrupt Entry供操作系统使用。要想修改ISA中断,我们不仅要修改SIO配置空间的中断号,还要修改_CRS里宣告的中断号。
PCI中断:设置PCI内部Device的中断时,我们要完成成三部分的事情。首先要设置DXXIP和DXXIR寄存器,即选择IRQ Routing中的一条路径作为中断连线。其次,我们要在LPC配置空间的PIRQ[A..H]_ROUT寄存器中设置IRQEN为1,代表使用APIC作为中断控制器。并且据此设置好MP table或者APCI的_PRT,这样,系统程序就会根据这些表格配置中断控制器和Interrupt Line寄存器。所以如果想修改PCI内部设备的中断号,我们就可以通过修改DXXIP来完成。
3. 中断控制器
中断控制器是CPU和外设中断的一个枢纽。CPU外部设备想要争取CPU的关注,就要向中断控制器发起中断,中断控制器通知CPU。CPU会放下手上的事情去处理该外设的请求,待处理完该外设的请求后,再接着忙活手上的事情。中断控制器集成在南桥中,一般来讲,南桥会有PIC和APIC两种中断控制器。因为主流操作系统都不再使用PIC,所以本章内容以APIC为主。
APIC的A是高级的意思,是可编程中断控制器的一个升级。一个IOAPIC可支持24个中断。访问IOAPIC需要使用一个内存寄存器对。一般来说是0xFEC00000和0xFEC00010,和其它寄存器对没什么区别,前者是INDEX寄存器,后者是DATA寄存器。使用它们来读写REDIR_TBL,就可以设置中断号所对应的中断向量以及使用的LAPIC,中断模式,是否禁止等。可以说,REDIR_TBL几乎干完了PIC的N个寄存器的活。
4. 中断向量
所谓的中断向量,我们可以认为它是确定中断号所对应的中断服务程序位置的。我们来看一下REDIR_TBL的字段。
Vector就是我们想要的向量,OS通过读MP表或ACPI表来设置这个值。有了这个Vector,我们就可以确定相应的中断处理程序在IDT表的相应表项。
2. 中断描述符
在实模式下,中断服务程序入口地址存储在中断向量表中,中断向量表存入在内存0地址处。PIC的中断的中断向量起始于INT8,因为前面8个被CPU内部中断给占了。中断向量表每个表项由四个BYTE构成。
但现在的操作都工作在保护模式下,取代中断向量表的是中断描述符。其每个表项由8个BYTE构成,并且基址由CPU寄存器IDTR来决定,并且系统程序可通过LIDT和SIDT指令读写该寄存器,这就给系统带了很大便利。
中断描述符表项:
其中Segment Selector和Offset字段共同构成了中断处理程序的入口地址。调用这个中断处理程序,我们的中断就得到了最终的处理。
2. 初始化APIC所用到的表
操作系统要做到通用,就不能和硬件打太多交道。所以它初始化APIC所用到的资源,是从BIOS处的内存得来的。根据操作系统的喜好,可是以MP table,也可以是ACPI。
6.1 MP table中分为很多个Entry,其中比较重要的一个为Entry Type=3的Entries,我们来看一下它的结构:
这个Entry字段意义比较多,但其offset 7最重要,可以认为其就是我们所说的中断号。至于offset 6的字段,我也很好奇,做过的X86平台,无论是笔记本还是台式机服务器的平台,都只有一个IOAPIC,所以此字段一直为0,不知道IA64会不会用多个IO APIC进行级联的。
6.2 ACPI表会提供_CRS和_PRT供操作系统使用,还提供APIC子表告诉操作系统IO APIC地址和LAPIC的地址,给操作系统提供了很大的方便。
(完)
附:缺乏经验的人背道叛逆,自招丧命;愚昧的人事事满不在乎,自取灭亡。