Chinaunix首页 | 论坛 | 博客
  • 博客访问: 375563
  • 博文数量: 44
  • 博客积分: 2060
  • 博客等级: 上尉
  • 技术积分: 528
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-17 20:50
文章分类
文章存档

2011年(1)

2010年(28)

2008年(15)

分类:

2010-03-08 11:23:47

Linux的中断子系统

从这章开始,我们来看看Linux中断子系统的实现。

PinGSIVector

这几个概念经常把人搅晕掉,下面的内容经常要用到它们,还是先说清楚为妙。

IRQPIC时代的产物,由于ISA设备通常是连接到固定的PIC管脚,所以说一个设备的IRQ实际是指它连接的PIC管脚号。IRQ暗示着中断优先级,例如IRQ0IRQ3有着更高的优先级。当前进到APIC时代后,或许是出于习惯,人们仍习惯用IRQ表示一个设备的中断号,但对于16以下的IRQ,它们可能不再与IOAPIC的管脚对应,例如PIT此时接的是2号管脚。

Pin是管脚号,通常它表示IOAPIC的管脚(前面说了,PIC时代我们用IRQ)。Pin的最大值受IOAPIC管脚数限制,目前取值范围是[0,23]

GSIACPI引入的概念,全称是Global System Interrupt。它为系统中每个中断源指定一个唯一的中断号。下图展示了GSI的思想:

2-1

2-1中有3IOAPICIOAPIC0~2IOAPIC024个管脚,其GSI base0,每个管脚的GSI=GSI base + pin,故IOAPIC0GSI范围为[0~23]IOAPIC116个管脚,GSI base24GSI范围为[24,39],依次类推。ACPI要求ISA16IRQ应该被identify mapGSI[0,15]

IRQGSIAPIC系统中常常被混用,实际上对15以上的IRQ,它和GSI相等。我们在谈到IRQ时,一定要注意它所处的语境。

VectorCPU的概念,是中断在IDT表中的索引。每个IRQ(或GSI)都对应一个Vector。在PIC模式下,IRQ对应的vector=start vector + IRQ;在APIC模式下,IRQ/GSIvector由操作系统分配。

中断探测

操作系统如何知道平台上硬件中断系统的情况?BIOS告诉它的。表,是BIOS报告系统资源的通常方式。MP spec定义了MP tableACPI规范定义了MADTMultiple APIC Description Table)。虽然构建方式不一样,但从OS看来两者大同小异,都支持LAPIC entryIOAPIC entry,以及其它几个与它们相关的entry。这些entry描述了平台APIC硬件的情况。下面根据Linux两条不同的中断探测路径,介绍如何根据MP tableMADT构建中断子系统的主要数据结构。

关键数据结构

Linux最初实现的是MP spec相关规范,故定义一组符合MP spec的数据结构来管理平台硬件。ACPI被引入后,虽然汇报硬件资源的方式变了,但仍可以使用MP spec的数据结构来管理。LinuxACPI解析路径,实际上是用ACPI的方式读表,填充MP spec的数据结构。由此看来,我们只要理解MP spec数据结构就可以了,和中断相关的有如下几个:

笔者:这些结构体和MP spec规定的各个entry结构是相同的,下面表格将两者列在一起说明,以后就不单独画MP specentry的结构表了。

struct mpc_config_ioapic:对应MP specIOAPIC entry ,各字段如下:

结构体成员

MP spec字段

长度(byte

描述

mpc_type

TYPE

1

类型,2(IOAPIC ENTRY)

mpc_apicid

IOAPIC ID

1

IOAPIC ID

mpc_apicver

IOAPIC Version

1

IOAPIC版本

mpc_flags

IOAPIC FlagsEN

1

最低bit有效,其余bit预留

0IOAPIC disabled

1IOAPIC enabled

mpc_apicaddr

IOAPIC Address

4

IOAPIC基地址

2-1 IOAPIC entrystruct mpc_config_ioapic

内核用mp_ioapics全局数组存放系统中所有IOAPIC对应的struct mpc_config_ioapicnr_ioapicsIOAPIC数量。目前Linux最多支持64IOAPIC,当数量超过时可以配置MAX_IO_APICS宏扩大限制。

struct mpc_config_intsrc:对应MP specIO interrupt entry,代表各个中断源(一个IOAPIC管脚连接一个中断源)各字段如下:

结构体成员

MP spec字段

长度(byte

描述

mpc_type

TYPE

1

3IOAPIC interrupt

mpc_irqtype

INTERRUPT TYPE

1

INTAPIC模式中断

NMI:不可屏蔽中断

SMI:系统管理中断

ExtINTvectorPIC提供。如果8259用作外部PIC,PIC INTRAPIC的一个管脚,vector8259提供

mpc_irqflag

PO:位于2byte 0bit

EL:位于2byte 1bit

2

PO:中断管脚极性

EL:触发模式

mpc_srcbus

SOURCE BUS ID

1

产生中断的总线

mpc_srcbusirq

SOURCE BUS IRQ

1

相对于产生中断的总线,该中断管脚代表的中断号。例如0,相对于ISA总线即IRQ0

mpc_dstapic

DESTINATION IOAPIC ID

1

该中断连接的IOAPIC0xff标识连接到所有的IOAPIC

mpc_dstirq

DESTINATION IOAPIC INTN#

1

连接到IOAPIC的管脚号

2-2 IO interrupt entrympc_config_intsrc

不同总线中断共享情况:如果两个IO interrupt entrydestinationIOAPIC IDINTN#)相同,则共享。例如IPCI-device1/INTA#ISA-IRQ2如对应相同的destination,则两者共享,接同样的IOAPICINTN#

中断共享和中断丢失

我们不讨论Level触发的情况,因为意义不大,它可以共享且不会丢失中断。

Edge触发,问题就比较多了。它通常对应ISA设备,一个常见的说法是“ISA设备不能共享中断,但也有人说这是个“superstition”(内核邮件列表曾有关于它的争论)。

从能找到的资料来看,标准的ISA设备是不支持中断共享的,但问题是有很多非标准实现的存在。从操作系统的角度看,支持ISA中断共享并非难事,我们完全可以使用level触发同样的方式去处理edge触发(例如Linux的实现)。Edge共享的一个难题是,当一个设备在另一个设备的中断正在被处理时发起中断,该中断会丢失(或者说要等到另一个设备再发起中断时才会处理),因为此时该中断管脚通常是被屏蔽的。为了解决这个问题,一些非标准的实现会用“re-trigger while in service”“sequencing of interrupt-generating”加以保证。前者会在一个中断服务完后再触发一次中断;后者会保证中断事件顺序产生,即处理完一个再产生一个。无论怎样,我们尽量在操作系统中支持ISA中断共享,但应该认识到edge中断是不应该共享的。

从理论上分析,edge中断会丢失,但我没找到足够的资料论述其丢失的具体情况,以及丢失后如何处理。Edge中断丢失出现在中断管脚被mask,设备又发起中断时。一些非官方资料说硬件会有一些re-trigger的机制,以及ISA驱动应实现timer poll来确保丢失的中断能被处理。没有更多的信息,留个疑问在这里吧。

Bluesky_jxc同学补充了一些观点:

这个问题和塑料袋争论过,edge触发的中断是可以共享的,但是需要考虑几个问题:

1.         设备需要中断状态位

2.         电路需要引入三态,而且空闲时需要上拉电阻。

3.         ISR链表。

ISA设计的时候没有考虑到这个需求,因此可以这么说“ISA中断可以共享,但是不要假设其它设备能支持共享功能”。还是那句话,能不能是一个问题,而用不用是另一个问题。

内核用mp_irqs全局数组记录系统中所有的mpc_config_intsrc。目前支持的最大数——MAX_IRQ_SOURCES256

Struct mpc_config_lintsrc:定义和mpc_config_intsrc一样。只是mpc_dstapic代表LAPIC,且mpc_dstirq只能取值01

 

 

阅读(4689) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~