初探 NVMe

NVMe

【参考资料】1、NVMe扫盲;2、NVME协议解读(一);3、NVMe协议SSD 控制器端实现浅析(一);4、NVMe解读

目录

一、概述

1.1 什么是NVMe

  • Non-Volatile Memory Express(非易失性存储器标准)
  • NVMe是面向PCIe SSD制定的标准接口协议,用于访问通过PCIe总线附加的SSD(可适用于各种支持PCIe总线的物理插槽上)
  • 定义了NVMe协议的使用范围、指令集、寄存器配置规范等
  • 具有良好的可拓展性、低延迟,低能耗,高性能等优点

PCle:Peripheral Component Interconnect Express,周边设备高速连接标准。是一种端对端的互连协议,提供了高速传输带宽的解决方案。其协议内容主要是物理层和数据链路层的。

另一个常用的相关协议是AHCI,AHCI主要是针对高延时的SATA接口的机械硬盘而设计的

1.2 高性能&低延迟

面向PCIe SSD产品的NVMe标准能有效降低控制器和软件接口部分的延迟,是因为:

  • 能让SSD走PCI-E通道直连CPU,有效降低了数据延迟
  • NVMe执行命令时则不需要读取寄存器

NVMe还能大大提高SSD的IOPS性能。理论上,IOPS=队列深度/ IO延迟,所以增加队列深度,就可以有效提升SSD的IOPS。

  • 传统的ACHI标准下队列深度最多能达到32
  • 在NVMe标准下,这一数值可以达到64000

此外NVMe还加入了自动功耗状态切换、动态能耗管理、免驱等功能,驱动适应性广,低功耗

1.3 名词&术语

1、Namespace

  • Namespace是一定数量逻辑块(LB)的集合
  • 其属性在Identify Controller中的数据结构中定义

逻辑块:NVMe定义的最小的读写单元,2KB、4KB……,用LBA来标识块地址
LBA range:表示物理上连续的逻辑块集合

2、Fused Operations

  • 聚合操作。只能聚合两条命令,并且这两条命令在队列中应保持相邻顺序,还需要保证聚合操作的两条命令读写的原子性
  • 只有NVM指令才有聚合操作

3、指令执行顺序

  • 除了聚合操作,每一条SQ中的命令都是独立的

4、写单元的原子性

  • 控制器需要支持写单元的原子性
  • 但有时也能通过host配置Write Atomicity feature,减小原子性单元的大小,提高性能

5、元数据

  • 数据的额外信息。可选的方式

6、仲裁机制

  • 用来选择执行的命令的SQ的机制,三种仲裁方式:
    • RR(每个队列优先级相同,轮转调度)
    • 带权重的RR(队列有4种优先级,根据优先级调度)
    • 自定义实现

7、Queue Pair

  • 由SQ(提交队列)与CQ(完成队列)组成
  • host通过SQ提交命令,NVMe Controller通过CQ提交完成命令

8、NVM 子系统

  • 控制器
  • NVM存储介质
  • 控制器与NVM之间的接口

二、NVMe命令

2.1 命令通用格式

Host提交的命令均为16字节,具有相同的格式,某些字段根据命令的不同有不同的定义

字段 定义
Dword0 CID、传输方式、聚合操作、操作码
1 NID(Namespace ID)
2 保留
3 保留
4、5 元数据指针(MPTR)
6-9 数据指针(DPTR)
10-15 根据命令指定

CQ命令均为4字节,也具有相同的格式,某些字段根据命令的不同有不同的定义

字段 定义
Dword0 根据命令指定
1 保留
2 SQID、SQ头指针
3 状态域、P位、CID

2.2 两类命令

主机提交的命令分为两类

2.2.1 Admin Command

  • Admin指令只能提交到Admin Controller中(Admin CQ/SQ)
  • 主要负责管理NVMe控制器,也包含对NVM的一些控制指令
  • Admin Command通过Dword0中的8位操作码定义不同指令,每一种指令都对应有其完成命令
  • 通过SQID(提交队列ID)+CID(命令ID)唯一标识完成的命令

字段

appmask apptag reftag dsmgmt slba addr metadata rsvd nblocks control Flags Opcode

操作码

操作码 指令 作用
00h 删除I/O SQ 释放SQ空间
01h 创建 I/O SQ 保存host分配给SQ的地址、队列优先权、队列大小
02h 获取日志 返回所选日志页于缓冲区
04h 删除 I/O CQ 释放CQ空间
05h 创建 I/O CQ 保存host分配给CQ的地址、中断向量、队列大小等
06h Identify 返回关于controller与namespace能力和状态的数据结构(2k字节)
08h 撤销 用来撤销之前完成的指令,best-effort
09h 设置features 根据FID设置相应的features
0Ah 获取 features 根据FID返回队列数量、仲裁信息等
0Ch 异步事件请求 Controller向host报告运行信息(error or health)
10h 固件激活 验证下载的镜像,提交到Firmware Slot(1-7)中
11h 固件镜像下载 下载固件镜像

2.2.2 IO Command(NVM Command)

  • NVM 指令只能提交到I/O Controller中(IO CQ/SQ)
  • 主要负责完成数据的传输
  • IO Command通过Dword0中的8位操作码定义不同指令,每一种指令都对应有其完成命令
  • 通过SQID(提交队列ID)+CID(命令ID)唯一标识完成的命令

字段

rsvd11 numd offset lid prp2 prp1 rsvd1 command_id flags Opcode
操作码 指令 作用
00h Flush 将数据(和元数据)提交到NVM中,所有命令都要执行
01h Write 将数据(和元数据)写入NVM中
02h Read 读NVM中的数据(和元数据)
04h Wirte Uncorrectable 标记无效数据块
05h Compare 比较从NVM端读出的数据和比较数据缓冲区的数据
09h Dataset Management 标识一定范围数据的特点,eg,频繁读、频繁写(提升性能)

2.3 SQ、CQ、DB

NVMe的三种队列命令

  • Submission Queue(SQ)提交队列(在内存中)
    • Host要发送命令时,先把准备好的命令放在SQ中(Host并不直接往SSD中发送命令,而是把命令准备好放在自己的内存中,写DB通知SSD来取)
  • Completion Queue(CQ)完成队列(在内存中)
    • 一个命令执行完成,成功或失败,SSD总会往CQ中写入命令完成状态、
    • SSD写完后,Host会处理CQ,查看指令完成状态
  • Doorbell Register (DB)门铃注册(在SSD控制器内部)
    • Host通过写DB告诉SSD去SQ读指令
    • Host通过写DB回复SSD命令已经处理完毕,可以前来检阅

在这里插入图片描述

2.4 命令的执行过程

命令由host提交到内存中的SQ队列中,更新TDBxSQ后,NVMe控制器通过DMA的方式将SQ中的命令(怎么取,如何取,取多少,因设计而异)取到控制器缓冲区,执行命令;执行完成后,根据执行状态,组装完成命令,仍然通过DMA的方式将完成命令写入内存CQ的队列中;NVMe控制器通过MSI-X中断方式通知host已完成命令;最后,host处理CQ命令,更新控制器中HDBxCQ,标识着命令真正完成

通过三种队列命令配合,完成处理流程

  • ① Host写命令到SQ;
  • ② Host写DB(通知SSD取指令);
  • ③ SSD收到通知,于是从SQ中取指令;
  • ④ SSD执行指令;
  • ⑤ 指令执行完成,SSD往CQ中写指令执行结果;
  • ⑥ SSD通过MSI-X中断方式通知host已完成命令;
  • ⑦ Host处理CQ,查看指令完成状态;
  • ⑧ Host通过DB回复SSD,命令真正完成

在这里插入图片描述

MSI-X中断:NVMe协议中支持的中断方式有4种,pin-based、Single MSI、Multi-message MSI和MSI-X,协议推荐采用MSI-X中断方式,能够支持更多的中断向量(2K)。

MSI-X允许每一个CQ发送自己的中断信息(相比于发一条中断信息提醒全部CQ队列有很大的优势)。在产生MSI-X中断信息前,需要检查该中断在相应寄存器种不被屏蔽

三、多命令队列与仲裁机制

3.1 NVMe多命令队列

  • NVMe采用了多命令队列,每个命令可变数据长度
  • NVMe协议支持命令间的乱序执行,也支持命令内数据块的乱序传输,同时支持命令队列间的可变权重处理
  • QID来标识唯一ID,16bit,由host分配
  • host可以修改队列优先级(如果支持的话),共四级:U、H、M、L

NVMe与SATA协议对比

在这里插入图片描述

3.2 多命令队列的仲裁机制

3.2.1 RR

Admin SQ与I/O SQ优先级相同,控制器每次可以选择一个队列中的多个命令,轮转调度

在这里插入图片描述

3.2.2 带有优先权的RR

有3个严格的优先权,Priority1 > Priority2 > Priority3,在这三个优先级队列中,高优先级的队列中如果有命令,则优先执行(非抢占式)

  • Priority1:Admin
  • Priority2:Urgent
  • Priority3:IO SQ

在这里插入图片描述

四、内存寻址

Host告诉Controller数据源在内存的什么位置,或者从闪存上读取的数据应该放到内存的什么位置,需要内存寻址

  • NVMe把Host的内存分为页的集合,页的大小在CC寄存器中配置
  • NVMe采取PRP和SGL两种寻址方式
    • Admin命令的数据地址只能采取PRP的方式
    • I/O命令的数据地址既可以采取PRP的方式,又可以采取SGL的方式
    • Host在命令中会告诉Controller采用何种方式。具体来说,如果命令当中DW0[15:14]是0,就是PRP的方式,否则就是SGL的方式

阅读材料:可乐学习NVMe之三:解读PRP/SGL

4.1 PRP方法

PRP Entry是一个64位(63 ~ 0编号)的内存物理地址指针,结构如下:

在这里插入图片描述

  • 最后两位为0,指四字节对齐
  • Offset(n:2)位表示页内内偏移

PRP寻址有两种方式

  • 直接用PRP指针寻址:直接由PRP指向内存页
  • 通过PRP List寻址:PRP指向PRP List的地址,PRP List存有真正的数据地址

在这里插入图片描述

4.2 SGL方法

SGL是另外一种索引内存的数据结构。SSGL字段由若干个SGL描述符组成,所以SGL描述符是SGL数据结构的基本单位

目前定义的SGL描述符有6种,在一个SGL字段中并不需要同时使用

  • SGL 数据描述符,用来索引数据块地址,host内存;
  • SGL 垃圾数据描述符,用来索引无用数据;
  • SGL 段描述符,用来索引下一个SGL段;
  • SGL 最后一个段描述符,用来索引最后一个SGL段;
  • keyed SGL 数据描述符;
  • Transport SGL 数据描述符;

在这里插入图片描述

  • 在上面SGL例子中,共有3个SGL段,用到了4种SGL描述符
  • Host需要往SSD中读取13KB(Data Block + Bit Bucket)的数据,其中真正只需要11KB数据(Data Block),这11KB的数据需要放到3个大小不同的内存中,分别是:A(3KB),B(4KB)和 C(4KB)

4.3 PRP 与 SGL 的比较

无论是PRP还是SGL,本质都是描述内存中的一段数据空间。

Host在命令中设置好PRP或者SGL,告诉Controller数据源在内存的什么位置,或者从闪存上读取的数据应该放到内存的什么位置。

SGL和PRP本质的区别在于:

  • 一段数据空间,对PRP来说,它只能映射到一个个物理页
  • 对SGL来说,它可以映射到任意大小的连续物理空间,具有更大的灵活性,也能够描述更大的数据空间

五、NVMe SSD Controller 物理架构(了解)

5.1 概念模型

整体来看,NVMe SSD可以分为三部分

  • host端的驱动
  • PCIe+NVMe实现的控制器
  • FTL+NAND Flash的存储介质

在这里插入图片描述

5.2 子模块

在这里插入图片描述

1、主机接口控制器

  • 主机接口负责进行主机与固态盘之间的通信和数据传输,接受和解析I/O请求,并维护一条或者多条请求队列
  • 主机接口控制器是对外连接的模块,它的两大工作 —— 接受和解析IO、维护请求队列是NVMe的实现难点,也是最最主要的设计点,我围绕NVMe的设计实现也基本是针对主机接口控制器而言的

2、多核处理器

  • 固态盘的管理需要处理诸多复杂的任务,比如主机接口协议、调度算法、FTL算法和缓存算法等,因此需要强有力的多核处理器来提高这些任务的处理效率,从而降低软件延时

3、缓存芯片

  • 固态盘内置有缓存芯片,一般是DRAM,用于缓存用户数据和软件算法的元数据
  • 缓存既能加快数据访问的速度,提高固态盘的性能,也能够减少对闪存的写入,延长固态盘的寿命
  • 缓存用户数据的部分称之为数据缓存,缓存地址映射表的部分称之为映射缓存
  • 为了防止突然掉电导致RAM中的数据丢失,固态盘一般会内置备用电容,并采用适当的数据保护技术,用于保证在突然掉电的情况下,将RAM中关键的脏数据刷回闪存

4、中央控制器

  • 中央控制器是整个固态盘控制器的核心,负责配置固态盘的工作模式,管理各个模块之间的通信和数据流。
  • 中央控制器内置有小容量的高速SRAM缓存,用于临时缓存数据

5、纠错码引擎

  • 纠错码引擎对要写入闪存的数据进行编码,所增加的纠错码冗余会被写到闪存页的额外存储区中
  • 当需要从闪存中读取数据时,纠错码引擎会对数据和它的纠错码冗余进行解码,如果发生的比特错误数在纠错能力范围内,数据中的错误就会被纠正,从而得到正确的数据;否则,如果没有其它的数据恢复手段,存储的数据就会丢失

6、通道控制器

  • 为了提高性能,固态盘将数量众多的闪存芯片安置在多个通道上,每个通道上的多个芯片共享一条I/O总线。
  • 每个通道包含一个独立的通道控制器,主要负责与中央控制器和本通道上的闪存芯片进行通信,并维护多条操作闪存的命令队列(比如为每个芯片维护一条单独的队列,外加一条总的高优先级队列),将命令发往目标芯片进行执行

7、闪存芯片

  • 闪存芯片上既存储用户数据,也存储需要持久化的元数据,比如地址映射表
  • 固态盘提供的物理存储容量会比用户可见的容量要多(一般多7% ~ 28%),多余部分称之为过量供应(Over-provisioning, OP)空间,主要用于提高软件算法(比如垃圾回收操作)的效率和补偿因闪存坏块产生的容量损失
  • 有的固态盘还会在闪存芯片之间组建RAID5,以加强存储的可靠性

RAID5:将校验数据条带化存储在多个盘中

8、DMA引擎

  • DMA引擎负责控制在两个RAM之间进行快速的数据传输,比如在中央控制器的SRAM和缓存芯片之间

5.3 NVMe主机接口控制器

NMVe主机接口控制器的逻辑将是我主要的设计内容,一般来说NMVe主机接口控制器包括以下几个部分:

  • Admin队列处理模块
  • IO命令队列处理模块
  • IO Completion队列处理模块
  • IO写数据处理模块
  • IO读数据处理模块
  • 中断处理模块

在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340