[元带你学NVMe协议] 从传输层看PCIE 和 NVME 交互

29 篇文章 13 订阅 ¥49.90 ¥99.00

声明

主页元存储的博客_CSDN博客

https://blog.csdn.net/vagrant0407?type=blog
本文依据公开知识及个人经验整理而成,如有错误请留言。
文章为个人辛苦整理,付费内容,禁止私自转载。

内容摘要

PCIe传输层作为NVMe最直接的服务者,不管你NVMe发给我的是命令,还是命令状态,还是用户数据,我统统帮你放进包裹,打包后交给下一层。

TLP 类型

  1. Configuration Read/Write

  1. I/O Read/Write

  1. Memory Read/write

  1. Message

  1. Completion

NVMe命令处理流程


前言

今天我又把这张图搬出来了。没错,它是《蛋蛋读NVMe之一》里面的第一张图。任何一种计算机协议,它都是采用这种分层结构的。下层总是为上层服务的。有些协议,上图所有的层次都有定义和实现,而有些协议,只定义了其中的几层。然而,要让一种协议能工作,它需要一个完整的协议栈,PCIe定义了下三层,NVMe定义了最上层,两者一拍即合,构成一个完整的Host与SSD通讯的协议。

PCIe与NVMe最直接接触的是传输层。在NVMe层,我们能看到的是64字节的命令,16字节的命令返回状态,以及跟命令相关的数据。而在PCIe的传输层,我们能看到的是TLP (Transaction Layer Packet)。还是跟快递做类比,你要寄东西,可能是手机,可能是电脑,不管是什么,你交给快递小哥,他总是把你要寄的东西打包,快递员看到的就是包裹,他根本不关心你里面的内容。PCIe传输层作为NVMe最直接的服务者,不管你NVMe发给我的是命令,还是命令状态,还是用户数据,我统统帮你放进包裹,打包后交给下一层,让数据链路层继续处理。

今天不打算深入讲解PCIe,这又是一个大的话题。SSD FANS可能后续会推出类似NVMe系列文章,来个PCIe系列的,大家可以期待一下。对PCIe,我们今天只关注传输层,因为它跟NVMe接触是最直接最亲密的。PCIe传输层传输的是TLP,它就是个包裹,一般由包头和数据组成,当然也有可能只有包头没有数据。NVMe传下来的数据都是放在TLP的数据部分的(Payload)。为实现不同的目的,TLP可分为以下几种类型:

  1. Configuration Read/Write

  1. I/O Read/Write

  1. Memory Read/write

  1. Message

  1. Completion

注意,这个Completion跟NVMe层的Completion不是同一个东西,他们处在不同层。在NVMe命令处理过程中,PCIe传输层基本只用Memory read/write TLP来为NVMe服务,其他TLP我们不用管。

Host发送一个Read命令,PCIe是怎么服务的?今天主要目的,就是结合NVMe命令处理流程,蛋蛋带着大家把下面这张图看懂,看看NVMe和PCIe的传输层发生了什么。

我靠,密密麻麻的,什么鬼东西?别急,蛋蛋带你一步一步把它看懂。

首先,Host准备了一个Read命令给SSD:

也许你对NVMe Read命令格式不是很清楚,说实话,我也不清楚,但从上图,我们还是能得到下面的信息: Host需要从起始LBA 0x20E0448(SLBA)上读取128个DWORD (512字节)的数据,读到哪里去呢?PRP1给出内存地址是0x14ACCB000。这个命令放在编号为3的SQ里 (SQID = 3),CQ编号也是3 (CQID = 3)。我觉得知道这些就够了。相信看了蛋蛋读NVMe系列的,刚才说的这些都应该能懂。

当Host把一个命令准备好放到SQ后,接下来步骤是什么呢?回想一下NVMe命令处理的八个步骤。

第二步就是:Host通过写SQ的Tail DB,通知SSD来取命令

上图中,上层是NVMe层,下层是PCIe的传输层,这一层我们看到的是TLP。Host想往SQ Tail DB中写入的值是5。PCIe是通过一个Memory Write TLP来实现Host写CQ的Tail DB的。

一个Host,下面可能连接着若干个Endpoint,该SSD只是其中的一个Endpoint而已,那有个问题,Host怎么能准确更新该SSD Controller中的Tail DB寄存器呢?怎么寻址?其实,在上电的过程中,每个Endpoint的内部空间都会通过内存映射(memory map)的方式映射到Host的内存中,SSD Controller当中的寄存器会被映射到Host的内存,当然也包括 Tail DB寄存器。Host在用Memory Write写的时候,Address只需设置该寄存器在Host内存中映射的地址,就能准确写入到该寄存器。以上图为例,该Tail DB寄存器应该映射在Host内存地址F7C11018,所以Host写DB,只需指定这个物理地址,就能准确无误的写入到对应的寄存器中去。应该注意的是:Host并不是往自己内存的那个物理地址写入东西,而是用那个物理地址作为寻址用,往SSD方向写。否则就太神奇了,往自己内存写东西就能改变SSD中的寄存器值,那不是量子效应吗?我们的东西还没有那么玄乎。

NVMe处理命令的第三步:SSD收到通知,去Host端的SQ中取指

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

在上图中,SSD往Host发送了一个Memory Read的请求,Host通过Completion的方式把命令数据返回给SSD。和前面的Memory Write不同,Memory Read中是不含数据,只是个请求,数据的传输需要对方发个Completion。像这种需要对方返回状态的TLP请求,我们叫它Non-Posted请求。怎么理解呢?Post,有”邮政”的意思,就像你寄信一样,你往邮箱中一扔,对方能不能收到,就看快递员的素养了,反正你是把信发出去了。像Memory Write这种,就是Posted请求,数据传给对方,至于对方有没有处理,我们不在乎;而像Memory Read这种请求,它就必须是Non-Posted了,因为如果对方不响应(不返回数据)给我,Memory Read就是失败的。所以,每个Memory read请求都有相应的Completion。

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

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

SSD一旦把数据返回给Host,SSD认为命令以及处理完毕,第五步就是:SSD往Host的CQ中返回状态。

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

SSD往Host的CQ中写入后,第六步就是:SSD采用中断的方式告诉Host去处理CQ。

SSD中断Host,NVMe/PCIe有四种方式:Pin-based interrupt, single message MSI,multiple message MSI,和MSI-X。关于中断,具体的可以参看spec 第171页,有详细介绍,有兴趣的可以去看看。从上图中,这个例子中使用的是MSI-X中断方式。跟传统的中断不一样,它不是通过硬件引脚的方式,而是把中断信息和正常的数据信息一样,PCIe打包把中断信息告知Host。上图告诉我们,SSD还是通过Memory Write TLP把中断信息告知Host,这个中断信息长度是1DWORD。

Host收到中断后,第七步就是:Host处理相应的CQ。这步是在Host端内部发生的事情,在PCIe线上我们捕捉不到这个处理过程。

最后一步,Host处理完相应的CQ后,需要更新SSD端的CQ Head DB,告知SSD CQ处理完毕。

跟前面一样,Host还是通过Memory Write TLP更新SSD端的CQ Head DB。

从我们抓的PCIe trace(感谢山哥提供!!除此之外,在整个NVMe系列的写作过程中,经常向山哥取经,在这深表感谢,感谢无私的帮助与解惑!)上,我们从PCIe的传输层看到了一个NVMe Read命令是怎么处理的,看到传输层基本都是通过Memory Write和Memory Read TLP传输NVMe命令、数据和状态等信息;我们确实也看到了NVMe命令处理的八个步骤,蛋蛋没有欺骗大家。

上面举的是NVMe读命令处理,其他命令处理过程其实差不多,就不凑篇幅了。

最后,我再贴出完整Trace,相信,也希望大家不会再有一团乱麻的感觉。

转载自:

brokenegg SSDFans: 蛋蛋读NVMe之四

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值