NVMe指令执行详解
NVMe PCIe 指令执行流程详解
在上图协议栈中,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中的命令执行完成不同)
1 首先Host准备了一条Read命令给SSD
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来取命令
上层是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中取指
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的过程。
上图中,SSD是通过Memory write TLP 把Host命令所需的128个DWORD数据写入到Host命令所要求的内存中去。SSD每次写入32个DWORD,一共写了4次。正如之前所说,我们没有看到Completion。
5 SSD把数据返回给Host后,SSD往Host的CQ中返回状态
从上图中可以看出,SSD是通过Memory write TLP 把16个字节的命令完成状态信息写入到Host的CQ中。
6 SSD往Host CQ中写入状态后,采用中断方式告知Host处理CQ
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处理完毕
Host还是通过Memory Write TLP来更新SSD端的CQ Head DB