ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

第三章:FPGA PCIe Root Port 与 Endpoint 有什么区别?NVMe SSD 为什么需要 Host

第三章:FPGA PCIe Root Port 与 Endpoint 有什么区别?NVMe SSD 为什么需要 Host 本篇位置FPGA NVMe Host 实战连载 · 第一幕共同底座 · 第 03 篇第 02 篇已经把 M.2 SSD 的供电、参考时钟、复位和 Lane 检查了一遍。假设现在user_lnk_up1LTSSM 已经进入 L0说明 FPGA 与 SSD 的 PCIe 物理链路已经可以传输数据。但这时 SSD 还没有真正“被识别”。如果 FPGA 不主动发起配置访问SSD 不会自己把 Vendor ID、BAR 或 NVMe 寄存器送到 FPGA 面前。原因在于两端的 PCIe 角色不同三星 980 这样的 NVMe SSD 是EndpointFPGA 直连 SSD 时需要站在Root Port和 Host 一侧负责从配置空间访问开始把后面的枚举、BAR、NVMe 初始化和数据通路逐步建立起来。本文沿着下面这条控制路径展开FPGA Root Port → PCIe Configuration Request → NVMe SSD Endpoint → Completion → FPGA先把这几个角色分清后面的 Vendor ID、BAR、CAP、CC、CSTS、队列和 DMA 才不会混在一起。PC 和 FPGA 直连 SSD谁在做 Host在 PC 里CPU、芯片组、固件和操作系统共同承担 Host 一侧工作。SSD 插入 M.2 插槽后系统会完成配置访问、资源分配和驱动初始化用户平时几乎看不到这些步骤。FPGA 直连 SSD 时PC 的那套软件环境不在链路上。SSD 面前的上游设备就是 FPGA因此配置访问和 NVMe Host 所需的逻辑要由 FPGA 工程实现。图 1PC 和 FPGA 直连 SSD 的共同点是SSD 都处于 PCIe Endpoint 一侧差别在于由 PC 或 FPGA 承担 Host 工作。这里有一个词需要分开说。Root Complex可以理解为 PCIe 树最上游的 Host 一侧整体。它把处理器、内存和 PCIe 域接在一起并为下游设备提供访问路径和资源管理。Root Port是 Root Complex 面向下游设备的端口。它直接与 Endpoint 建链并能够向下游发起 PCIe 访问。Endpoint是被上游发现和配置的设备。本文的三星 980 1TB 对 PCIe 来说是 Endpoint它内部包含 NVMe 控制器和 NAND Flash。在一个 FPGA 直连单块 SSD 的工程里没有必要照搬完整 PC 的软件体系。但从 SSD 的角度看FPGA 仍要完成这个 Root Port 需要完成的工作先发起配置访问再建立可访问的 NVMe 控制器路径。Root Port 不是 Endpoint 的另一种叫法很多 FPGA PCIe 示例工程默认采用 Endpoint 模式。它们的目标通常是把 FPGA 做成一张 PCIe 扩展卡让 PC 枚举 FPGA并访问 FPGA 暴露出来的 BAR。这个方向没有问题只是和“FPGA 直连 SSD”正好相反。场景上游 Root Port / HostEndpoint谁先发起配置访问PC 插 FPGA 加速卡PCFPGAPCFPGA 直连 NVMe SSDFPGANVMe SSDFPGA因此不能只把 PCIe 差分线接好再拿一个 Endpoint 示例工程去等待 SSD 工作。即使链路训练成功两个只按 Endpoint 方式工作的设计之间也没有一方承担枚举、资源分配和下游配置请求的责任。这里要说得严谨一些这不等于“两个 Endpoint 的电气链路一定无法建立”。问题在于即便底层链路能够进入 L0SSD 也不会因此自动变成可供 FPGA 使用的 NVMe 设备。它仍在等待上游 Host 的后续动作。AMD 的 7 系列 PCIe IP 本身支持 Endpoint 和 Root Port 两种配置。本文使用的 XC7Z100 平台将 PCIe IP 配置为 Root Port但 IP 角色配置只是起点后续的配置请求、Completion 处理和 NVMe Host 逻辑仍要由工程逻辑完成。Root Port 自己也有配置空间Root Port 和 Endpoint 都有配置空间但使用的配置头类型不同。AMD PG054 中明确区分了两者Endpoint 使用 Type 0 HeaderRoot Port 应用使用 Type 1 Header。图 2AMD《PG054 v3.3》Table 25p.44。Root Port 使用的 Type 1 PCI Configuration Space Header非本项目实测截图。这张表不用在本篇逐字段背下来但可以先看出 Root Port 和普通 Endpoint 的侧重点不同。Type 1 Header 中出现了 Primary Bus Number、Secondary Bus Number、Subordinate Bus Number以及 Memory Base、Memory Limit 等桥接和下游资源相关字段。对本项目来说最重要的理解是FPGA 不只是“链路另一端”。它需要作为上游端知道怎样访问下游 SSD并为后续的地址分配和控制器寄存器访问做好准备。先把最小的配置读取走通才能对这些后续工作建立可靠的判断。SSD 作为 Endpoint会暴露什么给 HostNVMe SSD 并不是一块把 NAND 地址直接接到 PCIe 总线上的存储器。它首先是一个 PCIe Endpoint具有 PCI Header、PCIe Capability、MSI/MSI-X 和 AER 等 PCIe 结构在此基础上才通过 BAR 暴露 NVMe 控制器寄存器。NVM Express 的 NVMe over PCIe Transport 规范列出了这些 PCIe 寄存器结构并说明控制器属性映射在 MLBAR/MUBAR 指定的地址范围也就是 PCI BAR0/BAR1 对应的内存窗口。图 3NVM Express《NVMe over PCIe Transport Specification v1.4》Figure 3p.9。图中列出 NVMe PCIe 控制器的 PCI Header、Capability 与 AER 结构下方文字说明控制器属性由 BAR0/BAR1 指定的内存窗口访问。这也解释了为什么不能跳过 PCIe 枚举直接读 CAP 或写 CC在访问 NVMe 控制器寄存器前Host 先要确认 Endpoint 存在读取配置空间并处理 BAR 等 PCIe 层的前置条件。Link Up 后第一件事是谁发起链路进入 L0 后SSD 不会先“报告自己是 NVMe SSD”。最小的下一步是由 FPGA Root Port 发起 Configuration Read。SSD 作为 Endpoint 返回 Completion with DataFPGA 可以先从返回数据中确认 Vendor ID判断下游设备是否已经被正确识别。图 4从 PCIe Link Up 到读取配置空间标识信息的最小控制路径。图为项目调试路径示意不是完整 PCIe 枚举状态机。这张图有两个方向不能混淆。FPGA 先发出 Configuration Read请求读取 SSD 的配置空间。SSD 返回 Completion with Data带回这次读取的结果。因此user_lnk_up1的意义是“现在可以开始发起这类访问了”而不是“Vendor ID 已经读到”。读到有效的 Vendor ID才是枚举真正有了第一个可验证结果。这条路径在板上需要确认三件事请求是否从 FPGA 发出、SSD 是否返回 Completion with Data、返回的配置空间字段能否被正确解析。后续上板实测章节会用这三个观察点给出完整结果本篇先把 Root Port 与 Endpoint 的职责和通信方向理清。SSD 后面也会主动发数据为什么它仍不是 Host这个问题很容易让人困惑。后面的 NVMe 读命令执行时SSD 会通过 PCIe Memory Write 把读取结果 DMA 到 Host 提供的内存地址写入 SSD 时SSD 还会通过 Memory Read 取得 Host 准备好的数据。看上去 SSD 也会主动发 TLP。但这不改变它是 Endpoint 的角色。因为这些动作发生在 Host 已经完成控制器初始化、建立队列并通过 PRP 提供 Host Memory 地址之后。SSD 是按照 Host 提交的 NVMe 命令执行数据传输不是主动承担配置、枚举和资源管理的一方。可以把两件事分开看阶段谁先发起SSD 的角色PCIe 枚举FPGA Root Port返回配置访问的 CompletionNVMe 控制器初始化FPGA NVMe Host响应寄存器访问进入 ReadyNVMe 读取数据FPGA 提交 NVM Read依据 PRPDMA 写入 Host MemoryNVMe 写入数据FPGA 提交 NVM Write依据 PRP读取 Host Memory 中的数据角色说的是 PCIe 拓扑和控制责任不是“哪一侧永远不能发起任何数据包”。从 Root Port IP 到可用系统工程怎样分层“PCIe IP 已配置为 Root Port”并不等于“FPGA 已经是完整 NVMe Host”。在这个工程里至少还有下面几层工作。图 5本篇重点在第 2 层 PCIe Host。第 02 篇解决物理链路后续章节再进入 NVMe Host 与两条数据通路。物理链路层确认供电、REFCLK、PERST#、Lane 和 LTSSM最终进入 L0。这是第 02 篇解决的问题。PCIe Host 层Root Port 发起配置访问、读取配置空间、完成枚举并处理 BAR。这是当前和接下来几篇的重点。NVMe Host 层读取 CAP、配置 CC、等待 CSTS建立 Admin Queue 和 I/O Queue。数据通路层让 SSD 能依据 PRP 访问 PS DDR 或 PL DDR并完成 DMA、缓冲和校验。这四层按顺序依赖。前一层没有证据后面的调试就容易变成猜测。例如如果配置空间还读不到就不应先检查 CC.CSTS如果队列还没有建立也不能要求 SSD 把用户数据 DMA 到 DDR。三个容易走偏的判断1. “Link Up 了说明 NVMe 驱动有问题”不一定。Link Up 只说明 PCIe 物理链路可用。下一步应该观察 Configuration Request 有没有发出、Completion 有没有回来、返回数据是否合理。NVMe 初始化还在更后面。2. “用 Endpoint 示例工程SSD 应该会自动被识别”不会。Endpoint 示例适合让 PC 枚举 FPGA而 FPGA 直连 SSD 时FPGA 需要改为 Root Port 和 Host 侧角色。两种场景的上游、下游方向不同。3. “SSD 会 DMA所以 SSD 也算 Host”不算。SSD 的 DMA 是在 Host 提交 NVMe 命令并给出 PRP 地址后执行的。枚举、BAR、控制器初始化和队列建立仍由 FPGA Host 发起。本篇自查清单检查项需要看到的结果还不能据此断定什么PCIe IP 角色Root Port 模式不代表已经完成枚举物理链路LTSSML0user_lnk_up1不代表配置空间可读配置访问FPGA 发起请求收到 Completion不代表 BAR 已配置完成小结FPGA 直连 NVMe SSD 时SSD 是 PCIe EndpointFPGA 需要位于 Root Port 和 Host 一侧。链路进入 L0 后第一件需要做的事不是提交 NVMe 命令而是由 FPGA 发起 Configuration Request读取 SSD 配置空间并确认设备存在。具体的板上读取结果放在后续实测章节展示。Root Port 模式解决的是“谁来面对下游 SSD”从这里到稳定的 NVMe 读写系统还会经历枚举、BAR、控制器初始化、队列和数据通路等层次。下一篇先看链路进入 L0 后真正在线上运行的内容TLP、DLLP 和 Completion 分别是什么Configuration Read、Memory Read 与 Memory Write 各自承担什么角色。随后几篇会从配置空间访问开始把请求发送、返回接收和结果解析的工程过程逐步讲清楚。参考资料AMDPG054 v3.37 Series FPGAs Integrated Block for PCI Express本文图 2 引用 Table 25p.44文中 Root Port / Endpoint 配置能力参见 p.5。NVM ExpressNVMe over PCIe Transport Specification v1.4本文图 3 引用 Figure 3p.9BAR0/BAR1 映射说明位于同页。NVM ExpressBase Specification v2.4用于 Host、Controller 和 PCIe Memory-Based Transport 术语核对。PCI-SIG SpecificationsPCIe 术语与规范入口。
返回列表