2. SMP系统基础:对称多处理架构、CPU拓扑结构、ACPI与设备树描述

对称多处理(SMP)是现代多核处理器系统的核心架构,也是Linux内核启动流程中CPU热插拔与SMP协同的基础。本章深入剖析SMP系统的三大支柱:对称多处理架构、CPU拓扑结构,以及硬件描述标准(ACPI与设备树)。

2.1 对称多处理架构(SMP)

SMP架构的核心特征是所有处理器核心(CPU Core)共享同一物理内存地址空间,并通过共享总线或交叉开关互联。每个核心运行独立的指令流,但访问同一份操作系统内核与应用程序代码。

SMP关键特性:
  • 对称性:所有CPU核心在功能上对等,无主从之分(BSP在启动阶段临时特殊,启动后变为普通核心)。
  • 共享内存:所有核心通过统一地址空间访问内存,缓存一致性协议(如MESI)保证数据同步。
  • 并发执行:多个核心可同时执行不同进程或线程,提升系统吞吐量。
  • 一致性:硬件保证内存访问顺序与原子操作,操作系统无需额外同步即可实现基本互斥。

下图展示了SMP系统的典型架构,其中所有CPU核心通过系统总线连接到共享内存与I/O控制器:

SMP对称多处理架构 CPU Core 0 L1/L2 Cache CPU Core 1 L1/L2 Cache CPU Core 2 L1/L2 Cache CPU Core 3 L1/L2 Cache L3 共享缓存 (LLC) 系统总线 / 交叉开关 共享内存 (DRAM) I/O 控制器
架构启示:SMP的对称性使得Linux内核可以统一调度所有核心,无需区分主从。但启动初期,BSP(引导处理器)负责初始化内核,AP(应用处理器)通过热插拔机制逐步唤醒。这种设计既保证了启动的确定性,又实现了运行时的对称性。

2.2 CPU拓扑结构

CPU拓扑描述了处理器核心之间的层级关系,包括:核心(Core)、线程(Thread/HT)、簇(Cluster)、NUMA节点(Node)等。Linux内核通过cpu_topology结构体管理这些层级,用于调度优化、负载均衡和功耗管理。

拓扑层级 Linux表示 典型粒度 调度影响
线程(SMT) thread_sibling 超线程兄弟 共享L1/L2缓存,适合细粒度并行
核心(Core) core_sibling 物理核心 共享L2缓存,任务亲和性绑定
簇(Cluster) cluster_sibling 多核组 共享L3缓存,跨簇通信延迟较高
NUMA节点 numa_node 物理CPU插槽 内存访问延迟差异,远端内存访问慢

下图展示了一个典型的ARM big.LITTLE CPU拓扑结构,包含两个簇(性能簇与效率簇),每个簇包含4个核心:

CPU拓扑结构示例:ARM big.LITTLE 性能簇 (Performance Cluster) Core A76 #0 L1 64KB / L2 256KB Core A76 #1 L1 64KB / L2 256KB Core A76 #2 L1 64KB / L2 256KB Core A76 #3 L1 64KB / L2 256KB L3 共享缓存 2MB 效率簇 (Efficiency Cluster) Core A55 #4 L1 32KB / L2 128KB Core A55 #5 L1 32KB / L2 128KB Core A55 #6 L1 32KB / L2 128KB Core A55 #7 L1 32KB / L2 128KB L3 共享缓存 1MB 片内互联 (CCI/CMN)
拓扑感知调度:Linux内核的调度器(CFS)利用CPU拓扑信息进行负载均衡。当唤醒一个进程时,调度器优先选择同一核心的兄弟线程(共享缓存),其次选择同一簇的核心,最后才考虑跨簇或跨NUMA节点。错误的拓扑信息会导致性能下降或功耗失控。

2.3 ACPI与设备树描述

ACPI(高级配置与电源接口)和设备树(Device Tree)是两种主流的硬件描述标准,用于向操作系统传递CPU拓扑、中断控制器、内存映射等静态信息。Linux内核在启动初期解析这些信息,构建CPU拓扑结构并初始化SMP子系统。

2.3.1 ACPI(x86/ARM64服务器)

ACPI使用表格(Table)描述硬件,关键表格包括:

  • MADT(Multiple APIC Description Table):描述CPU核心、GIC(通用中断控制器)、IO-APIC等中断控制器信息。
  • SRAT(System Resource Affinity Table):描述CPU与内存的NUMA亲和性。
  • SLIT(System Locality Information Table):描述NUMA节点间的访问延迟。
  • DSDT(Differentiated System Description Table):包含AML字节码,描述设备树状结构。

Linux内核通过acpi_parse_madt()函数解析MADT表,提取每个CPU核心的APIC ID,并构建cpu_possible_mask位图:

// 内核源码示例:arch/x86/kernel/acpi/boot.c
static int __init acpi_parse_madt_lapic_entries(void)
{
    int count;
    
    // 解析MADT表中的Local APIC条目
    count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC,
                                  acpi_parse_lapic, MAX_LOCAL_APIC);
    if (count <= 0) {
        pr_err("No LAPIC entries found\n");
        return -ENODEV;
    }
    
    // 标记所有解析到的CPU为possible
    for_each_present_cpu(cpu)
        set_cpu_possible(cpu, true);
    
    return count;
}

2.3.2 设备树(ARM32/ARM64嵌入式)

设备树使用.dts(Device Tree Source)文件描述硬件,编译为.dtb(Device Tree Blob)传递给内核。关键节点包括:

  • cpus节点:包含每个CPU核心的子节点,定义reg(MPIDR)、enable-method(启动方式,如psci、spin-table)。
  • psci节点:描述电源状态协调接口,用于CPU热插拔和挂起。
  • interrupt-controller节点:描述GIC(通用中断控制器)的基地址和中断路由。

典型的设备树CPU描述片段:

// 设备树片段:cpus节点
cpus {
    #address-cells = <2>;
    #size-cells = <0>;
    
    cpu@0 {
        device_type = "cpu";
        compatible = "arm,cortex-a76";
        reg = <0x0 0x0>;          // MPIDR[1:0] = 0
        enable-method = "psci";    // 使用PSCI唤醒
        next-level-cache = <&l3_cache_0>;
    };
    
    cpu@1 {
        device_type = "cpu";
        compatible = "arm,cortex-a76";
        reg = <0x0 0x100>;        // MPIDR[1:0] = 1
        enable-method = "psci";
        next-level-cache = <&l3_cache_0>;
    };
    
    cpu@100 {
        device_type = "cpu";
        compatible = "arm,cortex-a55";
        reg = <0x0 0x10000>;      // MPIDR[1:0] = 0, 簇=1
        enable-method = "psci";
        next-level-cache = <&l3_cache_1>;
    };
};

下图对比了ACPI与设备树在SMP启动中的角色与流程:

ACPI vs 设备树:SMP硬件描述对比 ACPI 描述 MADT 表 (APIC/GIC) SRAT 表 (NUMA亲和性) DSDT/SSDT (AML字节码) → 内核解析表格,构建拓扑 设备树描述 cpus 节点 (reg/MPIDR) psci 节点 (enable-method) interrupt-controller (GIC) → 内核解析DTB,构建拓扑 x86/ARM64服务器 ARM32/ARM64嵌入式
关键差异:
  • ACPI 是动态描述,AML字节码可在运行时执行,支持热插拔和电源管理事件;适用于x86和ARM64服务器。
  • 设备树 是静态描述,编译后不可变,解析速度快;适用于嵌入式系统,启动时一次性加载。
  • 热插拔支持:ACPI通过_EJ0和_STA方法支持CPU热移除/热添加;设备树依赖PSCI或厂商自定义机制。

2.4 从硬件描述到内核拓扑

Linux内核在启动初期(start_kernel → setup_arch)解析ACPI或设备树,构建以下关键数据结构:

数据结构 含义 初始化时机
cpu_possible_mask 系统中可能存在的所有CPU 解析MADT/cpus节点后
cpu_present_mask 当前已上电的CPU 热插拔状态更新时
cpu_online_mask 已启动并参与调度的CPU 每个CPU完成初始化后
cpu_active_mask 可运行任务的CPU(热插拔迁移后) 热插拔回调完成后
cpu_topology 每个CPU的拓扑层级(thread/core/cluster/node) 解析拓扑信息后