一直想总结一下,PRP和SGL,网上也有不少资料,nvme官方spec只用了六七页解释了这俩货,还把寄存器如何操作也说明白了,作总结的目的是让自己对其更加深入了解
首先,SSD是用来保存数据,不是读就是写,即data从host流向SSD,或者从SSD到host中去。对于写来说,需要告诉SSD,写什么数据,写多少,数据在host哪个位置,对于读来说,同样,需要告诉SSD,需要什么数据,需要多少,需要把他放在host哪个位置。从上面读写的简单流程来说,我们应该会注意到都需要host那边有一块位置放数据,host不会主动把数据送给SSD,而是需要SSD主动去获取数据,或者写入数据,那么,host就需要一种方法,告诉SSD这些数据的地址,总共有两种方法,一种是PRP(Physical Region Page),另一种是SGL(Scatter Gather List)。
Physical Region Page Entry and List
首先来介绍一下PRP,nvme会把host的内存划分为页,每个页可以是4KB,8KB等,一般而言,一个页为4KB对齐的页,接下来看看PRP长什么样
其实PRP就是一个占用8个Byte的64位的内存物理地址,只不过把他分成了两部分,一个页基地址,和偏移。值得注意的是offset最后两位必须为0,因为要4Byte对齐
PRP Entry 描述的是一个物理内存的地址,PRP List就是多个PRP Entry组合起来的,其PRP的内存地址可以是连续的也可以是不连续的
对于PRP1和PRP2来说,它可以是个数据地址,也可以是PRP List 地址,不管是什么SSD总会解析出它是什么。下面给一个示例,
相信上图把PRP List解释的比较清楚了,就是PRP1中的地址是PRP List地址,然后从PRP List中再获取数据地址,如果疑问如何判断PRP1是数据地址还是PRP List地址,我们可以通过PRP Entry数量来判断,一般来说超过2个PRP Entry就需要使用PRP List。
Scatter Gather List
接下来讲讲SGL,对于SGL来说,相比PRP裸着的结构,SGL是一种数据结构,用来描述一段空间。我们首先明确一点SGL是一个链表,一个链表中结构是SGL Segment,每个Segment中又由多个SGL Descriptor组成,SGL Descriptor是最基本的一个单元,它占用16Byte,并且会有几种类型,Data Descriptor,Segment Descriptor,Last Descriptor等。
下图是Descriptor的定义,具体类型可以查看nvme spec。
在nvme spec中,给了一个样例可以很清晰的描述SGL的概念,
如果看着比较繁琐,那么看下图
对于SGL来说,相比PRP它的每块数据可以有不同的大小,PRP即是固定的大小,一个PRP为4KB或者8KB,SGL可以是1KB,2Kb,16KB等。
一般来说,如果当前读写命令的数据大小超过32KB,即选择SGL,小于32Kb就是PRP。
对于SSD来说,如何区分当前IO指令是SGL还是PRP,在nvme command中DW0[15:14],这个位置确定是什么,0即为PRP,1为SGL。
结
下班,哪有什么总结,就俩概念!
原文链接:PRP和SGL 你了解吗?