协议-NVME
是什么?
- NVMe协议是PCIe应用层上的协议,所有的NVMe命令在PCIe协议来看都是Data Patload
- NVM Express(NVMe),或称非易失性内存主机控制器接口规范英语:Non Volatile Memory Host Controller Interface Specification,缩写:NVMHCIS) 是一个逻辑设备接口规范。它是与AHCI类似的、基于设备逻辑接口的总线传输协议规范(相当于通讯协议中的应用层),用于访问通过PCI Express(PCIe)总线附加的非易失性存储器介质(例如采用闪存的固态硬盘驱动器),虽然理论上不一定要求 PCIe 总线协议。
为什么?
怎么做?
-
nvme list:列出系统中所有的NVMe设备及其相关信息,如设备名称、序列号、固件版本等。
-
nvme smart-log /dev/nvmeX:显示指定NVMe设备的SMART(Self-Monitoring, Analysis, and Reporting Technology)日志信息,包括温度、错误数、寿命等。
-
nvme id-ctrl /dev/nvmeX:显示指定NVMe设备的控制器相关信息,如厂商ID、产品ID、版本等。
-
nvme id-ns /dev/nvmeXnX:显示指定NVMe设备命名空间(Namespace)的相关信息,如大小、命名空间标识符等。
-
nvme get-log /dev/nvmeX –log-page=0x02:显示指定NVMe设备的错误日志,获取设备的错误信息。
-
nvme format /dev/nvmeX –lbaf=0 -n 1:格式化指定NVMe设备,参数–lbaf指定使用的格式化类型,-n 1表示格式化的命名空间编号为1。
-
nvme smart-log-threshold /dev/nvmeX:显示指定NVMe设备上的SMART阈值信息,即设备在达到哪些阈值时会发出警告或报告。
-
nvme reset /dev/nvmeX:重置指定NVMe设备,将其恢复到初始状态。
-
nvme fw-download /dev/nvmeX -s BIOS.bin:将固件文件(如BIOS.bin)下载到指定的NVMe设备上,实现固件升级。
-
nvme fw-commit /dev/nvmeX -s BIOS.bin:确认并激活刚刚下载的固件文件,使其成为设备的当前固件。
核心本质
-
命令由host提交到内存中的SQ队列中,更新TDBxSQ后,NVMe控制器通过DMA的方式将SQ中的命令取到控制器缓冲区,执行命令;执行完成后,根据执行状态,组装完成命令,仍然通过DMA的方式将完成命令写入内存CQ的队列中;NVMe控制器通过MSI-X中断方式通知host已完成命令;最后,host处理CQ命令,更新控制器中HDBxCQ,标识着命令真正完成。
-
命令 是什么?有几种?分别用在哪里?存储在哪里? 执行在哪里?多条命令同时产生时候如何仲裁?
-
命令 中带入的数据源在哪里?要写入NVME控制器的数据存储在哪里?
NVME 框架
Host Controller
- 这里主机称为Host,而NVMe设备称为Controller(控制器)。主机和控制器之间通过共享内存的队列实现交互
NVME 队列
NVMe的队列分为2种
-
管理队列 (Admin Queue),用于管理的队列,仅有一个
-
命令队列(Command Queue/IO Queue),最多可以有65535个
-
命令队列的数量和模式都是通过管理队列来设置的。
-
队列实际是队列对Queue Pair
- 提交队列SQ(Submission Queue)
- 完成队列CQ(Completion Queue)
-
提交队列SQ用于主机端向NVMe设备发送NVMe命令
-
完成队列则用于NVMe设备向主机反馈命令执行情况
NVME 配置空间
- PCIe能力寄存器空间(0x40 ~ 0xff)
- 配置了PCI Capbilities,包括电源管理、中断管理(MSI、MSI-X)、PCIe Capbilities
- PCI Express Extended Capabilities扩展能力寄存器空间(0x100~0xfff)
- 配置有关错误恢复等高级功能
PCI Express Type 0 Header
NVMe协议对部分bar寄存器有特殊的规定
- NVMe SSD拥有pci标准的配置空间头,但NVMe协议对部分bar寄存器有特殊的规定
- (bar0与bar1组成64bit bar)
- PCIe 总线中有两种 MMIO :P-MMIO 和 NP-MMIO
- NVMe协议要求与host交互相关的寄存器放在PCIe bar0空间
64-bit Memory Address Space Request
![![[Pasted image 20250216030054.png]](https://i-blog.csdnimg.cn/direct/3bdbdd72333d4276b0a1c8de514df0e0.png)
- CAP——控制器能力,定义了内存页大小的最大最小值、支持的I/O指令集、DB寄存器步长、等待时间界限、仲裁机制、队列是否物理上连续、队列大小;
- VS——版本号,定义了控制器实现NVMe协议的版本号;
- INTMS——中断掩码,每个bit对应一个中断向量,使用MSI-X中断时,此寄存器无效;
- INTMC——中断有效,每个bit对应一个中断向量,使用MSI-X中断时,此寄存器无效;
- CC——控制器配置,定义了I/O SQ和CQ队列元素大小、关机状态提醒、仲裁机制、内存页大小、支持的I/O指令集、使能;
- CSTS——控制器状态,包括关机状态、控制器致命错误、就绪状态;
- AQA——Admin 队列属性,包括SQ大小和CQ大小;
- ASQ——Admin SQ基地址;
- ACQ——Admin CQ基地址;
- 1000h之后的寄存器定义了队列的头、尾DB寄存器。
NVME 命令
- 命令分为Admin指令与NVM指令(I/O指令)。
- Admin指令只能提交到Admin Controller中,主要负责管理NVMe控制器,也包含对NVM的一些控制指令。
- NVM 指令只能提交到I/O Controller中,主要负责完成数据的传输
通用命令格式
- 命令均为64字节
- 完成命令
Command Identifier
- 该字段占用4个字节的空间
OPC: 全称为Opcode,也就是被执行命令的操作码。
- 具体来说就是想让控制器干什么,比如读数据、写数据或者刷写等
FUSE: 全称为Fused Operation
- 用于标识该命令是普通命令还是复合命令
PSDT: 全称为PRP or SGL for Data Transfer
- 这个用于说明存储数据的内存的组织形式
Admin指令NVM指令
- Admin指令在Admin CQ与SQ里,NVM指令在I/O CQ与SQ里
Admin 指令
- 通过Dword0中的8位操作码OPC定义不同指令
- 每一种指令都对应有其完成命令,通过SQID(提交队列ID)+CID(命令ID)唯一标识完成的命令。
NVM指令
- NVMe控制器读写的最小单元是LB
- NVM指令与Admin指令结构完全相同,也是通过Dword0中的8位操作码OPC来定义不同指令
仲裁机制
RR仲裁,Admin SQ与I/O SQ优先级相同,控制器每次可以选择一个队列中的多个命令
带有优先权的RR,队列有4种优先级,根据优先级调度
其他仲裁方式
- 自定义仲裁
PRP与SGL
- 对PRP来说,它只能映射到一个个物理页
- 对SGL来说,它可以映射到任意大小的连续物理空间,具有更大的灵活性,也能够描述更大的数据空间
PRP Entry PRP List
- NVMe把Host的内存分为页的集合,页的大小在CC寄存器中配置
- PRP1直接指向内存页,PRP Entry是一个指向物理内存页的指针 PRPEntry是固定大小的(8B)
- PRP2指向PRP List存在的地址 RP List为PRP列表指针
SGL
- SGL由若干个SGL段组成,SGL段又由若干个SGL描述符组成,所以SGL描述符是SGL数据结构的基本单位
SQ,CQ,DB
- Host往SQ中写入命令, SSD往CQ中写入命令完成结果
- 每个SQ或者CQ,都有两个对应的DB: Head DB和Tail DB。
- DB是在SSD端的寄存器,记录SQ和CQ的头和尾巴的位置
队列的生产/消费模型
-
生产者往队列的Tail写入东西,消费者往队列的Head取出东西。
-
SQ
- 生产者是Host,因为它往SQ的Tail位置写入命令
- 消费者是SSD,因为它往SQ的Head取出指令执行
-
CQ
- 生产者是SSD,因为它往CQ的Tail写入命令完成信息
- 消费者则是Host,它从CQ的Head取出命令完成信息
-
Host往SQ1中写入了三个命令,SQ1的Tail则变成3。Host在往SQ1写入三个命令后,更新SSD Controller端的SQ1 Tail DB寄存器,值为3。
- SSD Controller收到通知,派人去SQ1把3个命令都取回来执行。SSD把SQ1的三个命令都消费了,SQ1的Head从而也调整为3,SSD Controller会把这个Head值写入到本地的SQ1 Head DB寄存器
- SSD执行完了两个命令,于是往CQ1中写入两个命令完成信息,同时更新CQ1对应的Tail DB 寄存器,值为2。SSD并且发消息给Host:有命令完成
- Host收到SSD的短信通知,于是从CQ1中取出那两条完成信息处理。处理完毕,Host往CQ1 Head DB寄存器中写入CQ1的head,值为2
文档链接说明
-
参考文档
【NVME】NVME协议总结_协议nv-CSDN博客 -
参考文档
NVME(学习笔记四)—概念解读 - 咸鱼书生 - 博客园 -
参考文档
NVMe协议详解(一)_caodongwang-GitCode 开源社区 -
参考文档
PCIe扫盲(三)_pcie fom-CSDN博客 -
参考文档
可乐学习NVMe之二:三只熊SQ/CQ/DB_更新cq tail db的意义-CSDN博客 -
参考文档
linuxnvme命令 • Worktile社区