Hello,
maybe it is a bit off-topic but I would appreciate some clarification regarding the NVMe PRP format. Here is an example.
Let’s say, we have a S/G list with following physical segments:
- ph.addr: 0x20100, len: 0x0300
- ph.addr: 0x30100, len: 0x0F00
- ph.addr: 0x31000, len: 0x1000
- ph.addr: 0x32000, len: 0x0400
- ph.addr: 0x40100, len: 0x0F00
- ph.addr: 0x41000, len: 0x0B00
(I already cut them down to pages, page is 0x1000)
In such case a common S/G list is tirivial:
0x20100, 0x0300
0x30100, 0x2300
0x40100, 0x1A00
(total I/O is obviously 0x4000).
The space for the PRP list is allocated starting at the physical address 0x800000.
To my understanding in order to describe such S/G list in PRP terms we need to have surprisingly large allocation because it has to be “linked”.
I.e. at the address 0x800000 we would have something like:
0x0000 0000 2000 0100 <– the page address + offset
0x0000 0008 0000 1000 <– next list starts at this physical
Than the thing continues at 0x801000 with something like
0x0000 0000 3000 0100 <– the address + offset
0x0000 0000 3100 0000 <– the address + offset
0x0000 0000 3200 0000 <– the address + offset
0x0000 0008 0000 2000 <– next list starts at this physical
Than the thing continues at 0x802000 with something like
0x0000 0000 4000 0100 <– the address + offset
0x0000 0000 4100 0000 <– the address + offset
Altogether we consume three pages. Or maybe I completely misunderstand?
If that’s the case, the PRP way could be fast for the hardware - but somewhat tedious to construct and quite space-consuming.
Thanks!