附录参考 - 🧩 比较命令 CMD0 的参数详细说明(继续) (第452页)
我们继续深入分析 NVMe Base Spec 2.0b 第 B.3 节的 Fused Operation 示例,这段内容重点是构造完整的 Compare + Write 命令对 —— 两个连续命令形成原子操作。我们从上一节命令结构接着讲下去。
🧩 比较命令 CMD0 的参数详细说明(继续)
在第一个命令 CMD0 中,即 Compare 命令,需要设置如下字段:
字段名 | 设置值 | 说明 |
---|---|---|
MPTR |
可选 | 如果元数据(Metadata)单独存在,用于指向元数据缓冲区地址 |
PRP1 |
地址 | 第一个数据页(4 KiB)的物理地址 |
PRP2 |
地址或 PRP List | 如果有多个数据页(如本例是 16 KiB,需要 4 个页),设置为 PRP List 地址 |
SGL1 |
可选 | 如果使用的是 SGL 模式,设置为 SGL Segment 描述符 |
CDW10–11.SLBA |
起始 LBA | 比较的逻辑块起点 |
CDW12.LR |
0 | 关闭 Limited Retry,允许控制器使用所有错误恢复手段 |
CDW12.FUA |
0 | 允许从缓存中读取 |
CDW12.PRINFO |
0 | 未启用端到端保护 |
CDW12.NLB |
3h | 表示比较 4 个 LBA(NLB 是 0-based) |
CDW14 、CDW15 |
0 | 未启用保护信息时清零 |
🖼️ 图解:PRP List 映射数据页结构(Figure 480)
CMD0.PRP1 → 物理地址 Page i (LBA 0)
CMD0.PRP2 → PRP List:
PRP List[0] → Page j(LBA 1)
PRP List[1] → Page k(LBA 2)
PRP List[2] → Page m(LBA 3)
✍️ CMD1:Write 命令字段说明(第二条命令)
字段名 | 设置值 | 说明 |
---|---|---|
CDW0.OPC |
01h |
Write 命令 |
CDW0.FUSE |
10b |
Fused 操作中的第二条命令 |
CDW0.CID |
新的命令 ID | 必须与 CMD0 不同,例如 0xB1 |
NSID |
与 CMD0 相同 | 同一个命名空间 |
PRP1/PRP2 |
物理地址 | 要写入的 16 KiB 数据地址列表 |
CDW10–11.SLBA |
起始 LBA | 与 CMD0 相同 |
CDW12.FUA |
0 | 写缓存可用 |
CDW12.PRINFO |
0 | 未启用保护 |
CDW12.NLB |
3h | 写入 4 个逻辑块 |
CDW13–CDW15 |
0 | 未使用保护信息 |
🔁 执行流程图
graph TD
A[构建 CMD0 - Compare] --> B[设置 FUSE = 01b]
B --> C[构建 CMD1 - Write]
C --> D[设置 FUSE = 10b]
D --> E[Doorbell 提交命令队列]
E --> F[控制器原子处理 Compare + Write]
F --> G{Compare 成功?}
G -- 是 --> H[执行 Write]
G -- 否 --> I[取消 Write]
H & I --> J[填充 CQE 到 Completion Queue]
🧠 小结:构建 Fused Compare + Write 的关键点
- 命令必须连续地放在 Submission Queue 中;
- FUSE 字段必须正确设置:
- CMD0 设置为
01b
(First Command) - CMD1 设置为
10b
(Second Command) - 两个命令都需要正确设置 CID、NSID、PRP 指针等字段;
- Doorbell 提交时 必须一次提交两个命令;
- Compare 失败,Write 被自动取消 —— 不需要主机判断。
需要我接着为你画一张 PRP List 内存映射图、或者给出这一过程的代码伪实现(如 C/C++)来帮助你更直观理解吗?还是我们继续分析下一节内容?