浅析NVMe协议:PRP/SGL数据传输格式
文章目录
- 概述
- PRP
- PRP Entry
- PRP List
- SGL
- SGL描述符
- SGL描述符类型
- SGL Data Block描述符
- SGL BitBucket描述符
- SGL Segment描述符
- SGL Last Segment描述符
- Keyed SGL Data Block描述符
- Transport SGL Data Block描述符
- SGL Segment
- 相关参考
概述
NVMe支持PRP(Physical Region Page)和SGL(Scatter-Gather List)两种方式描述数据的位置和长度等信息,其中,PRP是以主机物理页面为基本单位来描述数据的位置信息,存放在PRP里的地址需要满足主机物理页面对齐,配合页面偏移描述数据的实际地址;SGL适合描述多个分散的数据区域,相对于PRP,SGL在使用上要相对灵活一些,地址对齐粒度通常可以是Byte或Dword。
PRP
NVMe协议使用PRP描述数据的示意如下:
PRP Entry
PRP Entry是PRP格式的基本描述单元,指向主机中的一个物理内存页面。NVMe协议定义的PRP Entry格式如下:
PRP Entry包含Page Base Address和Offset:
- Page Base Address:物理内存页面的地址;
- Offset:数据在物理内存页面中的偏移,需要满足Dword对齐,通常只有命令中的第一个PRP Entry需要使用Offset来指示数据偏移。
上面的n取决于物理内存页面的大小,典型场景是4KB,那么n的值就是11,主机驱动可以通过CC.MPS字段配置物理内存页面大小到NVMe控制器。
PRP List
PRP List是一系列PRP Entry的数组,用于描述使用多个物理页面的数据,协议定义如下:
SGL
NVMe命令使用SGL描述数据示意如下:
SGL描述符
通用SGL描述符的格式定义如下:
SGL描述符是一个16Byte的表项,其中最高位的Byte描述了SGL的类型信息,包括SGL描述符类型和SGL描述符子类型。
协议支持的SGL描述符类型如下:
对于SGL描述符子类型,主要用于对不同类型SGL描述符的Address字段进一步做解释。
协议主要使用的SGL描述符子类型主要是0和1,其它值取决于传输层特殊定义或保留,对于0和1子类型的含义说明如下:
- 0指示Address字段包含了64位的内存地址;
- 1指示Address字段包含了从特定位置的偏移,通常是用于NoF Capsule同时携带了SQE和数据的场景下,描述数据在Capsule中的偏移位置。
SGL描述符类型
SGL Data Block描述符
SGL Data Block描述符记录数据在主机中的位置信息,包含数据起始地址和长度,是SGL中描述数据的基本单元。
SGL Data Block描述符记录的地址和长度,需要满足NVMe Controller对于地址对齐粒度的要求,通常可以是Byte或DWord,最终取决于NVMe Controller Identify里的配置。
SGL BitBucket描述符
SGL BitBucket描述符只携带了长度信息,自身不指向数据,通常用于读写命令中,指示NVMe Controller跳过对应长度的数据不处理。
SGL Segment描述符
SGL Segment描述符记录的是SGL Segment在内存中的地址和长度。
SGL Last Segment描述符
SGL Last Segment描述符用于记录SGL List中最后一级SGL Segment的位置信息。
Keyed SGL Data Block描述符
Keyed SGL Data Block描述符相较于常规的SGL Data Block描述符,额外携带了Key的信息,主要用于RDMA场景访问内存时作权限校验。
Transport SGL Data Block描述符
Transport SGL Data Block描述符提供了特定于NVMe传输层的数据描述方式,描述符本身只描述数据的长度,至于数据的位置以及传输方式,则由对应的传输层进行处理。
SGL Segment
SGL Segment是SGL描述符的数组,用于描述单一SGL描述符无法描述的多个数据区域。
相关参考
- 《NVM Express Base Specification,Revision 2.3》
