NVMe 标准数据结构

  • 4数据结构
    • 4.1数据布局
      • 4.1.1Physical Region Page Entry and List
      • 4.1.2Scatter Gather List (SGL)
        • 4.1.2.1SGL示例
      • 4.1.3Metadata Region (MR)
    • 4.2Feature值
    • 4.3Identifier的格式与布局
      • 4.3.1PCI Vendor ID (VID) 和 PCI Subsystem Vendor ID (SSVID)
      • 4.3.2Serial Number (SN) 和 Model Number (MN)
      • 4.3.3IEEE OUI Identifier (IEEE)
      • 4.3.4IEEE Extended Unique Identifier (EUI64)
      • 4.3.5Namespace Globally Unique Identifier (NGUID)
      • 4.3.6Universally Unique Identifier (UUID)
    • 4.4List Data Structures
      • 4.4.1Controller List
    • 4.5NVMe Qualified Names
      • 4.5.1Unique Identifier

4数据结构

本节介绍 NVM Express 使用的数据结构。

4.1数据布局

本节描述控制器和主机可以理解的数据布局的数据结构。

4.1.1Physical Region Page Entry and List

physical region page (PRP) entry 是指向物理内存页的指针。PRP 用作控制器和内存之间数据传输的分散/收集机制。为了在控制器和主机之间实现高效的乱序数据传输,PRP entry 的大小是固定的。

物理内存页的大小由 CC.MPS 中的主机软件配置。Figure 108 显示了由 Page Base Address 和 Offset 组成的 PRP entry 的布局。Offset 字段的大小由 CC.MPS 中配置的物理内存页大小决定。

Figure 108: PRP Entry Layout

Figure 109 描述了 PRP entry 的定义。

Figure 109: PRP Entry – Page Base Address and Offset

Bits Description
63:00 Page Base Address and Offset (PBAO): 该字段表示 64 位物理内存页地址。该字段的最低有效位 (n:0) 表示内存页内的偏移量(例如,如果内存页大小为 4 KiB,则bits 11:00 形成 Offset;如果内存页大小为 8 KiB,则bits 12:00 形成Offset)。如果该 entry 不是命令中的第一个 PRP entry 或命令中的 PRP List 指针,则该字段的 Offset 部分应清为 0h。Offset 应为dword对齐,由bits 1:0 清为 00b 表示。

注意:控制器不需要检查bits 1:0 是否被清除为 00b。如果bits 1:0 未清零为 00b,控制器可能会报告 PRP Offset Invalid 错误。如果控制器未报告 PRP Offset Invalid 错误,则控制器应像位 1:0 被清除为 00b 一样操作。

physical region page list(PRP List) 是单个连续内存页中的一组 PRP entries。PRP List 描述了无法在命令本身中描述的其他 PRP entries。命令中描述的任何 PRP entries 不会在 PRP List 中重复。如果要传输的数据量需要多个 PRP List 内存页,则内存页末尾之前的最后一个 PRP entry 应指向下一个 PRP List 的指针,指示 PRP List 的下一段。Figure 110 显示了 PRP List 的布局,其中每个 PRP entry 标识物理上连续的内存页。Figure 111 显示了 PRP List 的布局,其中每个 PRP entry 标识不同的内存页(即,内存页在物理上不是连续的)。

Figure 110: PRP List Layout for Physically Contiguous Memory Pages

Figure 111: PRP List Layout for Physically Non-Contiguous Memory Pages

根据命令定义,包含在命令中的第一个 PRP entry 可能在内存页内具有非0偏移量。第一个 PRP List entry(即,第一个指向包含其他 PRP entry的内存页的指针)如果存在,通常包含在命令中的 PRP Entry 2 位置中,它应该是 qword 对齐的,并且也可以在内存页中具有非0偏移量。

PRP List 中包含的 PRP entries 的内存页偏移量应为 0h。如果命令中存在第二个 PRP entry,则它的内存页偏移量应为 0h。在这两种情况下,entry 都是基于 CC.MPS 中的值对齐的内存页。如果控制器接收到这些 PRP entries 的非0偏移量,则控制器应返回 PRP Offset Invalid 错误。

包装的 entries 从entry 0 开始,PRP Lists 的大小应最小。如果需要更多 PRP List pages,则 PRP List 的最后一个 entry 包含下一个 PRP List page 的 Page Base Address。下一个 PRP List page 应与内存页对齐。命令所需的 PRP entries 总数由命令参数和内存页大小暗示。

4.1.2Scatter Gather List (SGL)

Scatter Gather List (SGL) 是内存地址空间中用于描述数据缓冲区的数据结构。控制器指示控制器在 Identify Controller data structure 中支持的 SGL 类型。数据缓冲区要么是 source buffer,要么是 destination buffer。SGL 包含一个或多个 SGL segments。SGL 中 Data Block 和 Bit Bucket 描述符的总长度应等于或超过请求传输的数据量。

SGL segment 是物理内存的连续区域中的 qword 对齐数据结构,描述了数据缓冲区和下一个 SGL segment(如果有)的全部、部分或没有。一个 SGL segment 由一个或多个 SGL descriptors 组成的数组。只有 SGL segment 中的最后一个 descriptor 可以是 SGL Segment descriptor 或 SGL Last Segment descriptor。

最后一个 SGL segment 是不包含 SGL Segment descriptor 或 SGL Last Segment descriptor 的 SGL segment。 控制器可以支持byte或dword对齐和Data Blocks的粒度。如果控制器仅支持 Identify Controller data structure 的 SGL Support 字段中指示的dword对齐和粒度(参见Figure 275)),则所有 Data Block descriptors 的Address 和 Length 字段中的值中两个最低有效位应清为 00b。此要求适用于指示数据和(或)元数据内存区域的 Data Block descriptors。

Identify Controller data structure 中的 SGL Descriptor Threshold (SDT) 字段(参见 Figure 275)指示命令的 SGL descriptors 的建议最大数量。如果 SDT 字段设置为非0值,并且提交的命令的总和为:

a)具有非0 Length 字段内容的 SGL Bit Bucket descriptors 的数量; 和
  b)具有非0 Length 字段内容的 SGL Data Block descriptors 的数量,

超过 SDT 字段的值,则控制器的 performance 可能会降低。

SDT 字段的值应小于或等于 Identify Controller data structure 中的 Maximum SGL Data Block Descriptors(MSDBD) 字段的值(有关 MSDBD 字段的定义,请参阅 NVMe over Fabrics 规范)。

Keyed SGL Data Block descriptor 是一个 Data Block descriptor,它包括一个用作主机内存访问一部分的密钥。可在 Keyed SGL Data Block descriptor 中指定的最大长度为 (16 MiB – 1)。

Transport SGL Data Block descriptor 是一个 Data Block descriptor,它指定由 NVMe Transport 使用特定 NVMe Transport 的传输机制和 data buffers 传输的数据块。

SGL Identifier Descriptor Sub Type 字段可以指示关于描述符的附加信息。例如,Sub Type 可以指示 Address 字段是偏移量而不是绝对地址。Address 还可以指示 NVMe Transport。

如果出现以下情况,控制器应中止命令:

  • 一个 SGL segment 包含一个 SGL Segment descriptor 或一个 SGL Last Segment 描述符,而不是该 segment 中的最后一个 descriptor ;
  • 最后一个 SGL segment 包含一个 SGL Segment descriptor,或一个 SGL Last Segment descriptor;
  • SGL descriptor 的格式不受支持; 或
  • SGL Data Block descriptor 包含 Address 或 Length 字段,其中两个最低有效位中的任何一个设置为 1b,并且控制器仅支持 dword 对齐和粒度,如 Identify Controller data structure 的 SGL Support 字段中所示。请参阅 Figure 275。

Figure 112 定义了 SGL segment。

Figure 112: SGL Segment

一个 SGL segment 包含一个或多个 SGL descriptors。Figure 113 定义了 generic SGL descriptor 格式。

Figure 113: Generic SGL Descriptor Format

Figure 114 中定义的 SGL Descriptor Type 字段指定了 SGL 描述符类型。如果 SGL Descriptor Type 字段设置为 reserved 值或不支持的值,则 SGL descriptor 应被处理为具有 SGL Descriptor Type 错误。如果 SGL Descriptor Sub Type 字段设置为 reserved 值或不支持的值,则描述符应被处理为具有 SGL Descriptor Type 错误。

设为全0的 SGL 描述符是 Address 字段清0且 Length 字段清0的 SGL Data Block descriptor,可用作 NULL descriptor。

Figure 114: SGL Descriptor Type

Figure 115 定义了 SGL Descriptor Sub Type 值并指示每个 SGL Descriptor Sub Type 适用的 SGL Descriptor Types。

Figure 115: SGL Descriptor Sub Type Values

Figure 116 中定义的 SGL Data Block descriptor 描述了一个数据块。

Figure 116: SGL Data Block descriptor

Figure 117 中定义的 SGL Bit Bucket 描述符用于忽略部分 source data。

Figure 117: SGL Bit Bucket descriptor

Figure 118 中定义的 SGL Segment descriptor 描述了下一个 SGL segment,前提是它不是最后一个 SGL segment。

Figure 118: SGL Segment descriptor

Figure 119 中定义的 The SGL Last Segment descriptor 描述了下一个和最后一个 SGL segment。包含 SGL Segment descriptor 或 SGL Last Segment descriptor 的最后一个 SGL segment 将作为错误处理。

Figure 119: SGL Last Segment descriptor

Figure 120 中定义的 Keyed SGL Data Block descriptor 描述了一个加密的数据块。

Figure 120: Keyed SGL Data Block descriptor

Figure 121: Transport SGL Data Block descriptor

4.1.2.1SGL示例

Figure 122 显示了使用 SGL 的数据读取请求示例。在此示例中,逻辑块大小为 512B。访问的逻辑块总长度为 13 KiB,其中只有 11 KiB 传输到主机。命令中的 Number of Logical Blocks (NLB) 字段应指定 26,表示在控制器上访问的逻辑块的总长度为 13 KiB。有三个 SGL segments 描述了逻辑块数据在内存中传输的位置。

三个 SGL segments 总共包含三个 Data Block descriptors,长度分别为 3 KiB、4 KiB 和 4 KiB。destination SGL 的第 1 段包含长度为 2 KiB 的 Bit Bucket descriptor,指定不从 NVM 传输(即忽略)2 KiB 逻辑块数据。destination SGL 的第 1 段还包含一个 Last Segment descriptor,指定描述符指向的 segment 是最后一个 SGL segment。

Figure 122: SGL Read Example

4.1.3Metadata Region (MR)

元数据区域的定义是特定于 command set 的。有关适用性和其他详细信息(如果有),请参阅每个 I/O Command Set 规范。

4.2Feature值

Get Features 命令(参见第 5.15 节)和 Set Features 命令(参见第 5.27 节)可用于读取和修改控制器的操作参数。操作参数由 Feature Identifiers 分组和标识。每个 Feature Identifier 都包含一个或多个可能影响 Feature 行为的属性。

如果在 Figure 275 中 Identify Controller data structure 的 Optional NVM Command Support(ONCS) 字段中的第 4 位设置为“1”,那么对于每个 Feature,都有三个设置:default、saved和current。如果在Identify Controller data structure 的 Optional NVM Command Support 字段中将第 4 位清除为“0”,则控制器仅支持每个 Feature 的current 值和 default 值。在这种情况下,当前值可以在power cycle和基于Figure 316 中指定的信息的 resets 期间保持不变。

如果 ONCS 字段中的第 4 位设置为“1”,则每个 Feature 都具有支持的capabilities(请参阅Figure 195),这些 capabilities 是使用 Get Features 中的 Select 字段中的 Supported Capabilities 值发现的(请参阅Figure 192)。

除非另有说明,否则每个 Feature 的默认值是供应商特定的并由制造商设置。default 值不可更改。

Feature 可能是可保存的。保存的值是 Controller Level Reset 后 Feature 具有的值。如果 Feature 不可保存,则:

a) 在 Controller Level Reset 后使用 default 值; 和

b) 读取 saved 值的 Get Features 命令会返回 default 值。

Feature 的 current 值是控制器为该 Feature 主动使用的值。

Set Features 命令使用命令指定的值来设置:

a) 该 Feature 的 current 值; 或
  b) 如果该 Feature 是可保存的, 则可以Set 该 Feature 的 current 值和该 Feature 的 saved 值。

Feature 设置可能适用于:   a) the controller (i.e., the feature is not namespace specific); or   b) a namespace (i.e., the feature is namespace specific).

对于用于控制器的 feature 值:

a)如果 NSID 字段被清为 0h 或设为 FFFFFFFFh,则:

  • Set Features 命令应为控制器设置指定的 feature 值;
  • Get Features 命令应返回控制器请求的 feature 值的当前设置;

b)如果 NSID 字段设置为 valid namespace identifier(请参阅第 3.2.1.2 节),则:

  • Set Features 命令应以 Feature Not Namespace Specific 状态码中止;
  • Get Features 命令应返回控制器请求的 feature 值的当前设置。

对于用于一个命名空间的 feature 值:

a) 如果 NSID 字段设置为 active namespace identifier(请参阅第 3.2.1.4 节),则:

  • Set Features 命令应设置指定命名空间的指定 feature 值;
  • Get Features 命令应返回指定命名空间的请求 feature 值的当前设置;

b) 如果 NSID 字段设置为 FFFFFFFFh,则:

  • 对于 Set Features 命令,控制器应:
      o如果在 Identify Controller data structure 中将 MDS 位设为“1”,则使用 Invalid Field in Command 中止命令; 或者
      o如果 Identify Controller data structure 中的MDS位被清为’0’,除非另有说明,否则为所有连接到处理命令的控制器的命名空间设置指定的 Feature 值;
  • 对于 Get Features 命令,除非第 5.27.1 节另有规定,否则控制器应以 Invalid Namespace or Format 状态码中止命令;

c) 如果 NSID 字段设置为任何其他值,则 Set Features 命令和 Get Features 命令应中止,如 Figure 87 中 namespace identifier 使用规则中所述。

如果控制器支持 Set Features 命令中的 Save 字段和 Get Features 命令中的 Select 字段,那么任何命名空间特定的 Feature Identifier 都可以在每个命名空间的基础上保存。

在 Figure 316 中定义了强制和可选的 Feature Identifiers。如果处理了指定不支持的 Feature Identifier的 Get Features 命令或 Set Features 命令,则控制器应中止命令,状态码为 Invalid Field in Command。

4.3Identifier的格式与布局

本节为正确实施 Identify Controller、Identify Namespace 和 Namespace Identification Descriptor data structures 中定义的各种identifiers提供指导。

4.3.1PCI Vendor ID (VID) 和 PCI Subsystem Vendor ID (SSVID)

PCI Vendor ID(VID,bytes 01:00)和 PCI Subsystem Vendor ID(SSVID,bytes 03:02)在 Identify Controller data structure 中定义。这些值由 PCI SIG 分配。每个 identifier 都是小端格式的 16 位数字。

例子: - VID = ABCDh; and - SSVID = 1234h.

Figure 123: PCI Vendor ID (VID) and PCI Subsystem Vendor ID (SSVID)

4.3.2Serial Number (SN) 和 Model Number (MN)

Serial Number(SN,bytes 23:04)和 Model Number(MN,bytes 63:24)在 Identify Controller data structure 中定义。这些值是供应商分配的 ASCII 字符串。每个 identifier 都是大端格式。

示例(显示为 ASCII 字符的值): - SN = “SN1”; and - MN = “M2”.

Figure 124: Serial Number (SN) and Model Number (MN)

4.3.3IEEE OUI Identifier (IEEE)

IEEE OUI Identifier(OUI,bytes 75:73)在 Identify Controller data structure 中定义。该值由 IEEE Registration Authority 分配。identifier采用小端格式。

例子:

  • OUI = ABCDEFh.

Figure 125: IEEE OUI Identifier (IEEE)

4.3.4IEEE Extended Unique Identifier (EUI64)

IEEE Extended Unique Identifier(EUI64,bytes 127:120)在 Identify Namespace data structure 中定义。教程可在 https://standards.ieee.org/develop/regauth/tut/index.html 获得。IEEE 定义了可用于该字段的三种格式:MA-L、MA-M 和 MA-S。本节中的示例使用 MA-L 格式。

MA-L 格式定义为一个由八个八位字节组成的字符串:

Figure 126: IEEE Extended Unique Identifier (EUI64), MA-L Format

EUI64 以大端格式定义。OUI 字段不同于 4.3.3 节中描述的小端格式的 OUI Identifier。

例子:

  • OUI Identifier = ABCDEFh; and
  • Extension Identifier = 0123456789h.

Figure 127: IEEE Extended Unique Identifier (EUI64), OUI Identifier

Figure 128: IEEE Extended Unique Identifier (EUI64), Ext. ID (cont)

MA-L 格式类似于定义为 IEEE Registered 指示符 (NAA = 5) 的 World Wide Name (WWN) 格式,如下所示。

Figure 129: MA-L similarity to WWN

4.3.5Namespace Globally Unique Identifier (NGUID)

命名空间全局唯一标识符(Namespace Globally Unique Identifier,NGUID,bytes 119:104)在 Identify Namespace data structure 中定义。NGUID 由 IEEE OUI、扩展标识符和供应商特定扩展标识符组成。扩展标识符和厂商特定扩展标识符都由厂商分配并且可以被视为单个字段。NGUID 以大端格式定义。OUI 字段不同于 4.3.3 节中描述的小端格式的 OUI Identifier。

例子:

  • OUI Identifier = ABCDEFh;
  • Extension Identifier = 0123456789h; and
  • Vendor Specific Extension Identifier = FEDCBA9876543210h.

Figure 130: Namespace Globally Unique Identifier (NGUID)

Figure 131: Namespace Globally Unique Identifier (NGUID), OUI

Figure 132: Namespace Globally Unique Identifier (NGUID), Extension Identifier (continued)

NGUID 格式类似于作为 IEEE Registered Extended 指示符 (NAA = 6) 的 World Wide Name (WWN) 格式,如下所示。

Figure 133: Namespace Globally Unique Identifier (NGUID), NGUID similarity to WWN

4.3.6Universally Unique Identifier (UUID)

Universally Unique Identifier 在 RFC 4122 中定义并包含在 Namespace Identification Descriptor (参见Figure 277)。RFC 4122 中描述了 UUID 的字节顺序要求。

4.4List Data Structures

本节描述了本规范中使用的列表数据结构。

4.4.1Controller List

Figure 134 中定义的 Controller List 是控制器ID 升序的有序列表。controller identifier 在 Figure 134 中Identify data structure 的 bytes 79:78 中定义。未使用的条目用0填充。

Figure 134: Controller List Format

Figure 135 中定义的 Namespace List 是 namespace ID 的有序列表。未使用的条目是0填充的。

Figure 135: Namespace List Format

4.5NVMe Qualified Names

NVMe Qualified Names (NQN) 用于唯一描述主机或 NVM 子系统,以用于识别和身份验证。NVM 子系统的 NVMe Qualified Name 在 Identify Controller data structure 中指定。NQN 在主机或 NVM 子系统的生命周期内是永久的。

NVMe Qualified Name 被编码为具有以下属性的 Unicode 字符串:

  • 编码为 UTF-8(请参阅 RFC 3629);
  • 以下字符用于格式化:
        o破折号 (‘-‘=U+002d);
        o点 (‘.’=U+002e);
        o冒号 (‘:’=U+003a);
  • 名字的最大长度为 223 个字节;
  • 字符串以空值结尾。

有两种受支持的 NQN 格式。任何拥有域名的组织都可以使用第一种格式。这种命名格式可用于创建人类可解释的字符串来描述主机或 NVM 子系统。这种格式包括: