NVMe 2.3协议学习

文章目录

  • [1 Controller Properties](#1 Controller Properties)
  • [1.1 如何访问](#1.1 如何访问)
  • [1.2 Controller 初始化流程](#1.2 Controller 初始化流程)
  • [1.3 CAP - Controller Capabilities (Offset 00h, 64-bit)](#1.3 CAP - Controller Capabilities (Offset 00h, 64-bit))
  • [X 面试场景问题](#X 面试场景问题)
  • [1 为什么Properties Host必须通过BAR访问,不能通过DMA?](#1 为什么Properties Host必须通过BAR访问,不能通过DMA?)
  • [2 如果Host按dword访问qword的CAP会怎样?](#2 如果Host按dword访问qword的CAP会怎样?)
  • [3 CC.EN从1→0关闭Controller时,CSTS.RDY多久变0?](#3 CC.EN从1→0关闭Controller时,CSTS.RDY多久变0?)
  • [4 IO SQ/CQ的创建细节?](#4 IO SQ/CQ的创建细节?)

1 Controller Properties

NVMe 协议章节 3.1.4 Controller Properties

Controller Properties(如CAP、CC、CSTS) 这些关键的寄存器,和SSD Controller初始化流程相关。

画出初始化状态机流程图?

FTL关注点:

Controller Properties(如CAP、CC、CSTS)通常通过PCIe BAR空间访问

必须按指定宽度(dword/qword)访问,跨Property访问不支持

这意味着:如果你要读取64-bit的CAP(Controller Capabilities),必须一次性读qword,不能分两次读dword

1.1 如何访问

层级 存储位置 说明
PCIe BAR空间 SSD控制器内部的寄存器(Registers) 物理上在SSD主控芯片内
Host视角 映射到Host内存地址空间的MMIO区域 Host通过内存读写访问

Host CPU → PCIe TLP (Memory Read/Write) → SSD Controller BAR → 内部寄存器

关键:Host看到的"内存地址" = PCIe配置空间分配的BAR基地址 + Property Offset

1.2 Controller 初始化流程

Host要把SSD(Controller) 初始化,好让Controller能够开始接收命令

完整的Host初始化Controller的流程状态机如下:

c 复制代码
┌─────────────────┐
│   1. 读取CAP     │  ← 确认Controller能力
│   (Offset 00h)  │
└────────┬────────┘
         ▼
┌─────────────────┐
│   2. 配置CC     │  ← 设置Command Set, Page Size
│   (Offset 14h)  │     但不Enable (EN=0)
└────────┬────────┘
         ▼
┌─────────────────┐
│   3. 配置AQA    │  ← Admin Queue深度
│   (Offset 24h)  │
└────────┬────────┘
         ▼
┌─────────────────┐
│   4. 配置ASQ    │  ← Admin SQ基址 (64-bit)
│   (Offset 28h)  │
└────────┬────────┘
         ▼
┌─────────────────┐
│   5. 配置ACQ    │  ← Admin CQ基址 (64-bit)
│   (Offset 30h)  │
└────────┬────────┘
         ▼
┌─────────────────┐
│   6. 写CC.EN=1  │  ← Enable Controller
│   (Offset 14h)  │
└────────┬────────┘
         ▼
┌─────────────────┐
│   7. 轮询CSTS   │  ← Host轮询寄存器,等待RDY=1
│   (Offset 1Ch)  │     检查CFS=0
└────────┬────────┘
         ▼
┌─────────────────┐
│   8. Identify   │  ← 发送Admin命令
│   Controller    │     获取设备信息
└────────┬────────┘
         ▼
┌─────────────────┐
│   9. Create I/O │  ← Host发送 创建I/O Queue 请求
│   Queues        │
└────────┬────────┘
         ▼
┌─────────────────┐
│   10. 开始I/O   │  ← 发送Read/Write命令
└─────────────────┘

FTL需关注的Properties如下

关注点 为什么重要
CAP.MPS 决定PRP List结构,影响数据传输效率
CAP.MQES 决定Queue深度,影响并发I/O性能
CC.MPS配置 必须与Host内存页大小匹配
CSTS.RDY轮询 超时处理,防止初始化死锁
Doorbell机制 Tail Doorbell通知有新命令,Head Doorbell通知已取走完成

1.3 CAP - Controller Capabilities (Offset 00h, 64-bit)

CAP是只读寄存器

字段 作用 FTL关注点
MQES 15:00 Max Queue Entries Supported 决定SQ/CQ最大深度(0-based)
CQR 16 Contiguous Queues Required 1=必须用物理连续队列
AMS 18:17 Arbitration Mechanism Supported 0=Round Robin, 1=Weighted RR
TO 23:20 Timeout 500ms × (TO+1),初始化超时计算
DSTRD 31:24 Doorbell Stride 每个Doorbell寄存器间距 = 4 << DSTRD
NSSRS 33 NVM Subsystem Reset Supported 是否支持NSSR
CSS 44:37 Command Sets Supported 支持哪些I/O Command Set
MPSMAX/MPSMIN 52:32 Memory Page Size Max/Min 决定PRP/SGL页大小

X 面试场景问题

1 为什么Properties Host必须通过BAR访问,不能通过DMA?

Properties是控制器状态/配置寄存器,需要CPU直接访问(低延迟)。DMA用于数据传输(高吞吐)。BAR映射到MMIO空间,CPU可用普通load/store指令访问。

2 如果Host按dword访问qword的CAP会怎样?

未定义行为。Spec要求必须按定义宽度访问。实际可能导致读取错误值或触发错误。

3 CC.EN从1→0关闭Controller时,CSTS.RDY多久变0?

取决于CAP.TO定义的Timeout。Host必须轮询等待,或超时后强制Reset。

疑问,CC.EN从1→0 该行为意味着什么?Controller内部做什么后会把RDY置为0?

4 IO SQ/CQ的创建细节?

在Controller 准备就绪后,Host会给Controller发消息,来创建 IO SQ/CQ。

创建SQ/CQ的 队列数量 和 深度,如何确定的?

Host会通过Identify命令,来获取Controller 支持的 队列数量上限。

Host会通过Set Features的Number Of Queues 属性,来向Controller传递想要的 IO SQ/CQ 数量。

Number Of Queues 是 SSD的一个Feature

NSQ (Number of Submission Queues):主机希望创建的I/O提交队列数量(0值表示1个队列)。

NCQ (Number of Completion Queues):主机希望创建的I/O完成队列数量(0值表示1个队列)。

控制器收到请求后,会评估自己的能力。它不一定能满足Host的所有请求,可能会返回一个它实际能支持的、接近请求值的数量。这个协商结果会通过Set Features命令的完成队列条目返回给Host。之后,Host会读出该结果作为实际分配数量的参考。

获得最终数量后,Host便开始按这个参考结果进行实际的队列创建操作,主要有两种Admin命令:

Create I/O Completion Queue命令:用于逐个创建I/O CQ。命令参数包括指定CQ ID (qid) 和大小 (qsize) 等。

Create I/O Submission Queue命令:用于逐个创建I/O SQ。创建时需指定归属的CQ ID,实现多SQ对一CQ的关联。

典型协商流程

初始匹配阶段:主机首次写入 Set Features (FID=07h),假设要申请 NCQ=63 和

NSQ=63。若控制器最大支持32个I/O队列(0-based返回31),协商后主机会读取 Result 值: Result = (31

<< 16) | 31 (即0x001F001F)。

逐个创建阶段:最终按 31 的返回值,通过 Create I/O Completion Queue 和 Create I/O

Submission Queue 命令逐个创建这些队列。

相关推荐
柿柿快乐12 小时前
Redis 入门第一课:全局命令、内部编码与单线程模型
redis·学习·缓存·基础教学
Lucky_ldy13 小时前
C语言学习:文件操作
学习
AI算法沐枫13 小时前
大模型 | 大模型之机器学习基本理论
人工智能·python·神经网络·学习·算法·机器学习·计算机视觉
小新同学^O^14 小时前
简单学习 --> LangChain
python·学习·langchain
吃好睡好便好15 小时前
在Matlab中绘制阶梯图
开发语言·人工智能·学习·算法·机器学习·matlab
Restart-AHTCM15 小时前
LangChain学习之提示词模板 (Prompts) - 练习(2/8)
学习·langchain
YangYang9YangYan15 小时前
2026产品专员学习数据分析的价值与路径
学习·数据挖掘·数据分析
淘矿人15 小时前
【AI大模型】AI 大模型推理平台完整测评:8 家主流聚合服务对比分析
人工智能·sql·gpt·学习·github·php
我想我不够好。16 小时前
2026.5.20 消防监控学习 1.5hour
学习
爱喝水的鱼丶16 小时前
SAP-ABAP:数据类型与数据对象(8篇) 第七篇:进阶优化篇——基于类型与对象特征的性能优化技巧
运维·数据库·学习·性能优化·sap·abap·开发交流