队列模型 - 📘 一、Figure 94(续)——通用命令状态码定义(SCT = 0h) (第109页)
我们继续深入讲解 NVM Express® Base Specification, revision 2.0b 第 98 页,本页继续列出 通用命令状态码(Generic Command Status) 的具体值和含义。
本页重点围绕: - SGL(Scatter-Gather List)使用错误 - PRP(Physical Region Page)偏移问题 - 控制器内存使用 - 权限控制拒绝 - Keep Alive 超时 等典型错误场景的反馈机制。
📘 一、Figure 94(续)——通用命令状态码定义(SCT = 0h)
✅ 状态码清单(0Dh 到 19h)
| 代码 | 名称 | 描述 |
|---|---|---|
0Dh |
Invalid SGL Segment Descriptor | 无效的 SGL 段描述符,可能出现如下情况: ① Last Segment 包含 Segment 或另一个 Last Segment; ② Last Segment 长度非法(0h 或 1h,或非 16 的倍数); ③ 地址未 Qword 对齐。 |
0Eh |
Invalid Number of SGL Descriptors | SGL 的数量不符合规范。比如 Segment Descriptor 不是段中最后一个描述符,或命令胶囊中的 SGL 排布非法。 |
0Fh |
Data SGL Length Invalid | 数据类型 SGL 长度非法: ① 太短; ② 太长,超出控制器支持范围(参见 Identify Controller 中 SGL Support 字段)。 |
10h |
Metadata SGL Length Invalid | 元数据类型 SGL 长度非法。 |
11h |
SGL Descriptor Type Invalid | SGL 描述符类型或其类型-子类型组合为控制器不支持的值。 |
12h |
Invalid Use of Controller Memory Buffer | 控制器内存缓冲区(Controller Memory Buffer)的使用不被支持。参考 §8.3。 |
13h |
PRP Offset Invalid | PRP 条目的偏移字段非法: ① 第一项后出现非零偏移; ② 偏移不是 dword 对齐(低两位应为 00b)。 |
14h |
Atomic Write Unit Exceeded | 原子写单元大小被超出。参考适用的 I/O Command Set 说明(如 NVM 或 ZNS)。 ✅ 该状态码是 I/O Command Set Specific。 |
15h |
Operation Denied | 操作被拒绝,原因可能为缺乏访问权限(例如未通过认证机制,如 TCG)。对于读写类命令,更推荐使用 Access Denied 状态码。 |
16h |
SGL Offset Invalid | SGL 描述符中的偏移字段非法。常见于 NVMe-oF 数据胶囊(Capsule)中。 |
17h |
Reserved | 保留状态码,当前未使用。 |
18h |
Host Identifier Inconsistent Format | NVM 子系统发现有控制器在使用不同格式的 Host Identifier(64-bit 和 128-bit 同时存在)。 |
19h |
Keep Alive Timer Expired | 控制器未收到主机的 Keep Alive 命令,计时器超时。 |
🧩 二、重点状态码深入解析
1️⃣ 0Dh – Invalid SGL Segment Descriptor
此错误码在使用复杂的 SGL 结构(如 Segment、Last Segment)时出现频率较高。常见场景包括:
- Segment 指向的段内部格式不对;
- Segment 长度非法(如不为 16 的整数倍);
- 描述符地址未 Qword 对齐(即低三位不为 000b)。
📌 可通过调试 SGL 结构或对齐方式排查。
2️⃣ 0Fh / 10h – SGL 长度非法
- 控制器对 数据 / 元数据 SGL 的长度 有限制。
- 如果长度过短或大于 Identify Controller 中允许的传输大小,将触发该错误。
- 检查 SGL Descriptor 中的 Length 字段是否与传输期望值一致。
3️⃣ 12h – Invalid Use of Controller Memory Buffer
出现此错误说明主机尝试访问控制器内部缓冲区(CMB)时违反了规定。
常见原因: - 控制器未开启 CMB 支持,但主机试图访问; - 主机对缓冲区偏移或长度设置错误。
4️⃣ 13h – PRP Offset Invalid
此错误多见于 PRP 的第二个条目中:
| 错误原因 | 说明 |
|---|---|
| 非首个 PRP 条目存在 offset | 仅首个 PRP 条目可带 offset(偏移值) |
| offset 非 dword 对齐 | 例如 offset = 3,低两位 11b,应为 00b |
5️⃣ 14h – Atomic Write Unit Exceeded
该状态码适用于对存储介质要求“原子写入”的命令集,如: - NVM - ZNS(Zone Namespace)
控制器定义的 AUL(Atomic Write Unit Limit)不能被越界。典型场景如: - 跨越两个原子单元的写操作; - 写入未对齐。
6️⃣ 15h – Operation Denied
操作被控制器拒绝,原因: - 当前命令需要权限控制; - 主机未进行认证(如未通过 TCG 安全认证协议); - 命令违反了访问控制策略。
7️⃣ 19h – Keep Alive Timer Expired
- 控制器在设定的超时时间内 未收到主机 Keep Alive 消息;
- 会导致会话断开或控制器进入非活跃状态;
- NVMe over Fabrics 中尤为常见,主机需周期性发送 Keep Alive。
🧠 总结与核心要点
| 状态码 | 代表错误 | 检查建议 |
|---|---|---|
0Dh ~ 11h |
SGL 类型/结构/长度错误 | 检查 SGL 描述符是否格式合法、对齐、长度合理 |
12h |
控制器内存缓冲区使用错误 | 检查是否启用了 CMB,访问是否合规 |
13h |
PRP 偏移对齐错误 | 仅 PRP1 可设置 offset,且必须 dword 对齐 |
14h |
原子写超限 | 保证写入命令不越界原子单元 |
15h |
权限不足 | 检查是否正确认证,或访问权限设置 |
18h |
Host ID 不一致 | 保证所有控制器使用相同格式(64-bit 或 128-bit) |
19h |
Keep Alive 超时 | 主机需定时发送 Keep Alive 命令以维持连接状态 |
如果你希望我继续:
- ✅ 继续分析
1Ah及后续的通用状态码(Figure 94 的剩余部分) - ✅ 讲解 I/O Command Specific 状态码(SCT = 1h / 2h)
- ✅ 展示使用示例:如何根据
SCT + SC分析日志中命令失败的根因
请告诉我你最关心哪一部分内容?我可以逐步带你深入理解和应用这些状态反馈机制。