Files
dpdk-blog/notes/phase0/day01-pcie-topology.md
T
newbie 41531c19c2 init: DPDK → DPU learning blog (VitePress)
- VitePress static site for rendering all markdown documents
- Auto-discovers .md files from dpdk-roadmap-v3 and dpdk-study-kb
- Features: full-text search, dark mode, responsive design
- Pages: roadmap, notes (Phase 0-3), product docs, knowledge base
2026-08-09 15:42:47 +00:00

128 lines
5.0 KiB
Markdown
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Phase 0 · Day 1: PCIe 总线拓扑与 Config Space
---
## 一、BDF 地址:每个设备的唯一身份
```
0000 : 02 : 01 . 0
│ │ │ └── Function (0~7) — 一个物理芯片可以有多个功能
│ │ └────── Device (0~31) — 同一总线上最多 32 个设备
│ └─────────── Bus (0~255) — 256 条总线
└───────────────── Domain (0~65535) — 多 CPU socket 系统有多个 domain
单 CPU 系统 domain=0000。多路服务器每个 socket 一个 domain。
```
DPDK 通过 BDF 地址接管网卡:`dpdk-devbind.py -b vfio-pci 02:01.0`
### 为什么需要三级?
PCI 是树形拓扑。每个 Bridge 引入一条新 bus。256 条 bus × 32 设备 × 8 功能 = 65536 个可寻址功能。如果没有 bus 层级,只靠 5-bit device 最多 32 个设备——一张显卡+一张网卡就满了。
## 二、拓扑中的四种角色
| 角色 | 你的实例 | 职责 |
|------|---------|------|
| **Root Complex** | `00:00.0` | CPU 和 PCIe 世界的桥梁,把 load/store 翻译成 TLP |
| **PCI Bridge** | `00:11.0` → Bus 02 | 传统 PCI 桥,用 subtractive decode 转发未认领的访问 |
| **PCIe Root Port** | `00:15.0` → Bus 03 | PCIe 原生桥,点对点链路,支持更高带宽 |
| **Endpoint** | `02:01.0` `03:00.0` | 叶子节点,实际的网卡设备 |
关键差异:`02:01.0` (e1000) 是挂在传统 PCI Bridge 后面的老式设备,多条设备共享 Bus 02。`03:00.0` (VMXNET3) 是 PCIe Endpoint,独享 Bus 03 的整条链路(5GT/s × x32)。
## 二、PCIe 拓扑
```
[0000:00] ← Root Complex (Host Bridge)
│ CPU 访问 PCIe 设备的唯一入口
│
├── 11.0 → [02] ← PCI Bridge (老式总线)
│ ├── 01.0 e1000 (Endpoint)
│ └── 04.0 e1000 (Endpoint)
│
└── 15.0 → [03] ← PCIe Root Port (真正的 PCI Express)
└── 00.0 VMXNET3 (Endpoint)
```
数据流:CPU → Root Complex → TLP 封装 → PCIe 链路 → Endpoint。
## 三、Config Space 完整解码
e1000 (02:01.0) 的 256 字节 Config Space,逐字段解码:
| Offset | 字段 | Hex 值 | 含义 |
|--------|------|--------|------|
| 0x00-01 | Vendor ID | 0x8086 | Intel |
| 0x02-03 | Device ID | 0x100f | 82545EM |
| 0x04-05 | Command | 0x0113 | IO+Mem enable, BusMaster OFF |
| 0x0a-0b | Class Code | 0x020000 | Network Controller |
| 0x0e | Header Type | 0x00 | Endpoint |
| 0x10-13 | BAR0 | 0xfd5c0004 | Memory@0xfd5c0000, 64bit, 128KB, Non-Prefetchable |
| 0x18-1b | BAR2 | 0xfdff0004 | Memory@0xfdff0000, 64KB |
| 0x20-23 | BAR4 | 0x00002001 | IO Port@0x2000 |
| 0x34 | Capability Ptr | 0xdc | 链表起点 |
| 0x3c | Interrupt Line | 0x07 | IRQ 7 |
| 0x3d | Interrupt Pin | 0x01 | INTA# |
BAR flag bit 解码: bit0=Memory/IO, bit[2:1]=32b/64b, bit3=Prefetchable。`0xfd5c0004` 中的 `4` = 0100₂ → 64-bit Memory, Non-Prefetchable。真实基址 = 0xfd5c0004 & ~0xF = 0xfd5c0000。
Capability 链表: 0xdc→PM(ID=1)→0xe4→PCI-X(ID=7)→0x00(End)。
## 四、VMXNET3 对比 (真正的 PCIe 设备)
| | e1000 | VMXNET3 |
|---|---|---|
| 总线 | PCI-X (老) | PCIe v2.0 |
| Capability | PM + PCI-X | PM + PCIe Express + MSI + MSI-X + Serial# |
| MSI-X | 无 | 25 向量, BAR2 offset 0, PBA offset 0x1000 |
## 五、实战踩坑
### 坑 1: Bus Master 没开
- **现象**: DPDK 启动后一个包都收不到
- **根因**: Command bit2=0 → 网卡不能 DMA
- **定位**: `lspci -vvv | grep "BusMaster"`
- **修复**: `pci_set_master(pdev)` 或 `setpci -s XX:XX.X COMMAND=0x117`
### 坑 2: 64-bit BAR 误读
- **现象**: 物理地址 >4GB 时 MMIO 地址错误
- **根因**: 只用 uint32_t 读 BAR0 低 32 位
- **修复**: 用 `resource_size_t pci_resource_start(pdev, 0)`
### 坑 3: MSI-X 向量不够
- **现象**: 多队列网卡性能不增长
- **根因**: pci_alloc_irq_vectors 返回数 < RX 队列数
- **定位**: `cat /proc/interrupts | grep PCI-MSI | wc -l`
- **修复**: 增大内核 MSI-X 限制或 BIOS 调整
### 坑 4: PCIe 链路降速
- **现象**: 100Gbps 网卡只能跑 25Gbps
- **定位**: `lspci -vvv | grep -E "LnkCap:|LnkSta:"` → Speed 2.5GT/s
- **修复**: 检查物理槽位宽度、PCIe 延长线、BIOS 设置
### 坑 5: AER 静默数据损坏
- **现象**: 偶尔出现 mbuf 数据乱码但不 crash
- **定位**: `dmesg | grep AER` → Uncorrectable Error
- **修复**: 必须换硬件,链路已不可靠
## 六、核心认知
CPU 操作网卡的全路径:
```
读 Config Space → 匹配 Vendor/Device ID → 确定驱动
→ pci_enable_device → ioremap(BAR0) → 拿到虚拟地址
→ ioread32/iowrite32 操作寄存器 → 网卡开始工作
```
BAR 是 MMIO 的入口,Config Space 是身份证,Capability 链表是扩展机制。
## 七、检验标准
- [ ] 能解释 BDF 地址含义
- [ ] 能手写 Config Space 前 16 字节字段
- [ ] 能从 hex 值解码 BAR 的基址和大小
- [ ] 能画 Capability 链表结构
- [ ] 能对比 e1000(PCI-X) vs VMXNET3(PCIe v2)
- [ ] 能解释为什么 Bus Master bit 不置位就没 DMA