【SSD】NVMe协议

1 AHCI到NVMe

NVMe即Non-Volatile Memory Express,是非易失性存储器标准,是跑在PCIe接口上的协议标准。NVMe在设计之初就充分利用了PCIe SSD的低延时、高并行性,还有当代处理器、平台与应用的高并行性。NVMe为SSD而生,但不局限于以闪存为媒介的SSD,它同样可以应用在高性能和低延迟的3D XPoint这类新型的介质上。

1.低延时(Latency)造成硬盘存储延时的三大因素为存储介质、控制器以及软件接口标准。❑存储介质层面,闪存(Flash)比传统机械硬盘速度快太多了。❑控制器方面,从SATA SSD发展成PCIe SSD,原生PCIe主控与CPU直 接相连,而不像传统方式,要通过南桥控制器中转再连接CPU,因此基于PCIe的SSD延时更低。❑软件接口方面,NVMe缩短了CPU到SSD的指令路径,比如NVMe减少了对寄存器的访问次数,使用了MSI-X中断管理,并行与多线程优化,NVMe减少了各个CPU核之间的锁同步操作等。
在这里插入图片描述
2.高性能(Throughput&IOPS)理论上,IOPS=队列深度/输入输出延时,故IOPS的性能与队列深度有较大的关系(但IOPS并不与队列深度成正比,因为实际应用中,随着队列深度的增加,I/O延时也会提高)。市面上性能不错的SATA接口SSD,在队列深度上都可以达到32,然而这也是AHCI所能做到的极限。但目前高端的企业级PCIe SSD的队列深度可能要达到128,甚至是256才能够发挥出最高的IOPS性能。而在NVMe标准下,最大的队列深度可达64K。此外,NVMe的队列数量也从AHCI的1,提高到了64K。

在这里插入图片描述

2 NVMe综述

NVMe是为SSD而生的。NVMe出现之前,SSD绝大多数用的是AHCI加SATA的组合,后者其实是为传统HDD服务的。

NVMe制定了主机与SSD之间通信的命令,以及命令的执行方式。NVMe有两种命令,一种叫Admin命令,用于帮主机管理和控制SSD;另外一种就是I/O命令,用于在主机和SSD之间传输数据。
在这里插入图片描述
SSD作为一个PCIe Endpoint(PCIe终端,简称EP)通过PCIe连着RC,然后RC连接着CPU和内存。
在这里插入图片描述
SQ位于主机内存中,主机要发送命令时,先把准备好的命令放在SQ中,然后通知SSD来取;CQ也是位于主机内存中,一个命令执行完成,无论是成功还是失败,SSD总会往CQ中写入命令完成状态。DB又是干什么用的呢?主机发送命令时,不是直接往SSD中发送命令,而是把命令准备好放在自己的内存中,那怎么通知SSD来获取命令执行呢?主机就是通过写SSD端的DB来告知SSD的。

SQ、CQ和DB

I/O SQ/CQ不是一生下来就有的,它们是通过Admin命令创建的。Admin SQ/CQ和I/O SQ/CQ各司其职。每个SQ放入的是命令条目,无论是Admin还是I/O命令,每个命令的条目大小都是64B;每个CQ放入的是命令完成状态信息条目,每个条目大小是16B。
在这里插入图片描述

❑SQ用于主机发送命令,CQ用于SSD回复命令完成状态;❑SQ/CQ可以在主机的内存中,也可以在SSD中,但一般在主机内存中;
❑系统中只能有一对Admin SQ/CQ,但可以有很多对I/O SQ/CQ;❑I/O SQ与CQ可以是一对一的关系,也可以是多对一的关系;
❑可以赋予I/O SQ是不同优先级的;
❑I/O SQ/CQ深度可达64K,Admin SQ/CQ深度可达4K;
❑I/O SQ/CQ的广度和深度都可以灵活配置;
❑每条命令是64B,每条命令完成状态是16B。

DB就是用来记录一个SQ或者CQ的头和尾。每个SQ或者CQ都有两个对应的DB————Head DB(头部DB)和TailDB(尾部DB)。DB是SSD端的寄存器,记录SQ和CQ的头和尾巴的位置。
在这里插入图片描述
❑DB在SSD控制器端是寄存器;
❑DB记录着SQ和CQ队列的头部和尾部;
❑每个SQ或者CQ有两个DB:Head DB和Tail DB;
❑主机只能写DB,不能读DB;
❑主机通过SSD往CQ中写入的命令完成状态获取队列头部或者尾部。

4. PRP和SGL寻址

主机如果想往SSD上写入用户数据,需要告诉SSD写入什么数据,写入多少数据,以及数据源在内存中的什么位置,这些信息包含在主机向SSD发送的写命令中。每笔用户数据对应着一个叫作LBA(LogicalBlock Address,逻辑块地址)的东西,写命令通过指定LBA来告诉SSD写入的是什么数据。对NVMe/PCIe来说,SSD收到写命令后,通过PCIe去主机的内存中数据所在位置读取数据,然后把这些数据写入闪存,同时生成LBA与闪存位置的映射关系。

主机如果想读取SSD上的用户数据,同样需要告诉SSD需要什么数据,需要多少数据,以及数据最后需要放到主机内存的哪个位置上,这些信 息包含在主机向SSD发送的读命令中。SSD根据LBA查找映射表(写入时生成的),找到对应闪存物理位置,然后读取闪存获得数据。数据从闪存读上来以后,对NVMe/PCIe来说,SSD会通过PCIe把数据写入主机指定的内存。这样就完成了主机对SSD的读访问。

主机不亲自传输数据,那总该告诉我SSD去内存中什么地方取用户数据,或者要把数据写入到内存中的什么位置。主机也有两种方式来告诉SSD数据所在的内存位置,一是PRP(Physical Region Page,物理区域页),二是SGL(Scatter/Gather List,分散/聚集列表)。

PRP
PRP条目本质就是一个64位内存物理地址,只不过这个物理地址被分成两部分——页起始地址和页内偏移。最后两位是0,说明PRP表示的物理地址只能4字节对齐访问。页内偏移可以是0,也可以是个非零的值。
在这里插入图片描述
一个PRP条目描述的是一个物理页空间。如果需要描述若干个物理页,那就需要若干个PRP条目。把若干个PRP条目连接起来,就成了PRP链表(List)。PRP链表中的每个PRP条目的偏移量都必须是0,PRP链表中的每个PRP条目都是描述一个物理页。它们不允许有相同的物理页,不然SSD往同一个物理页写入几次数据,会导致先写入的数据被覆盖。
在这里插入图片描述
每个NVMe命令中有两个域——PRP1和PRP2,主机就是通过这两个域告诉SSD数据在内存中的位置或者数据需要写入的地址。PRP1和PRP2有可能指向数据所在位置,也可能指向PRP链表。类似C语言中的指针概念,PRP1和PRP2可能是指针,也可能是指针的指针,还有可能是指针的指针的指针。别管你包得有多严实,根据不同的命令,SSD总能一层一层地剥下包装,找到数据在内存的真正物理地址。
在这里插入图片描述
SGL

对Admin命令来说,它只用PRP告诉SSD内存物理地址;对I/O命令来说,除了用PRP,主机还可以用SGL的方式来告诉SSD数据在内存中写入或者读取的物理地址。SGL首先是一个链表,由一个或者多个SGL段(Segment)组成,而每个SGL段又由一个或者多个SGL描述符(Descriptor)组成。SGL描述符是SGL最基本的单元,它描述了一段连续的物理内存空间:起始地址+空间大小。

每个SGL描述符大小是16字节。一块内存空间,可以用来放用户数据,也可以用来放SGL段,根据这段空间的不同用途,SGL描述符也分几种类型。
在这里插入图片描述
❑数据块描述符,这个好理解,它用于表明这段空间是用户数据空间。
❑段描述符,SGL是由SGL段组成的链表,既然是链表,前面一个段就需要有一个指针指向下一个段,这个指针就是SGL段描述符,它描述的是它下一个段所在的空间。
❑对链表当中倒数第二个段,它的SGL段描述符我们称之为SGL末段描述符。它本质还是SGL段描述符,描述的还是SGL段所在的空间。为什么需要把倒数第二个SGL段描述符单独定义成一种类型呢?目的是让SSD在解析SGL的时候,碰到SGL末段描述符,就知道链表快到头了,后面只有一个段了。
❑SGL位桶也是一种描述符,它只对主机读有用,用于告诉SSD往这个内存写入的东西不是它要的,所以不用传了。
在这里插入图片描述
无论是PRP还是SGL,本质都是描述内存中的一段数据空间,这段数据空间在物理上可能是连续的,也可能是不连续的。主机在命令中设置好PRP或者SGL,并告诉SSD数据源在内存的什么位置,或者从闪存上读取的数据应该放到内存的什么位置。PRP描述的是物理页,而SGL可以描述任意大小的内存空间。

对NVMe over PCIe(我们目前讲的都是NVMe跑在PCIe上的情况),Admin命令只支持PRP,I/O命令可以支持PRP或者SGL;对NVMe over Fabrics,所有命令只支持SGL。

5 Trace分析

主机发送一个读命令,PCIe是如何服务的?

第一步:主机写命令到SQ。
NVMe读命令在这里插入图片描述
第二步:主机通过写SQ的Tail DB,通知SSD来取命令。
主机通过写存储TLP来实现主机写SQ的Tail DB的。SSD控制器当中的寄存器会被映射到主机的内存地址空间,当然也包括Tail DB寄存器。主机在用写存储写的时候,只要设置该寄存器在主机内存中映射的地址,数据就能准确写入该寄存器。
在这里插入图片描述

第三步:SSD收到通知,去主机端的SQ中取指。
SSD通过读存储取指。SSD往主机发送了一个读存储的请求,主机通过响应的方式把命令数据返回给SSD。和前面的写存储不同,读存储中不含数据,只是一个请求,数据的传输需要对方发一个响应。

在这里插入图片描述

第四步:SSD执行读命令,把数据从闪存中读到缓存中,然后把数据传给主机。

SSD通过写存储TLP把主机命令所需的128 DW数据写入主机命令所要求的内存中。SSD每次写入32 DW,一共写了4次。SSD一旦把数据返回给主机,就会认为命令处理完毕。

在这里插入图片描述

第五步:SSD往主机的CQ中返回状态。
SSD是通过写存储TLP把16B的命令完成状态信息写入主机的CQ中。
在这里插入图片描述

第六步:SSD采用中断的方式告诉主机去处理CQ。
SSD中断主机,在NVMe/PCIe中有4种方式:Pin-Based Interrupt(基于引脚的中断)、Single Message MSI(单信息MSI)、Multiple Message MSI(多信息MSI)和MSI-X。
在这里插入图片描述

第七步:主机处理相应的CQ。
主机还是通过写存储TLP更新SSD端的CQ的Head DB的。

第八步:主机处理完相应的CQ后,需要更新SSD端的CQ的HeadDB,告知SSD CQ处理完毕。
主机还是通过写存储TLP更新SSD端的CQ的Head DB的。
在这里插入图片描述

6 端到端数据保护

端到端:一端是主机的内存空间,一端是SSD的闪存空间。我们需要保护的是用户数据。主机与SSD之间,数据传输的最小单元是逻辑块(Logical Block,LB),每个逻辑块大小可以是512B、1024B、2048B、4096B,主机在格式化SSD的时候,逻辑块大小就确定了,之后两者就按这个逻辑块大小进行数据交互。

数据从主机到NVM(Non-Volatile Memory,目前一般是闪存,后面我就用闪存来代表NVM),首先要经过PCIe传输到SSD的控制器,然后控制器把数据写入闪存;反过来,主机想从闪存上读取数据,首先要由SSD控制器从闪存上获得数据,然后经过PCIe把数据传送给主机。
在这里插入图片描述
主机与SSD之间,数据在PCIe上传输的时候,由于信道噪声的存在(说白了就是存在干扰),可能导致数据出错;另外,在SSD内部,控制器与闪存之间的数据也可能发生错误。为确保主机与闪存之间数据的完整性,即主机写入闪存的数据与最初主机写的数据一致,以及主机读到的数据与最初从闪存上读上来的数据一致,NVMe提供了一个端到端的数据保护功能

❑Guard(保镖):16位的CRC,它是基于逻辑块数据算出来的。❑Application Tag(应用标签):这个区域对控制器不可见,为主机所用。
❑Reference Tag(参考标签):将用户数据和地址(LBA)相关联,防止数据错乱。

CRC能够检测出数据是否有错,Reference Tag用于保证数据不会出现张冠李戴的问题,比如想读LBA x,结果却读到了LBA y的数据。NVMe数据保护机制能发现这类问题。

在这里插入图片描述
如果是无关紧要的数据,完全没有必要进行端到端的保护,毕竟数据保护需要传输额外的数据(每个逻辑数据块需要至少8B的额外数据保护信息,有效带宽减少),还需要SSD做额外的数据完整性校验(耗时,性能变差)。最关键的是在PCIe通道上,本来就有LCRC的保护,有必要的话还可以使能ECRC(这个跟NVMe关系不大,就不展开了)。
在这里插入图片描述

主机数据通过PCIe传输到SSD控制器时,SSD控制器会重新计算逻辑块数据的CRC,然后与保镖的CRC比较,如果两者匹配,说明数据传输是没有问题的;否则,数据就是有问题的,这个时候,SSD控制器就会给主机报错。如果数据检测没有问题,SSD控制器会把逻辑块数据和PI一同写入闪存中。将PI一同写入闪存中有什么意义呢?在读的时候有意义。
在这里插入图片描述

SSD控制器读闪存的时候,会对读上来的数据进行CRC校验,如果写入的时候带有PI,这个时候就能检测出读上来的数据是否正确,从而决定这个数据要不要传给主机。有人要说,对闪存来说,数据不是受ECC保护吗?为什么还要额外进行数据校验?没错,写入闪存中的数据是受ECC保护,但在SSD内部,数据从控制器到闪存,一般都要经过DRAM或者SRAM,在之前从SSD控制器写入闪存,或者从闪存读数据到SSD控制器,可能就会发生位翻转之类的小概率事件,从而导致数据不正确。如果在NVMe层再做一次CRC保护,这类数据错误就能被发现了。

除了数据位在SSD内发生翻转,由于固件问题或者别的原因,还会出现数据张冠李戴的问题:数据虽然没有CRC错误,但是它不是我们想要的数据。因此,还需要做Reference Ta g检测。SSD控制器通过PCIe把数据传给主机,主机端也会对数据进行校验,看SSD返回的数据是否有错。

下图所示的情况,主机与控制器端之间是没有数据保护的,因为PCIe已经能提供数据完整性保证了。但在SSD内部,控制器到闪存之间,由于各种的原因(数据位翻转,LBA数据不匹配),存在数据出错的可能,NVMe要求SSD控制器在把数据写入闪存前,计算好数据的PI,然后把数据和PI一同写入闪存。
在这里插入图片描述

数据端到端保护是NVMe的一个特色,其本质就是在数据块中加入CRC和与数据块对应的LBA等冗余信息,SSD控制器或者主机端利用这些信息进行数据校验,然后根据校验结果执行相应的操作。加入这些检错信息的好处是能让主机与SSD控制器及时发现数据错误,副作用有如下几个。
❑每个数据块需要额外的至少8B的数据保护信息,有效带宽减少。数据块越小,对带宽影响越大。
❑SSD控制器需要做数据校验,影响性能。

  • 25
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值