我们分别看一下acpi_numa_init 中的这几个函数
int __init acpi_numa_init(void)
{
/* SRAT: Static Resource Affinity Table */
if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {
acpi_table_parse_srat(ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY,
acpi_parse_x2apic_affinity, 0);
acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,
acpi_parse_processor_affinity, 0);
acpi_table_parse_srat(ACPI_SRAT_TYPE_GICC_AFFINITY,
acpi_parse_gicc_affinity, 0);
cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
acpi_parse_memory_affinity,
NR_NODE_MEMBLKS);
}
}
首先srat 表分为下面几个type
enum acpi_srat_type {
ACPI_SRAT_TYPE_CPU_AFFINITY = 0,
ACPI_SRAT_TYPE_MEMORY_AFFINITY = 1,
ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY = 2,
ACPI_SRAT_TYPE_GICC_AFFINITY = 3,
ACPI_SRAT_TYPE_RESERVED = 4 /* 4 and greater are reserved */
};
1:acpi_table_parse_srat(ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY, acpi_parse_x2apic_affinity, 0);
查找ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY = 2,
static int __init
acpi_parse_x2apic_affinity(struct acpi_subtable_header *header,
const unsigned long end)
{
struct acpi_srat_x2apic_cpu_affinity *processor_affinity;
processor_affinity = (struct acpi_srat_x2apic_cpu_affinity *)header;
if (!processor_affinity)
return -EINVAL;
acpi_table_print_srat_entry(header);
/* let architecture-dependent part to do it */
acpi_numa_x2apic_affinity_init(processor_affinity);
return 0;
}
其中acpi_table_print_srat_entry 主要是打印log,可以忽略。实际做事的函数acpi_numa_x2apic_affinity_init也是打印一行log而已.
void __init __weak
acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
{
pr_warn("Found unsupported x2apic [0x%08x] SRAT entry\n", pa->apic_id);
}
2: acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY, acpi_parse_processor_affinity, 0);
static int __init
acpi_parse_processor_affinity(struct acpi_subtable_header *header,
const unsigned long end)
{
struct acpi_srat_cpu_affinity *processor_affinity;
/* let architecture-dependent part to do it */
acpi_numa_processor_affinity_init(processor_affinity);
return 0;
}
void __init
acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
{
int pxm;
if (!(pa->flags & ACPI_SRAT_CPU_ENABLED))
return;
if (srat_num_cpus >= ARRAY_SIZE(node_cpuid)) {
printk_once(KERN_WARNING
"node_cpuid[%ld] is too small, may not be able to use all cpus\n",
ARRAY_SIZE(node_cpuid));
return;
}
pxm = get_processor_proximity_domain(pa);
/* record this node in proximity bitmap */
pxm_bit_set(pxm);
node_cpuid[srat_num_cpus].phys_id =
(pa->apic_id << 8) | (pa->local_sapic_eid);
/* nid should be overridden as logical node id later */
node_cpuid[srat_num_cpus].nid = pxm;
cpumask_set_cpu(srat_num_cpus, &early_cpu_possible_map);
srat_num_cpus++;
}
这个函数会设定node和cpu的affinity,首先得到phys_id 和nid,然后调用cpumask_set_cpu 来设定cpu mask.
3: acpi_table_parse_srat(ACPI_SRAT_TYPE_GICC_AFFINITY, acpi_parse_gicc_affinity, 0);
static int __init
acpi_parse_gicc_affinity(struct acpi_subtable_header *header,
const unsigned long end)
{
struct acpi_srat_gicc_affinity *processor_affinity;
processor_affinity = (struct acpi_srat_gicc_affinity *)header;
if (!processor_affinity)
return -EINVAL;
acpi_table_print_srat_entry(header);
/* let architecture-dependent part to do it */
acpi_numa_gicc_affinity_init(processor_affinity);
return 0;
}
/* Callback for Proximity Domain -> ACPI processor UID mapping */
void __init acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa)
{
int pxm, node;
u64 mpidr;
pxm = pa->proximity_domain;
node = acpi_map_pxm_to_node(pxm);
early_node_cpu_hwid[cpus_in_srat].node_id = node;
early_node_cpu_hwid[cpus_in_srat].cpu_hwid = mpidr;
node_set(node, numa_nodes_parsed);
acpi_numa = 1;
cpus_in_srat++;
pr_info("SRAT: PXM %d -> MPIDR 0x%Lx -> Node %d cpu %d\n",
pxm, mpidr, node, cpus_in_srat);
}
这个函数从apci表得到node_id 和 cpu_hwid。最后调用node_set将node设定到numa_nodes_parsed中
4:static int __init
acpi_parse_memory_affinity(struct acpi_subtable_header * header,
const unsigned long end)
{
struct acpi_srat_mem_affinity *memory_affinity;
memory_affinity = (struct acpi_srat_mem_affinity *)header;
/* let architecture-dependent part to do it */
if (!acpi_numa_memory_affinity_init(memory_affinity))
parsed_numa_memblks++;
return 0;
}
int __init acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
{
u64 start, end;
int node, pxm;
start = ma->base_address;
end = start + ma->length;
pxm = ma->proximity_domain;
node = acpi_map_pxm_to_node(pxm);
pr_info("SRAT: Node %u PXM %u [mem %#010Lx-%#010Lx]\n",
node, pxm,
(unsigned long long) start, (unsigned long long) end - 1);
if (numa_add_memblk(node, start, (end - start)) < 0) {
bad_srat();
return -EINVAL;
}
return 0;
}
主要是调用numa_add_memblk 来为node添加memory,其输入参数是这个node 管理memory的起始地址和size.
int __init acpi_numa_init(void)
{
/* SRAT: Static Resource Affinity Table */
if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {
acpi_table_parse_srat(ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY,
acpi_parse_x2apic_affinity, 0);
acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,
acpi_parse_processor_affinity, 0);
acpi_table_parse_srat(ACPI_SRAT_TYPE_GICC_AFFINITY,
acpi_parse_gicc_affinity, 0);
cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
acpi_parse_memory_affinity,
NR_NODE_MEMBLKS);
}
}
首先srat 表分为下面几个type
enum acpi_srat_type {
ACPI_SRAT_TYPE_CPU_AFFINITY = 0,
ACPI_SRAT_TYPE_MEMORY_AFFINITY = 1,
ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY = 2,
ACPI_SRAT_TYPE_GICC_AFFINITY = 3,
ACPI_SRAT_TYPE_RESERVED = 4 /* 4 and greater are reserved */
};
1:acpi_table_parse_srat(ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY, acpi_parse_x2apic_affinity, 0);
查找ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY = 2,
static int __init
acpi_parse_x2apic_affinity(struct acpi_subtable_header *header,
const unsigned long end)
{
struct acpi_srat_x2apic_cpu_affinity *processor_affinity;
processor_affinity = (struct acpi_srat_x2apic_cpu_affinity *)header;
if (!processor_affinity)
return -EINVAL;
acpi_table_print_srat_entry(header);
/* let architecture-dependent part to do it */
acpi_numa_x2apic_affinity_init(processor_affinity);
return 0;
}
其中acpi_table_print_srat_entry 主要是打印log,可以忽略。实际做事的函数acpi_numa_x2apic_affinity_init也是打印一行log而已.
void __init __weak
acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
{
pr_warn("Found unsupported x2apic [0x%08x] SRAT entry\n", pa->apic_id);
}
2: acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY, acpi_parse_processor_affinity, 0);
static int __init
acpi_parse_processor_affinity(struct acpi_subtable_header *header,
const unsigned long end)
{
struct acpi_srat_cpu_affinity *processor_affinity;
/* let architecture-dependent part to do it */
acpi_numa_processor_affinity_init(processor_affinity);
return 0;
}
void __init
acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
{
int pxm;
if (!(pa->flags & ACPI_SRAT_CPU_ENABLED))
return;
if (srat_num_cpus >= ARRAY_SIZE(node_cpuid)) {
printk_once(KERN_WARNING
"node_cpuid[%ld] is too small, may not be able to use all cpus\n",
ARRAY_SIZE(node_cpuid));
return;
}
pxm = get_processor_proximity_domain(pa);
/* record this node in proximity bitmap */
pxm_bit_set(pxm);
node_cpuid[srat_num_cpus].phys_id =
(pa->apic_id << 8) | (pa->local_sapic_eid);
/* nid should be overridden as logical node id later */
node_cpuid[srat_num_cpus].nid = pxm;
cpumask_set_cpu(srat_num_cpus, &early_cpu_possible_map);
srat_num_cpus++;
}
这个函数会设定node和cpu的affinity,首先得到phys_id 和nid,然后调用cpumask_set_cpu 来设定cpu mask.
3: acpi_table_parse_srat(ACPI_SRAT_TYPE_GICC_AFFINITY, acpi_parse_gicc_affinity, 0);
static int __init
acpi_parse_gicc_affinity(struct acpi_subtable_header *header,
const unsigned long end)
{
struct acpi_srat_gicc_affinity *processor_affinity;
processor_affinity = (struct acpi_srat_gicc_affinity *)header;
if (!processor_affinity)
return -EINVAL;
acpi_table_print_srat_entry(header);
/* let architecture-dependent part to do it */
acpi_numa_gicc_affinity_init(processor_affinity);
return 0;
}
/* Callback for Proximity Domain -> ACPI processor UID mapping */
void __init acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa)
{
int pxm, node;
u64 mpidr;
pxm = pa->proximity_domain;
node = acpi_map_pxm_to_node(pxm);
early_node_cpu_hwid[cpus_in_srat].node_id = node;
early_node_cpu_hwid[cpus_in_srat].cpu_hwid = mpidr;
node_set(node, numa_nodes_parsed);
acpi_numa = 1;
cpus_in_srat++;
pr_info("SRAT: PXM %d -> MPIDR 0x%Lx -> Node %d cpu %d\n",
pxm, mpidr, node, cpus_in_srat);
}
这个函数从apci表得到node_id 和 cpu_hwid。最后调用node_set将node设定到numa_nodes_parsed中
4:static int __init
acpi_parse_memory_affinity(struct acpi_subtable_header * header,
const unsigned long end)
{
struct acpi_srat_mem_affinity *memory_affinity;
memory_affinity = (struct acpi_srat_mem_affinity *)header;
/* let architecture-dependent part to do it */
if (!acpi_numa_memory_affinity_init(memory_affinity))
parsed_numa_memblks++;
return 0;
}
int __init acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
{
u64 start, end;
int node, pxm;
start = ma->base_address;
end = start + ma->length;
pxm = ma->proximity_domain;
node = acpi_map_pxm_to_node(pxm);
pr_info("SRAT: Node %u PXM %u [mem %#010Lx-%#010Lx]\n",
node, pxm,
(unsigned long long) start, (unsigned long long) end - 1);
if (numa_add_memblk(node, start, (end - start)) < 0) {
bad_srat();
return -EINVAL;
}
return 0;
}
主要是调用numa_add_memblk 来为node添加memory,其输入参数是这个node 管理memory的起始地址和size.