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

2011年(1)

2010年(28)

2008年(15)

分类:

2010-03-08 11:31:10

路径 表结构

MADT表的entry和MP 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规定,LAPIC和IOAPIC的寄存器必须被实现成MMIO方式。对于LAPIC来说,每个CPU使用同样的地址访问自己的LAPIC,默认地址是FEE0_0000H。对于IOAPIC,默认基地址是FEC0_0000H,每个IOAPIC占4k地址,从基地址开始连续。

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

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

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

字段

长度(bytes)

偏移

描述

Type

1

0

0(LAPIC)

Length

1

1

8

ACPI Processor ID

1

2

在ACPI processor operator中列出的processorID

APIC ID

1

3

LAPIC ID

Flags

4

4

Bit0:enable位,

0:disable;

1:enable。

其它bit预留

表2-5  LAPIC entry

字段

长度(byte)

偏移

描述

Type

1

0

4(LAPIC NMI)

Length

1

1

6

APCI Processor ID

1

2

Processor object中的CPU的ID。0xff代表所有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

5(LAPIC 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 entry、Interrupt Source Overrides entry、NMI entry。

字段

长度(bytes)

偏移

描述

Type

1

0

1(IOAPIC)

Length

1

1

12

IOAPIC ID

1

2

IOAPIC ID

Reserved

1

3

0

IOAPIC address

4

4

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

GSI Base

4

8

该IOAPIC在GSI空间中的起始号。GSI=GSI base+管脚号

表2-9 IOAPIC entry

字段

长度(bytes)

偏移

描述

Type

1

0

2(interrupt source override)

Length

1

1

10

Bus

1

2

0(ISA)

Source

1

3

在ISA上的IRQ号

GSI

4

4

Map到GSI空间后的GSI号

Flags

2

8

见MP INIT flags表

表2-10 Interrupt Source Overrides(ISO)

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

举两个例子:

例1:PIT接PIC的0号脚,即IRQ0。当接IOAPIC时,它通常接在2号管脚上,即INTN2。此时需要一个ISO来描述此差异,source字段为0,GSI字段为2(0号IOAPIC的GSI base为0)。

例2:SCI,System Control Interrupt,通常接PIC的管脚9,即IRQ9,FADT会在SCI_INT字段里报告该值。如接到IOAPIC的11号脚,则需要一个ISO描述。Source字段为9,GSI字段为11。

字段

长度(bytes)

偏移

描述

Type

1

0

3(NMI)

Length

1

1

8

Flags

2

2

见MPS INIT Flags

GSI

4

4

该NMI的GSI号

表2-11 NMI entry

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

中断探测过程

X86的ACPI相关代码位于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-cacheable的identify mapping映射。

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

笔者:ACPI的LAPIC entry和MP spec的processor 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数组中

嗯,看上去够了。

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