NVMe 协议

NVMe是一个针对基于PCIe的固态硬盘的高性能的、可扩展的主机控制器接口。

NVMe的显著特征是提供多个队列来处理I/O命令。单个NVMe设备支持多达64K个I/O 队列,每个I/O队列可以管理多达64K个命令。

当主机发出一个I/O命令的时候,主机系统将命令放置到提交队列(SQ),然后使用门铃寄存器(DB)通知NVMe设备。

 当NVMe设备处理完I/O命令之后,设备将处理结果写入到完成队列(CQ),并引发一个中断通知主机系统。

NVMe使用MSI/MSI-X和中断聚合来提高中断处理的性能。

NVMe驱动是一个C函数库,可直接链接到应用程序从而在应用与NVMe固态硬盘之间提供直接的、零拷贝的数据传输。这是完全被动的,意味着不会开启线程,只是执行来自应用程序本身的函数调用。这套库函数直接控制NVMe设备,通过将PCI BAR寄存器直接映射到本地进程中然后执行基于内存映射的I/O(MMIO)。I/O是通过队列对(QP)进行异步提交,其一般的执行流程跟Linux的libaio相比起来,并非完全不同。

NVMe协议

NVMe概述

               NVMe是一个针对基于PCIe的固态硬盘的高性能的、可扩展的主机控制器接口。

               NVMe的显著特征是提供多个队列来处理I/O命令。单个NVMe设备支持多达64K个I/O 队列,每个I/O队列可以管理多达64K个命令。

               当主机发出一个I/O命令的时候,主机系统将命令放置到提交队列(SQ),然后使用门铃寄存器(DB)通知NVMe设备。

               当NVMe设备处理完I/O命令之后,设备将处理结果写入到完成队列(CQ),并引发一个中断通知主机系统。

               NVMe使用MSI/MSI-X和中断聚合来提高中断处理的性能。

 

NVMe驱动概述

NVMe驱动是一个C函数库,可直接链接到应用程序从而在应用与NVMe固态硬盘之间提供直接的、零拷贝的数据传输。这是完全被动的,意味着不会开启线程,只是执行来自应用程序本身的函数调用。这套库函数直接控制NVMe设备,通过将PCI BAR寄存器直接映射到本地进程中然后执行基于内存映射的I/O(MMIO)。I/O是通过队列对(QP)进行异步提交,其一般的执行流程跟Linux的libaio相比起来,并非完全不同。

 NVM Express(NVMe)是一个寄存器级接口,允许带内主机软件与NVM子系统通信。NVMe管理界面(NVMe-MI)允许管理控制器通过一个或多个外部接口与NVMe NVM子系统进行带外通信。

NVMe是一种Host与SSD之间通讯的协议

图1:NVMe管理接口协议分层

 

NVMe有三宝:Submission Queue (SQ),Completion Queue(CQ)和Doorbell Register (DB)。 SQ和CQ位于Host的内存中,DB则位于SSD的控制器内部。

SQ和CQ在Host的memory中以及DB在SSD端,上图中的NVMe Subsystem一般就是SSD。
SQ位于Host内存中,Host要发送命令时,先把准备好的命令放在SQ中,然后通知SSD来取;CQ也是位于Host内存中,一个命令执行完成,成功或失败,SSD总会往CQ中写入命令完成状态。

DB又是干什么用的呢?Host发送命令时,不是直接往SSD中发送命令的,而是把命令准备好放在自己的内存中,那怎么通知SSD来获取命令执行呢?Host就是通过写SSD端的DB寄存器来告知SSD的。

NVM Express基于配对的提交和完成队列机制

  •  命令由主机软件放入提交队列。完成被放入控制器关联的完成队列。多个提交队列可以使用相同的完成队列。提交和完成队列在内存中分配。    
  •  存在管理员提交和关联的完成队列以用于控制器管理和控制(例如,创建和删除I / O提交和完成队列,中止命令,等等)。只有属于管理员命令集的命令才可以提交给管理员提交队列。  
  •  I / O命令集与I / O队列对一起使用。该规范定义了一个I / O命令集,命名为NVM命令集。主机选择一个用于所有I / O队列的I / O命令集对。  
主机软件创建队列,最高可达控制器支持的最大值。通常的数量创建的命令队列基于系统配置和预期的工作负载。例如, 在基于四核处理器的系统上,每个核心可能有一个队列对,以避免锁定和确保数据结构在适当的处理器核心缓存中创建。

NVME命令

命令执行:
1. Host写命令到SQ
2. Host更新SQ的TailDB, 通知SSD取命令
3. SSD收到命令,于是从SQ中取出命令
4. SSD执行命令
5. 命令执行完成后,SSD往CQ中写入命令执行结果,同时修改CQ的TailDB
6. SSD发短信通知Host命令已经执行完成
7. Host收到命令后,到CQ中查看命令完成状态
8. Host处理完CQ中的命令执行结果,更新CQ中的HeadDB, 回复SSD, "命令执行结果已经处理完毕"

NVMe有两种命令,制定了Host与SSD之间通讯的命令,以及命令如何执行的。
一种叫Admin Command,用以Host管理和控制SSD;
一种就是I/O Command,用以Host和SSD之间数据的传输。

Admin 指令

Admin指令与NVM指令根据放置的的队列组(Queue Pair)来区分,Admin指令在Admin CQ与SQ里,NVM指令在I/O CQ与SQ里。

通过Dword0中的8位操作码定义不同指令,注意并不是绝对的顺序增加(eg,没有03h)。每一种指令都对应有其完成命令,通过SQID(提交队列ID)+CID(命令ID)唯一标识完成的命令。

操作码指令作用
00h删除I/O SQ,释放SQ空间
01h创建 I/O SQ,保存host分配给SQ的地址、队列优先权、队列大小
02h获取日志,返回所选日志页于缓冲区
04h删除 I/O CQ,释放CQ空间
05h创建 I/O CQ,保存host分配给CQ的地址、中断向量、队列大小等
06hIdentify返回关于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固件镜像下载,下载固件镜像

NVM指令

与Admin指令结构完全相同,也是通过Dword0中的8位操作码来定义不同指令。

操作码指令作用
00hFlush将数据(和元数据)提交到NVM中,所有命令都要执行
01hWrite将数据(和元数据)写入NVM中
02hRead读NVM中的数据(和元数据)
04hWirte Uncorrectable标记无效数据块
05hCompare比较从NVM端读出的数据和比较数据缓冲区的数据
09hDataset Management标识一定范围数据的特点,eg,频繁读、频繁写(提升性能)

寄存器

寄存器定义

NVMe寄存器主要分为两部分,一部分定义了Controller整体属性,一部分用来存放每组队列的头尾DB寄存器。

  1. CAP——控制器能力,定义了内存页大小的最大最小值、支持的I/O指令集、DB寄存器步长、等待时间界限、仲裁机制、队列是否物理上连续、队列大小;
  2. VS——版本号,定义了控制器实现NVMe协议的版本号;
  3. INTMS——中断掩码,每个bit对应一个中断向量,使用MSI-X中断时,此寄存器无效;
  4. INTMC——中断有效,每个bit对应一个中断向量,使用MSI-X中断时,此寄存器无效;
  5. CC——控制器配置,定义了I/O SQ和CQ队列元素大小、关机状态提醒、仲裁机制、内存页大小、支持的I/O指令集、使能;
  6. CSTS——控制器状态,包括关机状态、控制器致命错误、就绪状态;
  7. AQA——Admin 队列属性,包括SQ大小和CQ大小;
  8. ASQ——Admin SQ基地址;
  9. ACQ——Admin CQ基地址;
  10. 1000h之后的寄存器定义了队列的头、尾DB寄存器。

寄存器理解

  1. CAP寄存器标识的是Controller具有多少能力,而CC寄存器则是指当前Controller选择了哪些能力,可以理解为CC是CAP的一个子集;如果重启(reset)的话,可以更换CC配置;
  2. CC.EN置一,表示Controller已经可以开始处理NVM命令,从1到0表示Controller重启;
  3. CC.EN与CSTS.RDY关系密切,CSTS.RDY总是在CC.EN之后由Controller改变,其他不符合执行顺序的操作都将产生未定义的行为;
  4. Admin队列有host直接创建,AQA、ASQ、ACQ三个寄存器标识了Admin队列,而其他I/O队列则有Admin命令创建(eg,创建I/O CQ命令);
  5. Admin队列的头、尾DB寄存器标识为0,其他I/O队列标识由host按照一定规则分配;只有16bit的有效位,是因为队列深度最大64K。

性能提升

如果要完全释放NVMe SSD的IOPS性能,设计人员要先做好评估呢,因为当队列深度达到一定程度后,NVMe SSD的IOPS才会达到最佳。如下图(来自Tom'Hardware),六块NVMe SSD均在队列深度128以上才达到最佳的性能。

NVMe白皮书中对企业级SSD和消费级SSD设计时需要的队列深度的建议是:

  • 企业级SSD: 16~128 Queues;

  • 消费级SSD: 2-8 Queues.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值