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 命令逐个创建这些队列。

相关推荐
小糖学代码2 小时前
LLM系列:2.pytorch入门:9.神经网络的学习
人工智能·python·深度学习·神经网络·学习·机器学习
小陈phd2 小时前
多模态大模型学习笔记(三十八)——传统OCR技术机制:从DBNet到CRNN:吃透传统OCR两阶段范式的底层逻辑
笔记·学习·ocr
迷途之人不知返2 小时前
List的模拟实现
数据结构·c++·学习·list
HalvmånEver2 小时前
MySQL的内置函数
linux·数据库·学习·mysql
兜兜工作室2 小时前
兜兜消消单词|04.29 每日单词|glove
学习
zhangrelay2 小时前
三分钟云课实践速通--工程制图基础-3D--FreeCAD
笔记·学习·3d
勤劳的进取家3 小时前
传输层基础
运维·开发语言·学习·php
Gary Studio3 小时前
Frameworks学习预览
学习
for_ever_love__3 小时前
UI学习:单例传值
学习·ui·ios·objective-c