参考acpi_madt_io_apic结构,如果一个io apic是系统中的第二个io apic,而第一个io apic的中断
数目是24, 那么第二个io apic的global_irq_base就是24 -- 亦即,第二个io apic的中断输入从第
24开始递增。
12. SRAT表(System Resource Affinity Table)
该表可选.
13, E820及其它(ACPI spec, CH14)
传统的PC使用INT 15H这个BIOS调用来获得内存布局; 用EFI的系统,则可以通过EFI的一个boot service:
GetMemoryMap()函数,来获取内存布局.
OS loader获取的memory map,然后把它传递给OSPM。
1). ACPI定义了5种类型的内存范围:
Value || Mnemonic Description
==================================================================================
1 || AddressRangeMemory 该范围是OS可用的RAM
==================================================================================
2 || AddressRangeReserved 由system使用或保留,OS不得使用
==================================================================================
3 || AddressRangeACPI ACPI占用的内存。当OS读取了ACPI Tables后,它就可
|| 以使用这块RAM了。
================================================================================== 4 || AddressRangeNVS ACPI NVS内存
==================================================================================
5 || AddressRangeUnusuable 该范围的内存有错误,OS不可使用。
==================================================================================
Other || Undefined 未定义,即保留给将来。OSPM应该象对待 AddressRangeReserved一样对待它。
2). INT 15H, E820H - 查询memory map
只能在real mode使用。 \的意思是,给EAX赋值e820h,然后int 0x15来调用BIOS的15号 调用。
PC机上一共有3中memmap探测方法,Linux采用的顺序是:先使用e820h,然后使用e801h,然后使用88h。
e820h : lets us assemble a memory map e801h : returns a 32-bit memory size 88h : returns 0-64m memory
见arch/i386/boot/setup.S
ACPI规定的是,要作出一个int 15h,e820h BIOS调用,要准备以下的输入:
EAX : E820h
EBX : 如果是第一次调用,为0。 如果不是,则存放上次调用之后的Continuation value。ACPI
规范说,EBX应该包含上一次调用的返回值,意思是每次调用后BIOS都自动把continuation value写入了ebx中。如果BIOS往ebx写的值为0,则说明EOF,不要进行下一次调用了。 ES:DI : Buffer地址,指向一个Address Range Descriptor结构,BIOS把信息写入这个结构。
ECX : Buffer size
EDX : 签名。应该是\这4个字母的ASCII值。 Linux写作#define SMAP 0x534d4150
而输出是:
CF : 为1表示出错
EAX : 签名。为\表示正确,可以判断ebx值进行下一次调用;否则为出错,应该放弃e820方法
ES:DI : 和输入一样
ECX : Buffer size. BIOS往ES:DI写了多少字节。 最小是20字节。 EBX : Continuation Value.
Address Range Descriptor Structure: ----------------------------------
0 BaseAddrLow Low 32 Bits of Base Address 4 BassAddrHigh High 32 Bits of Base Address 8 LengthLow Low 32 Bits of Length in Bytes 12 LengthHigh High 32 Bits of Length in Bytes 16 Type Address Type of this range 20 Extended Attributes see below
其中BassAddrLow和BaseAddrHigh一起组成了64位的Base Addr。 是该range的起始物理地址。
LengthLow和LengthHigh一起组成了64位的长度,即该range的size。 Type,就是1)中说的5种类型之一了:)
扩展属性我就不抄了,见ACPI Spec CH14。表14-5.
3). 如果是EFI enabled
OS loader使用GetMemoryMap()函数--它是EFI提供的Boot Services之一--来获取memmap,并且把它传递给
OSPM。
EFI没研究,暂且不说。
4). Linux对E820 memmap的实现
Linux定义了几个内存地址:
#define E820MAP 0x2d0 #define E820NR 0x1e8
和E820最多能有多少entries:
#define E820MAX 128
而在setup.S中:
设置ES:DI的值为E820MAP,以便调用int 15h,e820h时让BIOS把memmap写入这个地址:
movw $E820MAP, %di
在每次调用int 15h,e820h时,都增加(E820NR)的值:
incb (E820NR)