NVME协议第四章-Data Structures

本章描述NVME所需的数据结构(讨论均基于PCIE over NVME)。

一、Submission Queue & Completion Queue Definition

host提交cmd到SQ,填入SQ后,Tail指针需要+1,如果tail指针超过队列queue size,那么tail跳回变成0(可以理解成为环形队列)。只要队列没full,那么host可以一直往队列提交cmd(entry)。----可以理解成生产者

对应的,SSD(或者nvme设备),从head指针获取entry后,head需要+1,如果head指针超过queue size,那么需要跳回变成0;只要queue不为空,那么head可以一直取entry。---消费者

创建和删除SQ和CQ需要由主机正确地排序。主机host应该创建CQ后,再创建任意的SQ。相关联的CQ创建完成后,任意时刻SQ都可能被创建。

删除时候,应该先删除相关联的SQ,再删除CQ。如果要终止提交到SQ的命令,主机host应该发出删除IO SQ queue命令。

主机host向 SQ doorbell tail和CQ doorbell head写入,把指针最新的值更新给controller。

如果host往SQ doorbell tail或者CQ doorbell head写入一个无效的值,并且异步事件并未完成,会产生一个异步事件,写入到admin CQ,状态码为invalid doorbell write value。主机host应该删除相关联的queue并重新创建。

对于发生错误的CQ来说,controller可能完成之前已经消耗的命令(已经取走的命令)或者没有额外的命令执行。这样情况发生可能原因:主机host尝试在一个full的SQ再添加一个entry,或者在一个empty的CQ里面取entry。

主机软件检查内存中的CQ Phase Tag (P)位,以确定是否有新的entry写入到CQ。CQ doorbell tail指针仅仅在controller内部使用,对host不可见。controller在CQ entry内部SQHD域,将SQ head信息(head pointer是由controller更新)的最新值发送给host。这里需要注意的是,SQHD域更新,仅仅代表entry被取走,但是具体命令还留在controller内部,可能能正在或者未执行。

当host往SQ doorbell tail写入新值,意味着SQ tail 指针位置移动,SQ entry提交给controller;SQ tail doorbell修改,可能被写入1个或者多个entry,提交给controller。

  一旦CQ entry被写入,一定至少有一个SQ被controller提交消耗。这里是多个SQ对一个CQ关系,或者一对一的关系。

一个CQ entry被写入,CQ entry内部phase Tag需要翻转用于标记CQ entry数量。controller会产生中断(一般MSI-X),通知一个或多个CQ entry被写入。

当host往CQ doorbell head指针写入值,代表CQ entry被消耗,指针位置移动到下一个位置;CQ head doorbell更新,可能意味着一个或者多个entry被消耗。

一旦CQ或者SQ entry被使用消耗,该位置可重复使用;SQ entry已经被提交,但在被消耗之前更改该SQ entry,或导致未定义行为。对CQ entry依然。

如果CQ无可用空间,那么controller需要停止写入直到空间可用,控制器可以处理其他queue。

1 empty queue

empty状态定义:当queue head指针 = queue tail指针时候,queue为空;

 2 full queue

当Head指针 = tail + 1时候,queue为满。当队列满时候,队列中entry size比 queue size小1个。

 3 queue size

queue size是一个0 base的16bit数,代表queue 能填入多少个entry。最小size是2个,IO SQ和CQ的queue size最大值为64k,被CAP.MQES设置所限制。Admin CQ and SQ queue size被定义成4k。根据full和empty queue定义,有一个空位是不被使用的。

4 queue Identifier

每一个queue都有一个16 bit的ID,在queue创建时候被分配;

5 queue priority

如果支持紧急优先级加权循环仲裁机制,host可能分配queue优先级等级,如紧急,高,中,低;若是不支持,controller会忽略优先级设置。

二、Submission Queue Entry – Command Format

 SQ entry可以是IO command,admin command,取决于queue的类型。

IO cmd(entry)是64byte;

DW0如下:

 opcode标识命令类型,不同命令的opcode不一样,opcode对照关系可以参考另外章节;

fused operation:可以将两个简单命令合并成一个复杂命令,合并的命令可以通过值知道first和second command。定义如下:

PSDT:用于标记数据传输时候,地址使用PRP还是使用SGL;PRPs在nvme over pcie中,对于admin和IO都适用;SGLs 在nvme over Fabrics,admin 和IO command都适用。

 如果metadata是单独保存的,那么MPTR用于指向metedata(通常开启PI情况下)。

command identifier:和SQ identifier组合成唯一命令标识符。

command DW0,Namespace identifier,Metadata Pointer,PRP entry 1, PRP entry 2,和metadata sgl segment pointer。以上部分是admin command和nvme command共同定义部分;

不是所有命令都会使用上面的部分,如 prp entry1, prp entry 2,metadata sgl segment pointer,可能有些命令不会使用。

一个通用的64byte command格式如下:(对admin和nvme command set)

注:sgls不应该被用于nvme over pcie的admin command上。

 namespace identifier:用于命名空间,command命令带NSID信息,指示当前哪一个NS;如果不支持namespace,那么默认清空为0;如果设置为0xFFFFFFFF,命令会应用到已经attached到controller的所有NS;

当前命令指定了一个inactive NSID,会造成controller终止命令,返回 Invalid Filed;

当前命令指定了一个invalid NSID,会造成controller终止命令,返回 Invalid Nanmespace or Format;

MPTR:logic bolock data和metedata单独保存,MPTR用于指向metadata数据;nvme over fabric上作为保留位;

 DPTR:根据PSDT值,选择PRP还是SGLs,以PRP为例:

后面得CDW,根据具体命令,格式稍有不同;

1 PRP

prp entry是一个指向物理内存的地址。PRPs被用于controller和host内存之间数据传输,PRP entry是有大小和对齐限制。

page size由CC.MPS决定,PRP entry的结构如下:

prp entry:64bit物理内存地址,[N: 2]代表内存页的偏移,比如一个内存页为4K,那么11 :2就是偏移;如果内存页8K,那么12:2就是偏移;如果PRP不是第一个entry或者不是PRP List pointer,偏移位应该清空为0;

prp list是一个prp entry集合,指向一段连续的内存页;PRP list是为了扩充prp entry,因为command内部就放置了2个prp位置,超过2个以上的prp,只能由prp list表示。在PRP List内的entry不会重复。如果PRP list内保存prp entry个数无法描述完这一笔数据传输,那么list最后一个entry也是一个prp list指针,指向prp entry。

关于PRP对齐的说明:

1 如果cmd传输data,只有1个prp情况下,保证prp1最低2bit为0;

2 如果传输data,刚好2个prp的情况,需要保证prp1最低2bit为0,且prp2 低12bit为0;

3 如果是prp list内部的entry,需要保证prp1是低2bit为0,prp list是8字节(64bit)对齐;

SGLs暂不讨论;

2 metadata region

对namespace来说,metadata可以作为logic block一部分,或者使用一个单独的数据buffer进行传输;metadata buff和logic block应该连续保存不分割;

logic block和metadata的数据格式是可变化的,不同的格式在性能方面是有差异;Identify Namespace data structure可以设置。

namespace如果使用PI功能,那么matadata的首8byte或者尾部8字节被用于存PI信息。

三、Completion Queue Entry

一个CQ entry包含16byte信息,如下图所示:

DW0是特定命令,若是要用DW0,那么需要包含到关联的命令定义中,不用就标记reserved。

DW1标记reserved;

DW2定义:

SQHD:记录当前SQ head指针,通过SQ head指针和SQ  tail指针(host可以写),这样host就可以知道SQ entry的数量;

SQID:标记已经执行的command关联的SQ, 当多个SQ共享一个一个CQ时候,host使用SQID来唯一确定command(CID)(不同的SQ可能CID一样,SQID下的CID是唯一的)。

DW3定义:

CID:用来标记正在完成的命令,当command被提交到SQ中, host会分配一个CID;

P:当CQ entry写入,此bit位翻转,用于标记新的entry。当CC.EN=1之前,host初始化就设置该bit位清0。当host写入一个CQ entry到CQ,P标记翻转,host能够区分新的entry;

SF:记录命令完成后状态;

主要是使用SC和SCT两部分;

 SC:

SC的value范围00h~FFH(具体state code可以参考spec)。

 

 四、Controller Memory Buffer

 CMB是controller上面一段通用读写内存区域,CMBSZ寄存器上设置flag,来表示内存区域的用途。controller需要通过PCIE的TLP包从host内存中读取SQ entry。

controller内存里的SQ意义在于:host能够写入整个所有的SQ entry到controller内部内存空间,避免频繁从host读取(每次读取都要TLP包传输),这样的方式可以减少命令执行的时间,提高数据的传输效率。类似地,PRP列表或SGL需要跨PCI Express(TLP)的单独获取,这可以通过将PRP或SGL写入控制器内存缓冲区来避免。

在小批量数据写场景下,将数据和metadata写入CMB,是对host有优势的,而不是从host内存从去这些数据。

CMB初始化未定义,host应该在使用前进行初始化。目前SQ、PRP、小写场景下都可以使用CMB,需要针对性进行初始化。

CMB上的queue使用方式和定义在host上面的queue一样,不同之处,使用的内存区域位于controller内存上,而不是主机上内存。

Admin queue或者IO queue也可以放置CMB上,对于一个特定的队列,与之相关联的所有内存都应驻留在CMB或host内存中。对于CMB的所有队列,该队列应是物理上连续的。

controller支持PRP放置在CMB上,若command上的prp list,与之关联的prps都应该保存CMB上。只有当保存在SQ上相关联的command先保存到CMB时候,PRPs才能被写入到CMB上。

controller CMB支持保存data或者metadata,与特定命令相关联的data和metadata都应该保存到CMB上面。

主机违反了CMB使用要求,会返回Invalid Use of Controller Memory Buffer status;

CMB地址需要4KB对齐,CMB地址分配时候需要注意。

host应该确保一个命令所需的CMB都已经被发送,然后再更新doorbell SQ tail。

五、namespace list

namespace list格式如下:

 六、controller list

 identify data structure的79:78byte定义controller identifier。

 七、Command Arbitration

 命令仲裁是用于确定controller中处理下一个候选命令的SQ的方法。一旦使用仲裁选择了一个提交队列,仲裁突发设置(Arbitration Burst)就确定了在仲裁再次发生之前,控制器可以从该提交队列开始处理的最大命令数量。

所有控制器均应支持循环指令仲裁机制。控制器可以选择性地实现具有紧急优先级类或者供应商特定的仲裁机制的加权循环。控制器能力寄存器中的仲裁机制支持字段(CC.AMS)表示控制器支持的可选仲裁机制。

为了有效地利用非易失性内存,并行执行来自提交队列的多个命令通常是有利的。对于使用具有紧急优先级类的加权循环或循环仲裁的提交队列,主机软件可以配置仲裁突发设置。仲裁突发设置指示控制器可以从特定提交队列一次启动的最大命令数。建议主机软件将仲裁突发设置配置为尽可能接近控制器的推荐值,并考虑到任何延迟要求。

Round Robin Arbitration

如果选择了循环仲裁机制,控制器应在所有提交队列中实现循环命令仲裁,包括管理提交队列。在这种情况下,处理所有提交队列的优先级相同。

2  Weighted Round Robin with Urgent Priority Class Arbitration

 在这个仲裁机制中,有三个严格的优先级类和三个加权循环优先级级别。如果SQ A的严格优先级高于SQ B,SQ A先执行,然后再执行SQ B中command。

最高严格优先级类是管理类(admin命令),它包括提交给SQ的任何命令。此类具有比提交给任何其他SQ的命令更最高的严格优先级。

第二个最高的严格优先级类是紧急类。分配给紧急优先级类的任何I/O SQ将在命令提交到管理员提交队列之后,以及在任何命令提交到加权循环优先级级别之前得到服务。

最低严格优先级类是加权循环类。这个类由三个加权循环优先级级别(高、中和低)组成,它们使用加权循环仲裁共享剩余的带宽。主机软件通过设置功能来控制高、中和低服务类的权重。循环用于在分配给相同加权循环级别的多个提交队列中进行仲裁。每轮可以从每个提交队列中开始处理的候选命令的数量是仲裁突发设置或剩余的加权循环积分,以较小者为准。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值