3. 高位寻址设备定义:64位DMA、双周期地址周期(DAC)、地址扩展
在PCI/PCIe DMA子系统中,高位寻址设备是指能够访问超过32位物理地址空间的设备。这类设备通常用于高性能计算、大容量存储或GPU加速场景,需要直接与系统物理内存中高于4GB的地址区域进行数据交换。理解高位寻址设备的三种核心特征——64位DMA、双周期地址周期(DAC)和地址扩展——是正确配置DMA寻址掩码的前提。
3.1 64位DMA:地址宽度的跃升
64位DMA是高位寻址设备最直观的特征。传统32位DMA只能寻址0x00000000~0xFFFFFFFF(4GB)的物理地址空间,而64位DMA将地址总线宽度扩展至64位,理论上可寻址16EB(Exabyte)的地址空间。在实际系统中,64位DMA通常用于访问高于4GB的物理内存区域,即高位内存(High Memory)。
pci_set_dma_mask() 或 dma_set_mask() 设置掩码为 DMA_BIT_MASK(64),即0xFFFFFFFFFFFFFFFF,才能启用完整的64位地址能力。
下表对比了32位与64位DMA的核心差异:
| 特性 | 32位DMA | 64位DMA |
|---|---|---|
| 地址宽度 | 32位 | 64位 |
| 最大寻址范围 | 4GB | 16EB(实际受系统限制) |
| 典型应用 | 传统外设、低端嵌入式 | GPU、NVMe SSD、RDMA网卡 |
| DMA掩码设置 | DMA_BIT_MASK(32) |
DMA_BIT_MASK(64) |
| 地址周期数 | 单周期 | 双周期(DAC) |
dma_set_mask_and_coherent() 尝试设置最高支持的掩码,并回退到较低掩码。
3.2 双周期地址周期(DAC):PCI总线的地址传输机制
在PCI总线协议中,双周期地址周期(Dual Address Cycle, DAC)是64位DMA设备在32位PCI总线上传输64位地址的机制。由于PCI总线地址周期(Address Phase)默认只传输32位地址,DAC通过两个连续的地址周期来传输完整的64位地址:第一个周期传输低32位,第二个周期传输高32位。
DAC的工作流程如下:
- 发起DMA操作: 设备需要访问高于4GB的物理地址。
- 检查DAC支持: 系统软件检查设备配置空间的DAC支持位(位于Command寄存器或扩展能力寄存器)。
- 发送双周期地址: 设备在地址周期中先发送低32位地址,再发送高32位地址。
- 桥接转发: PCI-to-PCI桥或Host Bridge识别DAC标志,将64位地址正确路由到目标内存控制器。
- 数据传输: 数据周期正常进行,使用标准的数据传输协议。
3.3 地址扩展:配置空间中的DAC支持位
地址扩展是PCI/PCIe配置空间中用于标识设备是否支持64位DMA的机制。在PCI配置空间的Command寄存器(偏移0x04)中,第10位(Bit 10)被定义为DAC支持位(Dual Address Cycle Support)。当该位被置1时,表示设备能够发起或接收双周期地址周期。
对于PCIe设备,地址扩展能力通过Device Capabilities寄存器(在PCIe扩展能力空间中)的Max Payload Size和地址宽度字段来体现。PCIe规范要求所有支持64位地址的RC(Root Complex)和EP(Endpoint)必须在配置空间中声明其地址扩展能力。
PCI_COMMAND 寄存器并检查 PCI_COMMAND_DAC 标志(0x0400)来判断设备是否支持DAC。示例代码:
u16 cmd;
pci_read_config_word(dev, PCI_COMMAND, &cmd);
if (cmd & PCI_COMMAND_DAC) {
dev_info(&dev->dev, "设备支持DAC(64位DMA)\n");
} else {
dev_info(&dev->dev, "设备仅支持32位DMA\n");
}
3.4 高位寻址设备的识别与配置清单
在实际嵌入式或服务器系统中,识别高位寻址设备并正确配置DMA掩码是系统稳定性的关键。以下清单总结了识别和配置步骤:
| 步骤 | 操作 | 验证方法 |
|---|---|---|
| 1 | 读取设备配置空间的Command寄存器 | 检查Bit 10(DAC支持)是否为1 |
| 2 | 检查PCIe扩展能力中的地址宽度 | 读取Device Capabilities寄存器 |
| 3 | 调用 pci_set_dma_mask() 尝试64位掩码 |
检查返回值是否为0(成功) |
| 4 | 若失败,回退到40位、48位或32位掩码 | 使用 dma_set_mask_and_coherent() 统一设置 |
| 5 | 分配DMA缓冲区并验证地址范围 | 使用 dma_alloc_coherent() 并检查返回的物理地址 |
dma_set_mask(dev, DMA_BIT_MASK(48)) 来匹配硬件实际能力,避免DMA操作失败。
3.5 高位寻址设备的系统架构关系
高位寻址设备在系统中的位置决定了DMA地址转换的路径。下图展示了64位DMA设备通过IOMMU或直接访问系统内存的典型架构:
在高位寻址设备中,DMA地址的最终目标可能是系统内存中的高位区域(>4GB)或低位区域(<4GB)。驱动程序必须根据设备能力和系统配置,选择合适的DMA掩码,确保地址转换路径正确无误。