多模块 Maven 依赖治理实录:${revision} + flatten + BOM 的完整实践
2026/10/23 5:01:57
CPU 访问 PCIe 设备:CPU 物理地址(PA) → Root Port(ATU) → PCIe 总线地址
PCIe 设备 访问 CPU(DMA):PCIe 总线地址 → Root Port(ATU/IOMMU)→ CPU 物理地址(PA)
中间没有魔法,全部是地址映射 + 路由转发。
完整转化路径(硬件真实流程):
ioread32(virt_addr + 0x10);虚拟地址 → MMU → **CPU PA = 0x8010_0000**Root Port 查ATU(地址转换表):
CPU PA 0x8010_0000 → 映射为 PCIe 总线地址 0x0000_0010设备只认识PCIe 总线地址,不认识 CPU PA:
总线地址 0x0010 → 设备内部寄存器偏移 0x10驱动写的是CPU PA,但设备不懂。
设备发:
PCIe 总线地址 = 0x8000_0000Root Port 查表:
PCIe 总线地址 0x8000_0000 → CPU 物理地址 0x8000_0000最终写到 DRAM。
Address Translation Unit
PCIe 地址 → IOMMU → 内存 PA| 方向 | 地址 A | 转化硬件 | 地址 B | 用途 |
|---|---|---|---|---|
| CPU→设备 | CPU 物理地址(BAR) | Root Port ATU | PCIe 总线地址 | 寄存器读写 |
| DMA←设备 | PCIe 总线地址 | Root Port / IOMMU | CPU 物理地址 | DMA 访问内存 |
| 配置访问 | ECAM 物理地址 | Root Port 解析 | BDF 路由 | 配置空间 |
每个 Bridge(Root Port / Switch Upstream / Switch Downstream)都有一张路由表,由三个寄存器构成:
这三个数,就是BDF 路由表。
当一个配置报文到达 Bridge:
目标 Bus = B 目标 Dev = D 目标 Func = FBridge 只看Bus 号 B:
B < Secondary Bus→ 报文是发给上游的 →往回发(Primary 方向)
B == Secondary Bus→ 是直连设备 →从本端口发出去Dev/Func 由设备自己判断
Secondary Bus < B ≤ Subordinate Bus→ 是我下面更深层的桥 →继续往下发(本端口)
B > Subordinate Bus→ 不归我管 →不管,丢给上游
之后每次访问该 CPU PA: