NVMe控制器寄存器


本文属于《 NVMe协议基础系列教程》之一,欢迎查看其它文章。

1 内存映射寄存器

NVMe控制器寄存器,位于配置空间BAR0与BAR1,所映射的内存空间中。
在PCI Header中,有如下定义:

在这里插入图片描述
BAR0为低32位,BAR1为高32位,一起组合为64位内存地址,表示PCIe设备内存空间的基址。
在这里插入图片描述

NVMe控制器寄存器,就位于该内存空间中,并且host访问这些寄存器,应按原始宽度或32位对齐来访问。
NVMe控制器寄存器,定义如下:
在这里插入图片描述
由于NVMe控制器寄存器,位于PCIe设备内存空间中,因此上表中Start和End列,是相对于PCIe设备内存空间基址的偏移。

NVMe协议中,常见术语缩写,如下所示:

  • RO:只读
  • RW:读写
  • R/W:读写,读取的值可能不是最后写入的值
  • RWC:读/写’1’,来清除寄存器
  • RWS:读/写’1’,来设置寄存器
  • Impl Spec:实现细节,控制器可以自由选择其实现
  • HwInit:默认状态,取决于设备和系统配置。该值在复位时初始化,例如,在集成设备的情况下,由平台BIOS在扩展ROM上初始化。

1.1 Offset 00h: CAP – Controller Capabilities

Controller Capabilities寄存器,共8字节,表示控制器对Host软件的基础能力。

Bit Type Reset Description
63:56 RO 0h 保留
55:52 RO Impl Spec Memory Page Size Maximum (MPSMAX):该字段表示,控制器支持的最大主机内存页大小。
最大内存页大小为(2 ^ (12 + MPSMAX)),主机不能在CC.MPS中配置,大于此值的内存页大小。
51:48 RO Impl Spec Memory Page Size Minimum (MPSMIN):该字段表示,控制器支持的最小主机内存页大小。
最小内存页大小为(2 ^ (12 + MPSMIN)),主机不能在CC.MPS中配置,小于此值的内存页大小。
47:45 RO 0h 保留
44:37 RO Impl Spec Command Sets Supported (CSS):该字段表示,控制器支持的l/O命令集,至少支持一个命令集。
这个字段有点重要,如果一个位被设置为’1’,则支持相应的l/O命令集;
如果一个位被清除为’0’,则不支持相应的l/O命令集。在这里插入图片描述
36 RO Impl Spec NVM Subsystem Reset Supported (NSSRS):该字段表示,控制器是否支持NVM Subsystem Reset特性。
如果控制器支持NVM Subsystem Reset特性,该字段设置为“1”;
如果控制器不支持NVM子系统复位特性,该字段清除为“0”。
35:32 RO Impl Spec Doorbell Stride (DSTRD):每个提交队列和完成队列Doorbell寄存器的大小是32位。
这个寄存器指示,Doorbell寄存器之间的间隔,间隔被指定为(2 ^ (2 + DSTRD))字节。
值0h表示4字节的间隔,其中Doorbell寄存器被打包,每个寄存器之间没有保留空间。
31:24 RO Impl Spec Timeout (TO):这是主机软件等待CSTS.RDY从以下过渡的超时时间:
a)CC.EN从’ 0 ‘转换到’ 1 ‘;
b)CC.EN从’ 1 ‘转换到’ 0 ';
这种最坏的情况,可能发生在突然关机或激活新固件镜像等事件之后;预计典型时间会短得多。该字段的单位是500毫秒。
23:19 RO 0h 保留
18:17 RO Impl Spec Arbitration Mechanism Supported (AMS):该字段的位是重要的,表示控制器支持的可选仲裁机制。如果一个位设置为“1”,则控制器支持相应的仲裁机制。
在这里插入图片描述
没有列出轮转仲裁机制,因为所有控制器都应支持该仲裁机制。
16 RO Impl Spec Contiguous Queues Required (CQR)
如果控制器要求,I/O提交队列和I/O完成队列,在物理上是连续的,则该字段设置为’ 1 ‘。
如果控制器支持物理上,不连续的I/O提交队列和I/O完成队列,该字段清空为“0”。
如果这个字段设置为’ 1 ‘,那么,在创建I/O提交队列和I/O完成队列命令中的物理连续位(CDW11.PC),应该设置为’ 1 '。
15:00 RO Impl Spec Maximum Queue Entries Supported (MQES):该字段表示,控制器支持的最大单个队列长度。
这个值适用于,主机软件可能创建的每一个I/O提交队列和I/O完成队列。这是一个基于0的值。最小值是1h,表示两个条目。

1.2 Offset 08h: VS – Version

Version寄存器,共4字节,表示控制器支持的NVM Express规范主和从版本。
上面两个字节,表示主版本号;下面两个字节,表示从版本号。
例如:版本3.12将表示为00030102h。本规范的有效版本是1.0。

Bit Type Reset Description
31:16 RO 0001h Major Version Number (MJR):主版本号为1
15:00 RO 0000h Minor Version Number (MNR):次版本号为0

1.3 Offset 0Ch: INTMS – Interrupt Mask Set

Interrupt Mask Set寄存器,共4字节。当使用基于引脚的中断、单消息MSI或多消息MSI时,该寄存器用于屏蔽中断。

  • 当使用MSI-X时,应该使用定义为MSI-X一部分的中断掩码表来屏蔽中断。
  • 当为MSI-X配置时,主机软件不得访问此寄存器;为MSI-X配置的任何访问都是未定义的。
Bit Type Reset Description
31:00 RW1S 0h Interrupt Vector Mask Set (IVMS):这个字段的位是重要的。
如果将’ 1 ‘写入到比特位,则对应的中断向量被屏蔽;将’ 0 ‘写入到一个比特位没有任何影响。
当读取时,该字段返回控制器内当前的中断掩码值(不是该寄存器的值);如果某个比特位的值为’ 1 ‘,则对应的中断向量被屏蔽;如果某个比特位的值为’ 0 ',则对应的中断向量不会被屏蔽。

1.4 Offset 10h: INTMC – Interrupt Mask Clear

Interrupt Mask Clear寄存器,共4字节。当使用基于引脚的中断、单消息MSI或多消息MSI时,该寄存器用于解除屏蔽中断。

  • 当使用MSI-X时,应该使用定义为MSI-X一部分的中断掩码表来解除中断掩码。
  • 当为MSI-X配置时,主机软件不得访问此寄存器;为MSI-X配置的任何访问都是未定义的。
Bit Type Reset Description
31:00 RW1S 0h Interrupt Vector Mask Set (IVMS):这个字段的位是重要的。
如果将’ 1 ‘写入到比特位,则对应的中断向量被屏蔽;将’ 0 ‘写入到一个比特位没有任何影响。
当读取时,该字段返回控制器内当前的中断掩码值(不是该寄存器的值);如果某个比特位的值为’ 1 ‘,则对应的中断向量被屏蔽;如果某个比特位的值为’ 0 ',则对应的中断向量不会被屏蔽。

1.5 Offset 14h: CC – Controller Configuration

Controller Configuration寄存器,共4字节。该寄存器修改控制器的设置。
主机软件应将Arbitration Mechanism(CC.AMS)、Memory Page Size(CC.MPS)和Command Set(CC.CSS)设置为有效值,然后通过将CC.EN设置为’ 1 '来启用控制器。

Bit Type Reset Description
31:24 RO 0h 保留
23:20 RW 0h I/O Completion Queue Entry Size (IOCQES):该字段定义了,用于所选I/O命令集的I/O Completion Queue条目的大小。Identify Controller数据结构,为每个I/O命令集指定了,该字段的所需值和最大值。该值以字节为单位,以2的幂(2^n)指定。
19:16 RW 0h I/O Submission Queue Entry Size (IOSQES):该字段定义了,用于所选I/O命令集的I/O Submission Queue条目的大小。Identify Controller数据结构,为每个I/O命令集指定了,该字段的所需值和最大值。该值以字节为单位,以2的幂(2^n)指定。
15:14 RW 0h Shutdown Notification (SHN):该字段用于在关机发生时,启动关机处理(即,预期出现掉电条件)。
对于正常的关机通知,期望控制器有时间来处理关机通知。对于突然关机通知,主机可能没有等到关机处理完成才失去电源。
关闭通知的值定义为:
在这里插入图片描述这个字段应该在,任何电源关闭条件之前和PCI电源管理状态的任何改变之前,由主机软件编写。建议在热重启之前,也写入该字段。要确定关闭处理,何时完成,请参考CSTS.SHST。
13:11 RW 0h Arbitration Mechanism Selected (AMS):该字段用于选择要使用的仲裁机制。
只有当EN被清除为“0”时,这个值才会改变。主机软件只能将此字段设置为CAP.AMS中所示的支持的仲裁机制。如果将该字段设置为不支持的值,则行为未定义。在这里插入图片描述
10:07 RW 0h Memory Page Size (MPS):这个字段,表示主机内存页面大小,内存页面大小为(2 ^ (12 + MPS))。
因此,最小的主机内存页面大小是4KB,最大的主机内存页面大小是128MB。
主机软件设置的值,应该是CAP.MPSMAX和CAP.MPSMIN字段所表示支持的值。该字段描述了,用于PRP条目大小的值。只有当EN被清除为“0”时,该字段才会被修改。
06:04 RW 0h I/O Command Set Selected (CSS):该字段指定,用于I/O Submission Queue的I/O命令集。
主机软件只能选择支持的I/O命令集,如CAP.CSS所示。该字段只能在,控制器被禁用时更改(CC.EN被清除为“0”)。所选I/O命令集应用于所有I/O Submission Queue。
在这里插入图片描述
03:01 RO 0h 保留
00 RW 0h Enable (EN)
a)当设置为’ 1 ‘时,控制器根据Submission Queue Tail doorbell写的命令进行处理。
b)当清除为’ 0 ‘时,控制器将不会处理命令,也不会将完成队列条目发送到Completion Queues。
c)当这个字段从1转换到0时,控制器被重置(称为Controller Reset)。
重置删除所有I/O Submission Queues和I/O Completion Queues,重置Admin Submission Queue和Completion Queues,并使硬件处于空闲状态。
复位不影响PCIe寄存器或Admin Queue寄存器(AQA、ASQ或ACQ)。在本节中定义的,所有其他控制器寄存器和控制器内部状态(例如,不跨电源状态持久化的特征值),将重置为默认值。
控制器应确保,在复位操作之前,已将相应的完成队列条目发送到I/O Completion Queue的命令,没有数据丢失。
d)当该字段被清除为“0”时,一旦控制器准备重新启用,控制器将把CSTS.RDY位清除为“0”。
当该字段设置为’ 1 ‘时,控制器在准备处理命令时,将CSTS.RDY设置为’ 1 '。
当CSTS.RDY为1时,将该字段从0设置为1,或者当CSTS.RDY为0时将该字段从1设置为0,将产生未定义的结果。管理队列寄存器(AQA, ASQ和ACQ),只有在EN被清除为“0”时才会被修改。

1.6 Offset 1Ch: CSTS – Controller Status

Controller Status寄存器,共4字节。

Bit Type Reset Description
31:05 RO 0h 保留
04 RW1C HwInit NVM Subsystem Reset Occurred (NSSRO)
如果最后一次NVM Subsystem Reset,发生在NVM子系通电时,则此字段的初始值为“1”。
此字段的初始值为“0”,这是由于NVM子系统通电而导致的NVM Subsystem Reset。
该字段,仅在控制器支持NVM Subsystem Reset特性时有效,如CAP.NSSRS设置为’ 1 '。
如果NVM Subsystem Reset导致激活新的固件镜像,此字段的重置值为“0”。
03:02 RO 0h Shutdown Status (SHST):此字段表示由主机设置CC.SHN字段,而启动的关机处理的状态。
关机状态的值,定义如下:在这里插入图片描述在执行关机操作(CSTS.SHST设置为10b)后,要在控制器上执行命令,需要复位(CC.EN清除为“0”)。如果主机软件向控制器提交命令而不发出复位,则该行为是未定义的。
01 RO HwInit Controller Fatal Status (CFS):当发生无法在适当的完成队列中传递的,致命控制器错误时,此字段设置为’ 1 '。
当没有发生致命控制器错误时,该字段被清除为“0”。
当控制器初始化过程中,检测到致命错误时,该字段的重置值为“1”。
00 RO 0h Ready (RDY):CC.EN设置为“1”后,当控制器准备好接受Submission Queue Tail doorbell写入时,此字段设置为“1”。
当CC.EN清除为“0”时,此字段应清除为“零”。
在CC.EN位设置为“1”之后,此字段设置为“1”之前,不得向控制器提交命令。不遵守此要求会产生未定义的结果。
在将CC.EN从以前的值“0”设置为“1”后,主机软件应等待至少CAP.TO秒,以便将该字段设置为“1”。

1.7 Offset 20h: NSSR – NVM Subsystem Reset

NVM Subsystem Reset寄存器,共4字节。
此可选寄存器,为主机软件提供初始化NVM Subsystem Reset的能力。对该寄存器的支持由NVM Subsystem Reset Supported(CAP.NSSRS)字段的状态表示。如果寄存器不被支持,则保留寄存器占用的地址范围。

Bit Type Reset Description
31:00 RW 0h NVM Subsystem Reset Control (NSSRC):将值4E564D65h (“NVMe”)写入该字段,以初始化NVM Subsystem Reset。
写入任何其他值,对NVM子系统的操作,都没有功能上的影响。
该字段在读取时,返回值为0h。

1.8 Offset 24h: AQA – Admin Queue Attributes

Admin Queue Attributes寄存器,共4字节。
这个寄存器定义了Admin Submission Queue和Admin Completion Queue的属性。Admin Submission Queue和Admin Completion Queue的队列标识符是0h。Admin Submission Queue的优先级由所选择的仲裁机制决定。

Admin Submission Queue和Admin Completion Queue需要在物理上连续的内存中。

注意:
建议引导操作使用UEFI。在低内存环境中(比如legacy BIOS环境中的Option ROMs),可能没有足够的可用内存来分配必要的Submission和Completion队列。在这些类型的条件下,控制器的低内存操作是特定于供应商的。

Bit Type Reset Description
31:28 RO 0h 保留
27:16 RW 0h Admin Completion Queue Size (ACQS):定义管理完成队列的大小,最小是2个条目,最大是4096个条目。这是一个基于0的值。
15:12 RO 0h 保留
11:00 RW 0h Admin Submission Queue Size (ASQS):定义管理提交队列的大小,最小是2个条目,最大是4096个条目。这是一个基于0的值。

1.9 Offset 28h: ASQ – Admin Submission Queue Base Address

Admin Submission Queue Base Address寄存器,共8字节。
这个寄存器定义了,管理提交队列的内存基地址

Bit Type Reset Description
63:12 RW Impl Spec Admin Submission Queue Base (ASQB):管理提交队列的64位物理地址,此地址应与内存页对齐(基于CC.MPS中的值)。
所有的管理命令,包括I/O提交队列和I/O完成队列的创建,都必须提交到这个队列。
11:00 RO 0h 保留

1.10 Offset 30h: ACQ – Admin Completion Queue Base Address

Admin Completion Queue Base Address寄存器,共8字节。
此寄存器定义了,管理完成队列的内存基地址

Bit Type Reset Description
63:12 RW Impl Spec Admin Completion Queue Base (ACQB):管理完成队列的64位物理地址,此地址应与内存页对齐(基于CC.MPS中的值)。
所有提交到Admin Submission Queue的命令的完成队列条目,都应该提交到这个完成队列。该队列总是关联到中断向量0。
11:00 RO 0h 保留

1.11 Offset (1000h + ((2y) * (4 << CAP.DSTRD))): SQyTDBL – Submission Queue y Tail Doorbell

Submission Queue y Tail Doorbell寄存器,共4字节。
这个寄存器定义了doorbell寄存器,用于更新Submission Queue y的尾部条目指针(Tail),y的值等于队列标识符。这向控制器表明,已经提交了新的命令待处理。

  • Host不应该读取doorbell寄存器,如果读取doorbell寄存器,则返回特定于供应商的值。
  • 向不存在的Submission Queue Tail Doorbell写入,结果未定义。
Bit Type Reset Description
31:16 RO 0 保留
15:00 RW 0h Submission Queue Tail (SQT):表示Submission Queue尾部条目指针的新值,该值将覆盖先前Submission Queue尾部条目指针的值。
上一次SQT写和当前SQT写之间的差值,表示添加到Submission Queue的命令数量。
注意:需要考虑,提交队列翻转。

1.12 Offset (1000h + ((2y + 1) * (4 << CAP.DSTRD))): CQyHDBL – Completion Queue y Head Doorbell

Completion Queue y Head Doorbell寄存器,共4字节。
这个寄存器定义了doorbell寄存器,用于更新Completion Queue y的头部条目指针(Head),y的值等于队列标识符。这表示已被Host软件处理完毕的,完成队列条目。

  • Host不应该读取doorbell寄存器,如果读取doorbell寄存器,则返回特定于供应商的值。
  • 写入一个不存在的Completion Queue Head Doorbell,有未定义的结果。
  • Host软件应该确保,它继续处理Completion Queues中的完成队列条目,而不管在特定或任何Submission Queue中是否有可用条目。
Bit Type Reset Description
31:16 RO 0 保留
15:00 RW 0h Completion Queue Head (CQH):表示Completion Queue头部条目指针的新值,该值将覆盖先前Completion Queue头部条目指针的值。
上一次CQH写和当前CQH写之间的差值,表示Completion Queue中可供控制器重用的条目数量。
注意:需要考虑,完成队列翻转。

1.13 Doorbell寄存器组织结构

在这里插入图片描述
在这里插入图片描述
每个NVMe控制器有一个Admin Queue。因此,协议规定,Admin Queue的Doorbell,默认固定从1000h开始:

  • 1000h ~ 1003h,Submission Queue 0 Tail Doorbell (Admin)
  • 1000h + (1 * (4 << CAP.DSTRD)) ~ 1003h + (1 * (4 << CAP.DSTRD)),Completion Queue 0 Head Doorbell (Admin)

CAP.DSTRD,就是Controller Capabilities的Doorbell Stride (DSTRD)寄存器,表示Doorbell寄存器之间的间隔,间隔被指定为(2 ^ (2 + DSTRD))字节。DSTRD=0h表示4字节的间隔,其中Doorbell寄存器被打包,每个寄存器之间没有保留空间。

每个NVMe控制器最多64K个I/O Queue。Admin Submission Queue和Admin Completion Queue的队列标识符均为0h;因此,IO Queue标识符从1开始,一直到y,y最大可以为64k。

因此,协议规定,I/O Queue的Doorbell偏移范围为:

  • 从1000h + (2 * (4 << CAP.DSTRD)) ~ 1003h + (2 * (4 << CAP.DSTRD))开始,Submission Queue 1 Tail Doorbell
  • 至1000h + ((2y + 1) * (4 << CAP.DSTRD)) ~ 1003h + ((2y + 1) * (4 << CAP.DSTRD))结束,Completion Queue y Head Doorbell

2 I/O空间寄存器(可选)

Index/Data Pair registers(索引/数据对寄存器),是一对I/O空间寄存器。

Index/Data Pair registers,为Host软件提供了一种基于I/O空间寄存器,来访问NVMe内存映射寄存器的机制。如果支持此特性的话,这些寄存器将位于BAR2对应内存空间中。

在基于PC的平台上,如果PCIe Function的地址空间,被内存映射,并且映射到1MB以上,那么,Host软件(BIOS, Option ROMs, OSes)在实模式下的写操作,不能访问该地址空间中的寄存器。

索引/数据对机制,允许Host软件使用间接I/O寻址代替直接内存映射,来访问所有内存映射的NVMe寄存器。

注意:
UEFI驱动没有1MB的限制,因此在使用EFI时,不需要索引/数据对机制。因此,这个特性对于控制器来说是可选的,并且随着UEFI的普及,此特性可能会被淘汰。

2.1 限制

Host软件不得在,基于索引/数据对的存取和直接内存映射存取方法之间交替使用。在使用对控制器寄存器的直接内存映射访问后,索引/数据对机制将不再使用。

2.2 Index/Data Pair registers

下列寄存器描述了,实现索引/数据对所需的寄存器。
在这里插入图片描述

  • Index register:索引寄存器,占4字节,偏移为00h~03h;
  • Data register:数据寄存器,占4字节,偏移为04h~07h。

2.3 Offset 00h: IDX – Index Register

Bit Type Reset Description
31:02 RW 0h Index (IDX):该寄存器表示,MLBAR/MUBAR寄存器(PCI BAR0和BAR1)内存映射空间中的NVMe寄存器双字偏移。
01:00 RO 0h 保留

2.4 Offset 04h: DAT – Data Register

Bit Type Reset Description
31:00 RW na Data (DAT):该寄存器是一个“窗口”,通过它可以向索引寄存器,指向的内存映射寄存器读取或写入数据。没有实现物理寄存器,因为数据实际上存储在内存映射寄存器中。由于这不是一个物理寄存器,复位值与索引寄存器当前指向的寄存器复位值相同。

举两个例子,就明白了。
假设,欲将4E564D65h值,写入NVMe控制器的20h(NVM Subsystem Reset)寄存器,那么:

  • 将偏移20h,写入Index Register;
  • 将值4E564D65h,写入Data Register;
  • 机制会自动将Data Register寄存器值,写入Index Register指向的寄存器。

假设,欲读取NVMe控制器的20h(NVM Subsystem Reset)寄存器,那么:

  • 将偏移20h,写入Index Register;
  • 对Data Register进行读取操作;
  • 机制会自动读取Index Register指向的寄存器,并将结果作为Data Register寄存器值返回。

如此,便可以通过索引/数据对寄存器,实现对NVMe内存映射寄存器的访问。

相关推荐

  1. NVME Doorbell 寄存器& 数据请求时doorbell 处理

    2024-01-03 16:52:04       32 阅读
  2. 【ARMv9 DSU-120 系列 3 -- 系统控制寄存器

    2024-01-03 16:52:04       29 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-01-03 16:52:04       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-01-03 16:52:04       100 阅读
  3. 在Django里面运行非项目文件

    2024-01-03 16:52:04       82 阅读
  4. Python语言-面向对象

    2024-01-03 16:52:04       91 阅读

热门阅读

  1. Linux文件和目录管理命令---- cp 命令

    2024-01-03 16:52:04       66 阅读
  2. sql执行顺序

    2024-01-03 16:52:04       56 阅读
  3. 【docker】linux部署docker

    2024-01-03 16:52:04       61 阅读
  4. ChatGPT在金融财务领域的10种应用方法

    2024-01-03 16:52:04       63 阅读
  5. 数字图像处理滤波器汇总大全

    2024-01-03 16:52:04       61 阅读
  6. 如何解决跨域问题

    2024-01-03 16:52:04       68 阅读
  7. 笙默考试管理系统-MyExamTest----codemirror(59)

    2024-01-03 16:52:04       49 阅读
  8. 带多版本管理的Ubuntu软件源服务器搭建

    2024-01-03 16:52:04       64 阅读
  9. Go 语言为什么不支持并发读写 map

    2024-01-03 16:52:04       53 阅读