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

2011年(1)

2010年(28)

2008年(15)

分类:

2010-03-08 11:27:08

中断探测内核路径

路径

MP spec的相关代码位于arch/i386/kernel/mpparse.c中,主函数是get_smp_config(),它被setup_arch()调用,用MP table的信息配置系统。我们从get_smp_config()开始,看看Linux是怎么做的:

笔者:在此之前,我建议先跳文章末尾,阅读MP spec对硬件中断系统的规定

1、首先检查系统支持PIC模式还是Virtual Wire模式。如果支持PIC模式,全局变量pic_mode=1,否则pic_mode=0。接着获得LAPIC地址,存入mp_lapic_addr全局变量。最后检查mp table是否提供了默认配置。这些信息都可以通过MP Floating Pointer entry得到。

Default Configuration

MP Floating Pointer entry有两个字段用于描述一些特殊的属性,如下表:

字段

偏移(bytes:bits

长度(bit

描述

MP FEATURE INFORMATION BYTE1

11

 

 

8

 

 

0:使用MP configuration table

不为0:使用Default configuration

 

MP FEATURE INFORMATION BYTE2

 

12:0

12:7

 

 

7

1

 

 

Bit0-6:预留

Bit7IMCRP,该位置一,PIC mode被实现;否则Virtual Wire Mode被实现

2-3 MP Floating Pointer Structure(只摘录的部分字段)

Default ConfigurationMP spec为了简化BIOS设计,给特定的平台提供的默认配置。它对平台有如下假设:

u  系统支持两个CPU

u  CPUIntel兼容指令集

u  LAPIC位于默认地址FEE0_0000H

u  LAPIC ID0开始连续分配

u  系统有一个IOAPIC位于FEC0_0000H

u  系统实现了PIC modeVirtual Wire Mode

u  根据平台总线类型、APIC类型的不同,默认配置又分7种情况,这里我们只关心一种,即平台总线为PCI+ISAAPIC是集成型时的情况。

笔者:MP spec给了两种APIC类型,一种是82489DX,一种是Integrated类型。个人认为目前流行的属于Integrated

来看一下默认配置表,图中画框的是我们讨论的情况:

2-2 Default Configuration

该配置有几个需要注意的地方,INTIN0IOAPIC0管脚)接的是PICINTIN2接的是IRQ0,即PITIRQ2不存在,因为PIC为两片8259a,其中第二片8259a接第一片的IRQ2管脚。

2、  如果平台使用Default Configuration,调用construct_default_ISA_mptable()。该函数会对CPU、总线、中断等使用默认配置,我们只关心和中断相关的部分,流程如下:

a、               注册IOAPIC。由于Default Configuration中只有一个IOAPIC,故其配置如下:

ioapic.mpc_type = MP_IOAPIC;

ioapic.mpc_apicid = 2;

ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;

ioapic.mpc_flags = MPC_APIC_USABLE;

ioapic.mpc_apicaddr = 0xFEC00000;

MP_ioapic_info(&ioapic);

注意这里IOAPIC ID2,是从LAPIC ID后最小的数字分配的(Default Configuration有两个CPU)。MP_ioapic_info()用于把该struct mpc_config_ioapic存入mp_ioapics数组。

b、              调用construct_default_ioirq_mptable()配置ISA中断。该函数首先配置struct mpc_config_intsrc中各字段,除dstirq。如下:

intsrc.mpc_type = MP_INTSRC;

intsrc.mpc_irqflag = 0;                /* conforming */

intsrc.mpc_srcbus = 0;

intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid;

intsrc.mpc_irqtype = mp_INT;

其中mpc_irqflag=0表示中断的触发模式、管脚极性由中断所在的总线决定。接着配置各个ISA中断,即设置dstirq。内核为了正确的配置PCI中断,使用了ELCREdge/Level Controller Register,用于判断某IRQ的触发方式,详情见ICH9 spec),在使用前,检查ELCR是否可用。

1213是什么?

Kernel检查ELCR是否可用的方式,是判断IRQ01213是否有level触发,因为这4IRQ只能为edge触发。那么,它们是什么?IRQ0PIT timerIRQ1是键盘;IRQ2是连接的slave 8259aIRQ13是协处理器,也就是老式的浮点运算单元。实际上还有一个可用于检查,即IRQ8——RTC,它也是edge触发。

                设置dstirq代码如下(简化后):

for (i = 0; i < 16; i++) {

       if (i == 2)

           continue;

       if (ELCR_fallback) {

              if (ELCR_trigger(i))

                     intsrc.mpc_irqflag = 13;

              else

                     intsrc.mpc_irqflag = 0;

       }

       intsrc.mpc_srcbusirq = i;

       intsrc.mpc_dstirq = i ? i : 2;         /* IRQ0 to INTIN2 */

       MP_intsrc_info(&intsrc);

}

               IRQ2不设置,IRQ0连接到IOAPIC管脚2。其它IRQxidentify map0IOAPIC1~15脚。此外,如果ELCR检查到该IRQ接的是PCI中断,则重新设置mpc_irqflag配置触发方式。最后调用MP_intsrc_info()把各ISA中断配置存入mp_irqs数组。

笔者:这里ELCR_trigger(i)返回1表示该IRQlevel触发。从内核的注释看,此时为PCI中断。令人费解的是intsrc.mpc_irqflag = 13代表了高电平有效、电平触发。而PCI应该是低电平有效、电平触发。内核错了?

                最后,还要描述一下0号管脚接PIC的情况,如下:

intsrc.mpc_irqtype = mp_ExtINT;    /*注意和前面的MP_INT类型区分*/

intsrc.mpc_srcbusirq = 0;

intsrc.mpc_dstirq = 0;                         /* 8259A to INTIN0 */

MP_intsrc_info(&intsrc);

c、               注册mpc_config_lintsrc Default configurationLINT0ExtINTLINT1NMI。调用MP_lintsrc_info注册(仅打印信息,无实用)。

3、  如果系统未实用默认配置,就需要解析MP table。该任务在smp_read_mpc()中完成,它将MP table的各个entry分别存入mp_ioapicsmp_irqs等数组。

4、  至此,平台上各IOAPIC、中断源的信息应已存储到各相关数组里。Kernel再做最后一次检查,如果mp_irq_entries == 0,说明MP table没有报告中断源,construct_default_ioirq_mptable()将系统设置到ISA模式。

 

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