附录参考 - 📘 附录 B 概览:主机软件如何构造 NVMe 命令 (第450页)
NVME2.0协议解读 1 min read

附录参考 - 📘 附录 B 概览:主机软件如何构造 NVMe 命令 (第450页)

Blog Author

我们现在进入了 《NVM Express® Base Specification, Revision 2.0b》附录 B:主机端的设计考量(Annex B. Host Considerations) 的分析环节。这个附录主要是面向主机软件开发者,从构建指令、管理队列的角度,提供一些具体的指导与流程建议。


📘 附录 B 概览:主机软件如何构造 NVMe 命令


B.1 构建 NVMe 命令的基本步骤

主机软件向控制器发出命令前,需要经过以下几个步骤来构造并提交命令:

✅ 步骤一:确认 Submission Queue(提交队列)未满

  • NVMe 队列是循环队列,当队列中命令数达到队列大小减一时,视为已满
  • 如果队列未满,主机可以在空槽 SQ[pFreeSlot] 中构造命令。

✅ 步骤二:构建命令字段

字段 说明
CDW0.OPC 设置为对应的操作码,例如读(02h)、写(01h)等
CDW0.FUSE 是否是 Fused Command 的一部分,通常为 00b
CDW0.CID 命令标识符,需在该队列中唯一
NSID 指定该命令要操作的命名空间 ID
MPTR 若使用单独的 Metadata Buffer,则需填入其地址
PRP1/PRP2SGL Entry 1 若有数据传输,指定数据缓冲区物理地址
CDW10–CDW15 指令特定的参数字段,按命令类型决定其含义

✅ 步骤三:通过 Transport 层触发命令提交

如 PCIe 的 MMIO 操作,或者 Fabrics 上的传输层驱动。


B.2 创建 I/O Submission Queue 的流程

这一小节详细解释了如何通过 Admin 命令创建一个 使用非连续物理内存地址(PRP List) 的 I/O 提交队列(I/O Submission Queue)。

✅ 前提条件:

  1. 控制器需支持非连续 PRP(CAP.CQR = 1);
  2. 创建 I/O SQ 前必须 先创建对应的 I/O Completion Queue(CQ)

✅ 构建 “Create I/O Submission Queue” 命令的步骤如下:

字段 设置内容 说明
CDW0.OPC 01h 操作码,表示创建 I/O SQ
CDW0.FUSE 00b 非 Fused 操作
CDW0.CID 任一可用命令 ID 在 Admin SQ 中唯一
NSID 0h 因为 SQ 非命名空间相关
MPTR 0h 无 metadata
PRP1 指向 PRP List 的物理地址 说明 SQ 本体的地址
PRP2 0h 不使用第二个地址
CDW10.QSIZE 191(表示 192 项) 队列深度,不超过 CAP.MQES
CDW10.QID SQ ID 要创建的 SQ 的标识符
CDW11.CQID CQ ID SQ 将关联的 Completion Queue
CDW11.QPRIO 10b Medium Priority
CDW11.PC 0 表示使用 PRP List(非连续内存)

构造完成后,通过传输层提交该命令。

🔒注意:PRP List 在 SQ 生命周期内不得修改或释放,否则控制器可能访问非法内存。


🔍 小结:主机软件构建 NVMe 命令的核心关注点

  1. 确定队列状态与命令槽位(pFreeSlot)
  2. 正确填写命令结构体中的关键字段(CDW0~CDW15、PRP等)
  3. 遵守 NVMe 中的资源生命周期管理(如 PRP List 不可更改)
  4. 正确配对 SQ 与 CQ,并设置优先级与队列类型

如你希望,我可以进一步配合这部分写一个完整的 C 或 Rust 伪代码示例,来模拟 NVMe Admin 命令构造与提交流程。需要我继续吗?