/* Predefined (fixed) table indexes */ #define ACPI_TABLE_INDEX_DSDT (0) #define ACPI_TABLE_INDEX_FACS (1)
16, ACPI in Linux: 启动和初试化 /*{{{*/
0). NND,最先执行的ACPI函数不是acpi_early_init(),害我cscope查了半天!
start_kernel() > setup_arch() > acpi_boot_table_init() > acpi_table_init() > acpi_initialize_tables():
> acpi_boot_init() > acpi_table_parse(boot) > acpi_table_parse(fadt) > acpi_process_madt() > Note > acpi_table_parse(hpet)
acpi_process_madt()函数:
static void __init acpi_process_madt(void) {
#ifdef CONFIG_X86_LOCAL_APIC int error;
/** 寻找MADT表,找到的话,在其上运行acpi_parse_madt()函数 */ if ( !acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt) ) {
/*
* Parse MADT LAPIC entries -- 找到MADT中的LAPIC
* ADDRESS OVERRIDE结构, 再找MADT中的Local APIC结构, * 把找到的APIC的物理地址映射到FIXMAP保留的线性地址上 */
error = acpi_pase_madt_lapic_entries(); if (!error) { //success acpi_lacpi = 1;
#ifdef CONFIG_X86_GENERICARCH generic_bigsmp_probe(); #endif /*
* Parse MADT IO-APIC entries */
error = acpi_parse_madt_ioapic_entries(); if (!error) {
acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC; acpi_irq_balance_set(NULL); acpi_ioapic = 1;
smp_found_config = 1; setup_apic_routing(); } }
if(error == -EINVAL) {
printk(\
disable_acpi(); } }
#endif//Local APIC return; }
这个函数是X86 SMP机器的关键代码,它负责找出系统中全部的LAPIC和IO-APIC。
先看看acpi_initialze_tables函数:
acpi_status __init acpi_initialize_tables(struct acpi_table_desc *initial_table_array, u32 initial_table_count, u8 allow_resice) {
acpi_physical_address rsdp_address; acpi_status status;
/* 如果initial_table_array为NULL,我们就申请一个; * 如果非NULL,说明它是整个ACPI表数组的首地址 *
* 其定义为:
* static struct acpi_table_desc initial_table[ACPI_MAX_TABLES] __initdata; * */
if (!initial_table_array) {
/*设置flag中的ACPI_ROOT_ALLOW_RESIZE*/
status = acpi_allocate_root_table(initial_table_count);
} else {
/* Root Table Array has been statically allocated * by the host.
* --什么意思?我猜测是:ACPI表数组(initial_tables)已经由BIOS静态分配好了, * 猜测是位于RAM中。 */
ACPI_MEMSET(initial_table_array, 0,
initial_table_count * sizeof(struct acpi_table_desc) );
/* XXX :
* 下面这3行代码很重要。在这个赋值操作发生之后,ACPI一直使用全局变量 * acpi_gbl_root_table_list来进行操作。 */
acpi_gbl_root_table_list.tables = initial_table_array;
acpi_gbl_root_table_list.size = initial_table_count; //表的个数,不是字节数 acpi_gbl_root_table_list.flags = ACPI_ROOT_ORIGIN_UNKOWN; }
/**
* 取得RSDP的地址。又分为EFI和非EFI两种情况,注意看实现方法 */
rsdp_address = acpi_os_get_root_pointer(); if (!rsdp_address)
return_ACPI_STATUS(AE_NOT_FOUND);
/**
* 已经有RSDP了,就意味着知道了RSDT或XSDT的地址,好了,取出所有的Tables! * XXX : Note,这步非常关键,因为它负责读取所有的ACPI Tables
*/
status = acpi_tb_parse_root_table(rsdp_address, ACPI_TABLE_ORIGIN_MAPPED);
return_ACPI_STATUS(status); }
(Section 0)内核脚注:
===================
acpi_boot_table_init() and acpi_boot_init() called from setup_arch(), always: 1. checksums all tables; 2. enumerates lapics 3. enumerates io-apics
acpi_table_init() is seperate to allow reading SRAT without other side effects
side effects of acpi_boot_init: acpi_lapic = 1 if LAPIC found acpi_ioapic = 1 if IO-APIC found
if (acpi_lapic && acpi_ioapic) smp_found_config = 1; if acpi_blacklisted() acpi_disabled = 1; acpi_irq_model = ... ...