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

2011年(1)

2010年(28)

2008年(15)

分类: LINUX

2008-04-28 21:17:55

的初始化

smp_boot_cpus()将调用LAPICIOAPIC的初始化函数。

初始化:

1、  调用verify_local_APIC(),通过LAPIC version寄存器、LAPIC ID寄存器验证LAPIC

2、  此时系统可能还处于PIC模式或Virtual Wire模式,调用connect_bsp_APIC()通过IMCR切换入APIC模式

3、  调用setup_local_APIC()设置LAPIC。该函数流程如下:

a、  在一系列检验后,首先调用init_apic_ldr()设置DFRLDR。目前Linux采用的是Flat模式。LDRlogical APIC ID = 1UL << smp_processor_id()

笔者:Logical APIC ID只有8bit,当平台CPU超过8个后岂非要重复?不过问题似乎不大,因为是用Lowest Prioirty模式。但可能会对IPI有所影响,有机会验证一下

b、  设置TPR0

笔者:从Linux的注释来看,TPR将一直为0X86 spec有这么一段话:对于使用lowest priority delivery mode发送中断,却又不更新TPROS,芯片组将记忆TPR并将同一中断发送给同样的CPU处理。这将引起性能损失。这应该是指XeonPentium4系列,因为P6Pentium系列是由APR决定CPU优先级的。这是否意味着,LinuxIntel新的平台上,中断性能受到了影响?

c、  设置伪中断寄存器,enable LAPIC、打开focus processor、设置伪中断的vector0xff

什么是伪中断

X86 spec对它的描述是INTR被拉高,CPU发出了INTA cycle,软件屏蔽了中断,视之为伪中断。软件屏蔽了中断?从前面的内容我们可以看到,LAPIC情况下,CPU没有提供屏蔽中断的方法(TPR只阻止中断交给CPU处理,不影响pendingIRR),cli

Mp spec对伪中断有描述:当一个中断在第一个INTA周期后,第二个INTA周期前变为无效,则为伪中断

8259Aspec虽然没有明讲伪中断,但有这样的描述:“PIC收到一个中断时,拉高INT脚,此时CPU的应答周期随之开始(指CPU第一次INTA应答)。如果一个优先级更高的中断发生在第一次INTA和第二次INTA之间,INT在第二次INTA后立刻拉低。在一段没规定长短的时间后,再次拉高INT脚通知高优先级中断的到来 ……”(此段话不是描述伪中断,而是值INT脚应该保持到第二次INTA的到来)

综合来看,伪中断就是INT脚没有维持足够长的有效电平,它应该维持到第二次INTA结束。

那么这种情况是如何产生的呢?笔者认为这是在第二个INTA到来前,CPU通过PICIMR寄存器屏蔽中断,导致INT脚变低所致。由于没有找到8259的电路图,这仅是我个人猜测。

以上是关于PIC的,现在来看看APICMP spec提到:对于APIC系统,更容易产生伪中断,because the device interrupt may be latched and recognized without the INTA cycle”。(最后一句怎么翻译我都觉得不恰当,大家自己理解吧)。在不知道APIC的构造前,我完全无法理解这句话。起初认为,mask中断发生在IOAPIC送出消息前,不会产生伪中断;mask发生在IOAPIC送出消息后,由于LAPIC会接收,也不会有伪中断。但真相并非如此。LAPICCPU中是怎样连接的?如果我告诉你LAPIC也有一个INT脚和INTA脚连CPU,就像PIC一样,你会不会大吃一惊?真的是这样,虽然这两个脚在CPU内部只是两条硬连线而已。LAPIC在决定提交中断给CPU时,同样拉高INT脚,CPU用两次INTA应答,就和PIC一样。记得我们前面说的Remote IRR异或机制吗?如果在第二次INTA之前,maskIOAPIC上对应的中断,会产生一条level-deassert消息,导致IRR对应bit清零。当第二个INTA到达时,LAPIC中的Proritier(一个部件)在IRR中找不到对应的bit,无法提交vector,最终产生一个伪中断。这暗示了只有level触发会产生伪中断。

此外,还有一种情况是EOI和设备驱动应答顺序出错而引起的。如果一个设备是level触发,设备必须保证在EOI到达IOAPIC前将中断线拉低,否则产生一个伪中断。这同样是Remote IRR引起的。该情形是:EOI先到达,Remote IRR0,此时中断线仍然为1,产生level-assert消息。LAPIC收到后设置IRR,并向CPU提交中断,CPU以第一个INTA应答。在第二次INTA发起前,驱动应答了设备,中断线拉低,产生level-deassert消息,LAPIC清除IRR。怎样,是不是和前面产生伪中断的过程一样?这个例子给了我们两个暗示:1)操作系统在设计时,必须调用了设备的中断处理程序后才写EOI2)设备的中断应答寄存器一定不能被cache,否则延迟可能导致EOI比驱动的应答先到。

对于伪中断,硬件会提交一个预定好的伪中断vector,操作系统需要给伪中断vector注册一个handler,通常是打印一条信息或加个统计值什么的。注意,处理完伪中断不写EOI

X86的伪中断寄存器除了可以设置伪中断vector外,还有一些其它功能,其格式如图:

2-4 伪中断寄存器

其中0~7bit设置vector8bit用于enable/disable LAPICLinux就是使用该方式enable LAPIC的。9bitenable/disable focus processor

笔者:对于PIC,没有伪中断寄存器设置vector。通常是使用和IRQ7相同的vector为伪中断vector

d、  设置LINT0LINT1管脚。对于BSP,如果系统有PIC模式,且LINT0没有被屏蔽,对应的LVT被设置成ExtINT模式。LINT1管脚设置成NMI模式;如果是AP,则将LINT0设置成ExtINT模式并屏蔽掉。LINT1管脚设置成NMI模式并屏蔽掉。

什么是LVT

LVTLocal Vector Table,是LAPIC自身中断源的配置表,它和IOAPICPRT表有类似结构。到目前为止,LAPIC最多有6个中断源,根据不同系列的CPU,中断源可能更少一些。6个中断源如下:

u       APIC Timer中断:APIC时钟,对应LVT Timer Register

u       热量探测中断:就是探测CPU温度那个小探头,对应LVT Thermal Monitor Register

u       性能计数溢出中断:对应LVT Performance Counter Register

u       LINT0脚中断:对应LVT LINT0 Register

u       LINT1脚中断:对应LVT LINT1 Register

u       APIC错误中断:当APIC探测到一个内部错误时产生,对应LVT Error Register

各个寄存器的格式如图:

2-6 LVT格式

e、  设置APIC Errorvector0xfe,清0enable该中断。

     至此,LAPIC相关设置就已完成。当然,还有一些我们没提到,比如APCI timer的设置。这些以后再说吧。

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