NVMe PCIe 指令执行流程详解

蛋蛋读NVMe之四 (ssdfans.com)

1.1.png 1.1.png

在上图协议栈中,PCIe定义了下三层,NVMe定义了最上遍的应用层,NVMe+PCIe构成了一个完整的Host与SSD通讯的协议。PCIe与NVMe最直接接触的是传输层。在NVMe层,我们能看到的是64字节的命令,16字节的命令返回状态,以及跟命令相关的数据。而在PCIe的传输层,我们能看到的是TLP (Transaction Layer Packet)。PCIe传输层作为NVMe最直接的服务者,不管你NVMe发给我的是命令,还是命令状态,还是用户数据,我统统帮你放进包裹,打包后交给下一层,让数据链路层继续处理。

我们只关注PCIe传输层,其和NVMe接触最密切,PCIe传输层传输的是TLP包,由包头和数据组成,NVMe传下来的数据都是放在TLP数据部分。为实现不同的目的,TLP可分为以下几种类型:

  • Configuration Read/Write
  • I/O Read/Write
  • Memory Read/write(PCIe传输层基本只用该类型TLP为NVMe服务)
  • Message
  • Completion(与NVMe中的命令执行完成不同)
**Host发送一个Read命令,PCIe如何服务?结合NVMe命令处理流程,解析NVMe和PCIe传输层发生了什么**

1.1.png

  • 1 首先Host准备了一条Read命令给SSD

    1.1.png

    Host需要从起始地址LBA 0x20E0448(SLBA)上读取128个DWORD(512字节)的数据,读到PRP1给出的内存地址0x14ACCB000。命令放在编号为3的SQ里 (SQ ID = 3),CQ编号也是3 (CQ ID = 3)。

  • 2 当Host把一个命令准备好放到SQ后,Host通过写SQ的Tail DB,通知SSD来取命令

    1.1.png

    上层是NVMe层,下层是PCIe的传输层,Host想往SQ Tail DB中写入的值是5。

    • 一个Host下方可能连接多个Endpoint,目标SSD只是其中一块,Host如何精准识别目标SSD Controller中的Tail DB?

      在上电过程中,每个Endpoint内部空间都会通过内存映射的方式映射到Host内存中,SSD控制器中的寄存器会被映射到Host内存,其中包括Tail DB寄存器。Host利用Memory Write写的时候,Address只需设置该寄存器在Host内存中的映射地址,就能写入目标寄存器。以上图为例,目标Tail DB寄存器应该映射在Host内存的F7C11018,所以Host可以利用该地址作为寻址。

  • 3 SSD收到通知,去Host端的SQ中取指

    1.1.png

    PCIe是通过发一个Memory Read TLP到Host的SQ中取指的。PCIe需要往Host内存中读取16个DWORD的数据。为什么是16 DWORD数据,因为每个NVMe命令的大小是64个字节。从上图中,我们可以推断SQ 3当前的Head指向的内存地址是0x101A41100

    • 在上图中,SSD往Host发送了一个Memory Read的请求,Host通过Completion的方式把命令数据返回给SSD。和前面的Memory Write不同,Memory Read中是不含数据,只是个请求,数据的传输需要对方发个Completion。memory read是Non-posted的,因为必须要有数据返回,每个memory read请求都必须要有相应的completion。
  • 4 SSD执行读命令,把数据从闪存中读到缓存中,然后把数据传给Host

    数据从闪存中读到缓存中,这个是SSD内部的操作,跟PCIe和NVMe没有任何关系,因此,我们捕捉不到SSD的这个行为。我们在PCIe接口上,我们只能捕捉到SSD把数据传给Host的过程。

    1.1.png

    上图中,SSD是通过Memory write TLP 把Host命令所需的128个DWORD数据写入到Host命令所要求的内存中去。SSD每次写入32个DWORD,一共写了4次。正如之前所说,我们没有看到Completion。

  • 5 SSD把数据返回给Host后,SSD往Host的CQ中返回状态

    1.1.png

    从上图中可以看出,SSD是通过Memory write TLP 把16个字节的命令完成状态信息写入到Host的CQ中。

  • 6 SSD往Host CQ中写入状态后,采用中断方式告知Host处理CQ

    1.1.png

    SSD中断Host,NVMe/PCIe有四种方式:Pin-based interrupt, single message MSI,multiple message MSI,和MSI-X。

    上图中使用MSI-X方式,不是通过硬件引脚,而是把中断信息和正常的数据信息一样,PCIe将终端信息打包告知Host,上图中SSD还是通过Memory Write TLP把中断信息告知Host,中断信息长度是1DWORD。

  • 7 Host处理相应的CQ

    在Host内部完成的事情,在PCIe线上捕捉不到处理过程;

  • 8 Host处理完相应的CQ后,需要更新SSD端的CQ Head DB,告知SSD CQ处理完毕

    1.1.png

    Host还是通过Memory Write TLP来更新SSD端的CQ Head DB

以上就是从PCIe传输层看NVMe Read命令的执行过程;传输层基本是通过Memory Write/Read TLP来处理NVMe命令、数据和状态信息