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

2011年(1)

2010年(28)

2008年(15)

分类:

2010-03-08 11:31:10

路径 表结构

MADT表的entryMP table大同小异。

MADT表头结构:该结构拥有很多字段,例如版本号、OEM信息等,其中和本文内容相关的字段有3个,见下表:

字段

长度(bytes

偏移

描述

LAPIC Address

4

36

32bit物理地址,用于CPU访问自身LAPIC

Flags

4

40

Bit1表示系统是否有PIC存在。

1:有,当APIC使用时,PIC的各管脚必须被mask

0:无。

其它bit预留

APIC structures

-

44

各种中断的描述条目

2-4 MADT表头

的地址

Spec规定,LAPICIOAPIC的寄存器必须被实现成MMIO方式。对于LAPIC来说,每个CPU使用同样的地址访问自己的LAPIC,默认地址是FEE0_0000H。对于IOAPIC,默认基地址是FEC0_0000H,每个IOAPIC4k地址,从基地址开始连续。

LAPIC地址对齐到4K边界,IOAPIC地址对齐到1K边界。

笔者:每个CPU都用同样的物理地址访问自己的LAPIC。这说明除了x86平台的port I/O具有64K独立的物理地址空间外,LAPIC也拥有独立的物理地址。我能想到的理由是防止CPU访问不属于自己的LAPIC

LAPIC相关的MADT条目共有三个,分别是:LAPIC entryLAPIC NMI entryLAPIC address override entry

字段

长度(bytes

偏移

描述

Type

1

0

0LAPIC

Length

1

1

8

ACPI Processor ID

1

2

ACPI processor operator中列出的processorID

APIC ID

1

3

LAPIC ID

Flags

4

4

Bit0enable位,

0disable

1enable

其它bit预留

2-5  LAPIC entry

字段

长度(byte

偏移

描述

Type

1

0

4LAPIC NMI

Length

1

1

6

APCI Processor ID

1

2

Processor object中的CPUID0xff代表所有CPU

Flags

2

3

MPS INIT flags

LAPIC LINT#

1

5

LINT管脚号(0 or 1

2-6 LAPIC NMI entry

该表描述NMI中断接LAPIC LINTx管脚的情况,其中MPS INI flags为和MP spec兼容的属性,见下面的MPS INI flags表。

字段

长度(byte

偏移

描述

Type

1

0

5LAPIC Address Override

Length

1

1

12

Reserved

2

2

0

LAPIC address

8

4

LAPIC的物理地址

2-7 LAPIC address override entry

该表用于重载MADT表头中的LAPIC地址,整个MADT表中只应该包含一个LAPIC address override entry

LAPIC Flags

长度(bit

偏移

描述

Polarity

2

0

IOAPIC管脚有效电平极性

00 由总线决定极性(例如EISA总线为低电平有效,电平触发)

01 高电平有效

10 预留

11 低电平有效

Trigger Mode

2

2

管脚触发模式

00 总线决定(例如ISA总线为edge触发)

01 edge

10 预留

11 level

预留

12

4

0

2-8 MPS INIT flags

 

IOAPIC相关MADT条目:IOAPIC entryInterrupt Source Overrides entryNMI entry

字段

长度(bytes

偏移

描述

Type

1

0

1IOAPIC

Length

1

1

12

IOAPIC ID

1

2

IOAPIC ID

Reserved

1

3

0

IOAPIC address

4

4

32bit物理地址,CPU通过该地址访问IOAPIC。该地址对于每个IOAPIC都是唯一的

GSI Base

IOAPICGSI空间中的起始号。GSIGSI base+管脚号

2-9 IOAPIC entry

字段

长度(bytes)

偏移

描述

Type

1

0

2interrupt source override

Length

1

1

10

Bus

1

2

0ISA

Source

1

3

ISA上的IRQ

GSI

4

4

MapGSI空间后的GSI

Flags

2

8

MP INIT flags

2-10 Interrupt Source Overrides(ISO)

ISA中断接PIC0~15脚,通常需要identify mappingGSI空间。具体的说,ISA中断应该按接PIC的顺序接0IOAPIC0~15脚。若平台实现有差异,某个ISA中断没有被identify mapping的时候,需要一个ISO结构来描述。特别需要注意的是,管脚极性不同时,也需要一个ISO结构描述。

举两个例子:

1PITPIC0号脚,即IRQ0。当接IOAPIC时,它通常接在2号管脚上,即INTN2。此时需要一个ISO来描述此差异,source字段为0GSI字段为20IOAPICGSI base0)。

2SCISystem Control Interrupt,通常接PIC的管脚9,即IRQ9FADT会在SCI_INT字段里报告该值。如接到IOAPIC11号脚,则需要一个ISO描述。Source字段为9GSI字段为11

字段

长度(bytes

偏移

描述

Type

1

0

3NMI

Length

1

1

8

Flags

2

2

MPS INIT Flags

GSI

4

4

NMIGSI

2-11 NMI entry

描述IOAPIC某个管脚被配置成NMI的情况。NMI不应该被设备使用。

中断探测过程

X86ACPI相关代码位于arch/i386/kernel/acpi目录,其中对各表的解析位于boot.c文件。MADT表的解析经过下列路径:

1、  acpi_boot_initv()调用acpi_process_madt(),后者是解析MADT表的主函数。

2、  acpi_process_madt()首先检查MADT表头,确定MADT表包含多少个描述APIC部件的entry,以及获得LAPIC的默认地址并放入acpi_lapic_addr全局变量中。这在acpi_parse_madt()函数中完成。

3、  紧接着,acpi_parse_madt_lapic_entries()被调用以获得和LAPIC相关的信息。该函数做的事情比较多,依次执行下列步骤:

a、  调用acpi_parse_lapic_addr_ovr()检查是否有LAPIC address override entry,如有,用其中的LAPIC地址覆盖acpi_lapic_addr全局变量。

b、  至此,系统的LAPIC地址就已确定了。调用mp_register_lapic_address()注册,如下:

mp_lapic_addr = (unsigned long) acpi_lapic_addr;

set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);

            set_fixmap_nocache()建立一个un-cacheableidentify mapping映射。

c、  调用acpi_parse_lapic()解析LAPIC entry。如果LAPIC entryflag字段为enable,将LAPIC IDProcessorID的对应关系维护在x86_acpiid_to_apicid全局数组中。并调用mp_register_lapic()注册LAPIC信息。

笔者:ACPILAPIC entryMP specprocessor entry对应。mp_register_lapic()最终调用MP_processor_info()注册CPU信息。为了不把话题铺的太开,我们不介绍这个过程。

d、  最后调用acpi_parse_lapic_nmi(),该函数除打印一些信息,以及在NMI没有接到LINT1脚时打印一条警告信息,并没有实际用处。

4、  如果解析到了LAPIC信息,并且没有错误发生,acpi_parse_madt_lapic_entries()函数返回0表示执行成功,此时会继续解析IOAPIC entry    acpi_parse_madt_ioapic_entries()进行如下工作:

a、  调用acpi_parse_ioapic()解析IOAPIC entry,并调用mp_register_ioapic()注册IOAPIC信息,等同mp_ioapic_info()。此外,它还注册IOAPIC对应的struct mp_ioapic_routing结构。

b、  调用acpi_parse_int_src_ovr()解析ISO条目,如发现override,调用acpi_sci_ioapic_setup()重载SCI中断,以及调用mp_override_legacy_irq()重载ISA中断。

c、  至此,ISA中断的信息已经全部获得了,调用mp_config_acpi_legacy_irqs()配置ISA中断。该函数功能等同construct_default_ioirq_mptable()

d、  调用acpi_parse_nmi_src()解析NMI entry,仅打印相关信息。从kernel的注释来看,Linux还不支持IOAPIC管脚配置成NMI

到此为止,无论是从MP spec路径,还是ACPI路径。Linux完成了平台APIC系统的探测。我们来看看目前得到了些什么东西:

u  LAPIC地址

u  IOAPIC相关信息,在mp_ioapics数组中

u  中断源相关信息,在mp_irqs数组中

嗯,看上去够了。

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