SART表的parse

来源:互联网 发布:hello mui demo源码 编辑:程序博客网 时间:2024/05/21 05:20
在acpi_numa_init 中parse ACPI_SIG_SRAT
int __init acpi_numa_init(void)
{
    /* SRAT: Static Resource Affinity Table */
    if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {
        struct acpi_subtable_proc srat_proc[3];
        memset(srat_proc, 0, sizeof(srat_proc));
        srat_proc[0].id = ACPI_SRAT_TYPE_CPU_AFFINITY;
        srat_proc[0].handler = acpi_parse_processor_affinity;
        srat_proc[1].id = ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY;
        srat_proc[1].handler = acpi_parse_x2apic_affinity;
        srat_proc[2].id = ACPI_SRAT_TYPE_GICC_AFFINITY;
        srat_proc[2].handler = acpi_parse_gicc_affinity;
        acpi_table_parse_entries_array(ACPI_SIG_SRAT,
                    sizeof(struct acpi_table_srat),
                    srat_proc, ARRAY_SIZE(srat_proc), 0);
        cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
                        acpi_parse_memory_affinity,
                        NR_NODE_MEMBLKS);
    }
    
}
从这个函数看ACPI_SIG_SRAT表的parse分为两部分
第一部分包含cpu/x2apic/gic 的affinity.
第二部分包含memory的affinity.
if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat))
这句主要是找ACPI_SIG_SRAT表,其回调函数acpi_parse_srat
static int __init acpi_parse_srat(struct acpi_table_header *table)
{
    struct acpi_table_srat *srat = (struct acpi_table_srat *)table;
    acpi_srat_revision = srat->header.revision;
    /* Real work done in acpi_table_parse_srat below. */
    return 0;
}
并没有做各位的事情,就只得到acpi_srat_revision。实际的工作是在if中完成的
在if中定义了一个数组,分别parse cpu/x2apic/gic 的affinity

如果找到的话,就跑if中的case
srat_proc[0].id = ACPI_SRAT_TYPE_CPU_AFFINITY;
srat_proc[0].handler = acpi_parse_processor_affinity;
最终调用acpi_table_parse_srat
int __init
acpi_table_parse_entries_array(char *id,
             unsigned long table_size,
             struct acpi_subtable_proc *proc, int proc_num,
             unsigned int max_entries)
{
    acpi_get_table_with_size(id, instance, &table_header, &tbl_size);
    if (!table_header) {
        pr_warn("%4.4s not present\n", id);
        return -ENODEV;
    }
    count = acpi_parse_entries_array(id, table_size, table_header,
            proc, proc_num, max_entries);
    early_acpi_os_unmap_memory((char *)table_header, tbl_size);
    return count;
}
acpi_table_parse_entries_array 通过acpi_get_table_with_size得到ACPI_SIG_SRAT的header指针和size
然后调用acpi_parse_entries_array会分别调用cpu/x2apic/gic的回调函数
static int __init
acpi_parse_entries_array(char *id, unsigned long table_size,
        struct acpi_table_header *table_header,
        struct acpi_subtable_proc *proc, int proc_num,
        unsigned int max_entries)
{
    
    while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) <
           table_end) {
        if (max_entries && count >= max_entries)
            break;
        for (i = 0; i < proc_num; i++) {
            if (entry->type != proc[i].id)
                continue;
            if (!proc[i].handler ||
                 (!errs && proc[i].handler(entry, table_end))) {
                errs++;
                continue;
            }
            proc[i].count++;
            break;
        }
}
acpi_parse_entries_array通过while循环首先找到cpu/x2apic/gic这三个子表,然后调用cpu/x2apic/gic的handler
这三个函数分别问acpi_parse_processor_affinity/acpi_parse_x2apic_affinity/acpi_parse_gicc_affinity.
memory的affinity是通过下面这个函数完成的.其回调函数acpi_parse_memory_affinity
static int __init
acpi_table_parse_srat(enum acpi_srat_type id,
              acpi_tbl_entry_handler handler, unsigned int max_entries)
{
    return acpi_table_parse_entries(ACPI_SIG_SRAT,
                        sizeof(struct acpi_table_srat), id,
                        handler, max_entries);
}
acpi_table_parse_srat又调用
int __init
acpi_table_parse_entries(char *id,
            unsigned long table_size,
            int entry_id,
            acpi_tbl_entry_handler handler,
            unsigned int max_entries)
{
    struct acpi_subtable_proc proc = {
        .id        = entry_id,
        .handler    = handler,
    };
    return acpi_table_parse_entries_array(id, table_size, &proc, 1,
                        max_entries);
}
最终也是通过acpi_table_parse_entries_array来进行,和前面的case一样,只是这次的数组只有一个entry.

0 0