Linux PCIe驱动开发:设备树与ACPI配置对比 - 第2节
2.1 PCIe 拓扑结构:层次化与点对点
PCI Express(PCIe)采用 树形层次化拓扑,由 根复合体(Root Complex, RC)、交换器(Switch)、端点(Endpoint, EP) 以及 桥(Bridge) 组成。与传统的 PCI 共享总线不同,PCIe 使用 点对点串行链路,每个设备通过独立的通道(Lane)与上游通信。
关键概念: PCIe 拓扑中,RC 是 CPU 与 PCIe 域之间的桥梁;Switch 负责扩展端口数量并路由事务;Endpoint 是功能设备(如网卡、NVMe SSD);Bridge 用于连接旧式 PCI/PCI-X 设备。
拓扑中的关键角色
| 组件 | 功能描述 | 典型位置 |
|---|---|---|
| Root Complex (RC) | 连接 CPU/内存与 PCIe 域,生成配置、I/O、内存事务 | SoC 内部或芯片组 |
| Switch | 扩展端口,路由事务包(TLP),实现多设备共享 | 主板或扩展板 |
| Endpoint (EP) | 功能设备,发起或响应事务 | 独立设备(网卡、GPU) |
| Bridge | 连接旧式 PCI/PCI-X 总线,协议转换 | 兼容性设计 |
2.2 配置空间:PCIe 设备的“身份证”
每个 PCIe 设备(包括 RC、Switch、EP)都拥有 4KB 配置空间(传统 PCI 为 256 字节)。配置空间通过 配置读写事务(Type 0 / Type 1) 访问,由 RC 或系统软件(如 Linux 内核)在枚举阶段读取。
配置空间布局: 前 64 字节为 PCI 兼容头部(Vendor ID、Device ID、Class Code 等),剩余部分包含 PCIe 扩展能力结构(Capability Structure),如 MSI/MSI-X、Power Management、ARI 等。
配置空间关键字段
| 偏移 | 字段 | 说明 |
|---|---|---|
| 0x00 | Vendor ID | 厂商编号(如 0x8086 为 Intel) |
| 0x02 | Device ID | 设备型号编号 |
| 0x08 | Class Code | 设备分类(如 0x0108 为 NVMe) |
| 0x10-0x24 | BAR 0-5 | 基地址寄存器,定义设备内存/I/O 空间 |
| 0x34 | Capabilities Pointer | 指向第一个能力结构的指针 |
2.3 BAR 空间:设备与主存的数据通道
基地址寄存器(Base Address Register, BAR) 位于配置空间头部(偏移 0x10~0x24),共 6 个 32 位或 3 个 64 位寄存器。BAR 定义了设备需要映射到系统物理地址空间的 内存或 I/O 区域 的大小和类型。
BAR 空间的作用: 驱动程序通过 ioremap() 将 BAR 映射的物理地址转换为内核虚拟地址,从而直接读写设备寄存器或数据缓冲区。例如,NVMe 驱动通过 BAR 0 访问控制器寄存器。
BAR 类型与解码
| BAR 类型 | 编码位 | 说明 |
|---|---|---|
| 32 位内存 BAR | bit[2:1] = 00 | 映射到 32 位物理地址空间 |
| 64 位内存 BAR | bit[2:1] = 10 | 占用连续两个 BAR 寄存器,支持 64 位地址 |
| I/O BAR | bit[2:1] = 01 | 映射到 I/O 地址空间(x86 平台) |
2.4 中断机制:从 INTx 到 MSI/MSI-X
PCIe 中断机制经历了从 传统 INTx(共享中断线) 到 MSI(Message Signaled Interrupt) 再到 MSI-X(扩展 MSI) 的演进。MSI/MSI-X 通过 内存写事务(MWr) 直接向 CPU 发送中断消息,无需物理中断线。
重要区别: INTx 是边带信号(Sideband),需要中断控制器参与;MSI/MSI-X 是带内消息(In-band),通过 PCIe 数据链路层发送,延迟更低、可扩展性更强。
中断机制对比表
| 特性 | INTx | MSI | MSI-X |
|---|---|---|---|
| 信号方式 | 边带中断线 | 内存写事务 | 内存写事务 |
| 最大向量数 | 4(共享) | 32 | 2048 |
| 独立掩码 | 不支持 | 不支持 | 支持(每向量) |
| 目标地址 | 中断控制器 | 固定地址 | 每向量独立 |
| 适用场景 | 旧设备/兼容 | 通用设备 | 多队列高性能设备 |