[存储]NVMe-4-数据结构

注意:本文翻译仅为学习交流用,版权归原文作者所有。

原文出处。

4 数据结构

这个这个章节讲NVM Express中的数据结构。

4.1 提交队列和完成队列定义

一个entry的提交者使用当前项的尾指针指向下一个空闲的队列槽位。在放置新entry后,提交者将尾指针向后移动,如果尾指针超过了队列大小,则将尾部entry滚动至0。提交者放置新entry直至队列满为止。

entry的消费者使用当前头entry指针表示下一个准备消耗的entry。在消耗一个entry后,头指针向下一个entry移动。同提交者…

提交队列和关联的完成队列的创建和销毁要求是有序执行的。主机软件应该先创建完成队列,再创建与之关联的提交队列。提交队列能在完成队列被创建完毕后任何时间创建。主机软件应该先删除提交队列,再删除完成队列。为中止提交到提交队列中的命令,主机软件应该下发删除IO提交队列的命令。

主机软件写提交队列Tail Doorbell和完成队列Head Doorbell,来向控制器通知新值。如果主机软件向提交队列Tail Doorbell或者完成队列Head Doorbell写无效值,并且异步事件请求命令未完成,那么一个异步事件将被下发到Admin完成队列,状态码为Invalid Doorbell Write Value.与之关联的队列应该被删除和重新创建。

主机软件检查完成队列项的PhaseTag§判断是否有命令完成状态放入完成队列。完成队列尾指针对主机是透明的,仅在控制器内部使用。控制器使用完成队列项中的SQHD(提交队列头指针)告诉主机提交队列头指针的值,在SQHD指向的提交队列项被消耗时,并不表示像是否被执行或者已经完成。

当主机软件向提交队列Tail Doorbell写新值时,表示有新的命令放置在提交队列Tail pointer指向的地方。提交队列Tail Doorbell被写时,表示主机软件提供了一个至多个提交队列项。

完成队列项被下发时,SQ head pointer向前移动,SQ项被控制器消耗。完成队列项可能指示一个至多个提交队列项被消耗。

————————————————————————

局部总结:

  • 提交队列和完成队列是Host的连续内存,有两对指针进行管理,i.e., Head Pointer和Tail Pointer;
  • 提交队列和完成队列在添加新值时,通过Doorbell寄存器通知,Host SW写提交队列Tail Doorbell告知controller来取新命令,写完成队列Head Doorbell告知controller完成状态己经被取走;
  • HostSW将新命令放置于提交队列Tail Pointer, 将完成状态放置于完成队列Tail Pointer;

————————————————————————

4.1.1 Empty Queue

Head entry Pointer == Tail entry Pointer

[存储]NVMe-4-数据结构_第1张图片

4.1.2 Empty Queue

Head entry Pointer + 1 == Tail entry Pointer

4.1.3 Queue Size

IO SQ/CQ队列最大值是64Ki个slots,Admin SQ/CQ队列最大值是4Ki个slots。

4.1.4 Queue Identifier

队列的ID是两字节整型,在队列创建时被确定。

4.1.5 Queue Priority

加权robin采取优先级分四档:Urgent, High, Medium, Low.

4.2 Submission Queue Entry - Command Format

每个命令大小为64字节

提交队列项64字节,由以下几项组成:1) Command Dword 0, 2) NS Id, 3) Meta Pointer, 4) PRP Entry1/2, SGL Entry1, Meta SGL Segment Pointer.

具体的CDW0(4字节)格式可见SPEC中的图104。

Bits Description
31:16 Command Identifier (CID): This field specifies a unique identifier for the command when combined with the Submission Queue identifier.
命令ID,在提交队列创建时候CID
15:14 PRP or SGL for Data Transfer (PSDT):指定是否使用PRPs或者SGLs用于描述传输的数据,PRPs用于AdminCMD NVMe over PCIe, SGLs用于Admin/IO cmd NVMe over Fabrics,
- 00b: PRPs用于传输;
- 01b: SGLs用于传输,并且Meta Pointer(MPTR)包含单个连续物理buffer的地址,buffer字节对齐;
- 10b: SGLs用于传输,并且Meta Pointer(MPTR)包含SGL Segment的地址,这个SGL Segment是4字节对齐的;
- 11b: 保留
09:08 Fused Operation(FUSE): …
07:00 Opcode(OPC): 指定命令的操作码

Admin/NVM Command Set的大小是64字节,将来如果定义其他IO Command有可能有其他命令size/format.

SGLs不会被用在Admin CMD NVMe over PCIe中。

Bytes Description
03:00 Command Dword 0 (CDW0)
07:04 NSID: 这个命令应用的NS
15:08 保留
23:16 Metadata Pointer(MPTR):只有命令有meta数据并且不跟逻辑块数据交织在一起时有效,在Format NVM cmd中被用。CDW0.PSDT调节MPTR。
39:24 Data Pointer(DPTR):

CDW0.PSDT=00b:

PRPx每个占1字节

PRP2:

a) 如果数据传输不跨内存页,则保留
b) 如果数据传输超过一个内存页,则记录第二个内存页的基址。
c) PRP List Pointer跨多个内存页。

PRP1: 包含PRP项或者PRP List Pointer。

SGL占2字节

SGL1:

  • SGL segment是一个SGL Data Block或者Keyed SGL Data Block/Transport SGL Data Block desc,那么描述整个数据传输;
  • 如果需要多个segment描述数据传输,则这个SGL要么描述一个segment,要么描述下一个segment desc。
Bytes Desc
43:40 Command Dword 10
47:44 Command Dword 11
51:48 Command Dword 12
55:52 Command Dword 13
59:56 Command Dword 14
63:60 Command Dword 15

CDWx:在具体Admin/NVM CMD Set中定义具体的含义。

除了在Admin/NVM Cmd定义的变量,Admin/NVM Vendor Spec cmds支持Data/Meta Transfer数量(以Dwords为单位)。

CWD10: NO. of Dwords Data Transfer(NDT),数据传输的数量。

CWD11: NO. of Dwords Meta Transfer(NDM),元数据传输数量。

4.3 Physical Region Page Entry and List

PRP(物理区域页)entry是指向一个物理内存页的指针。PRP作为一个内存和控制器之间数据传递的catter/gather机制。PRP entry固定大小(8个字节)以在控制器和主机之间高效数据传输。

物理内存页大小在主机软件中的CC.MPS配置。

PRP entry由Page Base Addr + Offset组成(8字节)。

Bits Desc
63:00 Page Base Address and Offset(PBAO): 描述64-bit物理页内存地址,低n位数(n:0)描述页内偏移

PRP List(物理区域页列表)是一组PRP entry,存放在一个page里,描述连续内存。如果传输的数据量需要多个PRP List内存页描述,则最后一个PRP entry是一个指向下一个PRP List的指针。

第一个PRP Entry可能是非零内存页偏移,但是第二个PRP Entry需要是4字节对齐。

4.4 Scatter Gather List(SGL)

SGL是内存地址空间的数据结构,用于描述数据缓存(data buffer)。控制器在Identify Controller中指针SGL的类型。data buffer要么是源buffer要么是目标buffer。一个SGL包含多个SGL Segment。

SGL segment是4字节对齐的数据结构,存放在连续的物理内存中,描述全部、部分、无 数据缓存和下一个SGL segment。一个SGL segment由一组至少一个SGL描述符组成。只有SGL Segment中的最后一个描述符可能是SGL Segment描述符或者SGL Last Segment desc.

!控制器支持字节、双字节对齐和Data Blocks粒度。

Figure12: SGL Desc Type

Code Desc
0h SGL Data Block descriptor
1h SGL Bit Bucket descriptor
2h SGL Segment descriptor
3h SGL Last Segment descriptor
4h Keyed SGL Data Block descriptor
5h Transport SGL Data Block descriptor
6h to Eh 保留
Fh 厂商自定义

4.5 Metadata Region(MR)

NS支持meta时,meta作为逻辑块的一部分(i.e., extended logical block),meta也可能独立于data传输。meta与关联的逻辑块要保持原子写

MR是在NS格式化时指定的。

在NS被格式化用于End-to-End data protection时,meta的前8个字节或者后8个字节用于存放保护信息。

4.6 Completion Queue Entry

完成队列的一个entry至少16个字节。

如果CQ entry被多个写创建,那么Phase Tag应该被最后一个写 更新。

CQE前16个字节布局:

[存储]NVMe-4-数据结构_第2张图片

DW 2:

Bits Desc
31:16 SQID:标记命令下发到哪个提交队列
15:00 SQ Head Pointer: 当前提交队列的头指针位置

DW 3:

Bits Desc
31:17 Status Field(SF): 命令完成的状态
16 Phase Tag§: 标记CQE是否是新的
15:00 Command ID(CID): 正在完成的命令的ID,提交队列的最大深度是64Ki

4.6.1 Status Code/type

4.7 Controller Memory Buffer (CMB)

CMB是一个区域,这个区域能进行常规的对控制器的read/write。

通过设置CAP.CMBS=1控制器支持CMB

CMB PCIe地址范围能用于下发对CMB的外部内存读/写请求。CMB的PCIe基地址能通过PCI BAR(CMBLOC.BIR)和偏移(CMDLOC.OFST)定义。CMB大小由CMBSZ.SZ设置。

控制器能够使用主机提供的地址去读写CMB。

尽管PCIe地址范围与CMB控制器的地址范围可能不同,但是两个范围尺寸是相同的,并且每个范围的偏移是一一对应的。主机通过CMBMSC配置控制器地址范围。

Host通过CMBMSC.CMSE赋能CMB control内存空间,Host将地址映射到CMB的controller地址范围,controller能直接向CMB下发内存读/写请求。

Host需要配置CMB的controller地址范围,避免与用于DMA的地址范围重叠。

——————

注:

Host内存中的提交队列要求控制器执行PCIe读Host内存,以取回队列项。控制器内存中的提交队列赋能Host软件直接写SQE到控制器内部内存空间,避免从控制器读到内存。这个方法能减少命令执行时延,改善PCIe fabric 拓扑结构。PRP Lists和SGLs要求从PCIe fabrics中取回,当然也能直接将PRP/SGL写到CMB中。对于小数量的写,将data和meta直接写到CMB比从控制器取回Host内存,更有优势。

在控制器内存中的队列,与在Host内存中的队列,行为相同。不同的是,内存地址是位于控制器自己的内存,而不是Host的内存。Admin或者IO队列能存储在CMB中。

4.8 Persistent Memory Region

PMR基本原理与CMB相同,PMR是PM区域,能被PCIe 读/写。外部内存读写PCIe地址范围能被定向到PMR。

4.9 NVM Sets

NVM Set是一个集合,在逻辑上(有可能在物理上)独立于其他NVM Set的NVM集合。一个NS是在NVM Set里面,不会跨多个NVM Set.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a6Tud9HO-1613464013150)(./imgs/fig133.png)]

4.10 Namespace List

4.10 Controller List

4.13 Command Arbitration

从提交队列和完成队列中取entry有三种仲裁方式:1) Round Robin, 2) Werighted Round Robin with Urgent Priority Class Arbit. 3) Vendor Spec Arbit.

你可能感兴趣的:(存储)