PMP NAPOT Mode Covering the Entire Address Space

845 views
Skip to first unread message

Chongfeng Hu

unread,
Dec 13, 2021, 11:57:56 PM12/13/21
to RISC-V SW Dev
Hi,

I wish to come up with a PMP setting that covers the entire address space in 64 bit.

Per spec:

pmpaddr       pmpcfg.A   Match type and size
yyyy...yyy0   NAPOT      8-byte NAPOT range
yyyy...yy01   NAPOT      16-byte NAPOT range
yyyy...y011   NAPOT      32-byte NAPOT range
. . . . . . . . .
yy01...1111   NAPOT      2^XLEN -byte NAPOT range
y011...1111   NAPOT      2^XLEN+1 -byte NAPOT range
0111...1111   NAPOT      2^XLEN+2 -byte NAPOT range
1111...1111   NAPOT      2^XLEN+3 -byte NAPOT range


Therefore, if I set pmpaddr to be 0111...1111 (totally 54 bits here, and the top 10 bits in the pmpaddr register are hard-wired to 0 per spec), it would cover a range of size 2^56, which is already the max address range supported in Sv39 and Sv48, so this already covers the entire address space.

So, what is the meaning of the last entry (1111...1111)? I found out that Qemu defines the last entry to be reserved. However, the spec still defines the range, in this case to be 2^57, but why supporting a range that's 2X the max address space available?

For software developers, what should be the canonical and blessed pmpaddr setting if they wish to cover the entire address space, 0111...1111 or 1111...1111?

Regards,
Chongfeng

Andrew Waterman

unread,
Dec 14, 2021, 1:14:53 AM12/14/21
to Chongfeng Hu, RISC-V SW Dev
On Mon, Dec 13, 2021 at 8:58 PM Chongfeng Hu <chongf...@gmail.com> wrote:
Hi,

I wish to come up with a PMP setting that covers the entire address space in 64 bit.

Per spec:

pmpaddr       pmpcfg.A   Match type and size
yyyy...yyy0   NAPOT      8-byte NAPOT range
yyyy...yy01   NAPOT      16-byte NAPOT range
yyyy...y011   NAPOT      32-byte NAPOT range
. . . . . . . . .
yy01...1111   NAPOT      2^XLEN -byte NAPOT range
y011...1111   NAPOT      2^XLEN+1 -byte NAPOT range
0111...1111   NAPOT      2^XLEN+2 -byte NAPOT range
1111...1111   NAPOT      2^XLEN+3 -byte NAPOT range


Therefore, if I set pmpaddr to be 0111...1111 (totally 54 bits here, and the top 10 bits in the pmpaddr register are hard-wired to 0 per spec), it would cover a range of size 2^56, which is already the max address range supported in Sv39 and Sv48, so this already covers the entire address space.

So, what is the meaning of the last entry (1111...1111)? I found out that Qemu defines the last entry to be reserved. However, the spec still defines the range, in this case to be 2^57, but why supporting a range that's 2X the max address space available?

People requested that all possible pmpaddr values had defined meanings, rather than any of them having implementation-defined behavior.  So, even if some of these patterns aren't currently useful (because currently a 2^(XLEN+3)-bit address space is impossible), they are well defined.

It sounds like QEMU is not compliant with v1.12 of the privileged architecture in this respect, because the all-ones pattern isn't reserved.


For software developers, what should be the canonical and blessed pmpaddr setting if they wish to cover the entire address space, 0111...1111 or 1111...1111?

There isn't a canonical answer.  These are WARL registers for which the set of legal values depends on the address space supported by the implementation.  Better to program the register with a value that is known to be a legal value.  If you can't do that, then you could try programming the value you suggested, then reading the register back and making sure you find the value acceptable.  (In practice, most implementations will truncate it to a different value that's also one less than a power of two.  You could check for that property, or panic if you don't like what you see.)


Regards,
Chongfeng

--
You received this message because you are subscribed to the Google Groups "RISC-V SW Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sw-dev+un...@groups.riscv.org.
To view this discussion on the web visit https://groups.google.com/a/groups.riscv.org/d/msgid/sw-dev/b50c2a78-b976-4424-b5f9-dd0d47ac744cn%40groups.riscv.org.

Bruce Hoult

unread,
Dec 14, 2021, 1:15:30 AM12/14/21
to Chongfeng Hu, RISC-V SW Dev
I believe all 1s is commonly used. At least it's commonly used by me :-)

>but why supporting a range that's 2X the max address space available?

PMP is completely unrelated to the MMU. You might not even have an MMU. There is nothing but economics preventing someone building a chip with physical memory size matching or exceeding 2^XLEN.

If you do have an MMU, on RV32 you have Sv34, which allows the MMU to cover a physical memory 4x larger than 2^XLEN.

On RV64 at present there is Sv39 and Sv48 which cover a smaller physical memory than 2^XLEN. But in future there could well be an Sv57 and/or Sv66 defined.  And PMP is ready for that.


--

Chongfeng Hu

unread,
Dec 14, 2021, 11:01:50 AM12/14/21
to Bruce Hoult, RISC-V SW Dev

PMP is completely unrelated to the MMU. You might not even have an MMU. There is nothing but economics preventing someone building a chip with physical memory size matching or exceeding 2^XLEN.

If you do have an MMU, on RV32 you have Sv34, which allows the MMU to cover a physical memory 4x larger than 2^XLEN.

On RV64 at present there is Sv39 and Sv48 which cover a smaller physical memory than 2^XLEN. But in future there could well be an Sv57 and/or Sv66 defined.  And PMP is ready for that.


But remember, the pmpaddr register currently has the top 10 bits hard-wired to 0. This is exactly because Sv39 and Sv48 restrict physical addresses to 56 bits. If in the future there's Sv57/Sv66 which covers the whole 64 bit physical address, then the top 10 bits of pmpaddr can be opened up for that. Following the same logic, there will still be a pmpaddr setting (64 bits of straight 1's) that will cover 2X of 2^64, which is still impossible to address.

So yes, pmp is ready for that, but not just by covering 2^57 of physical address in the current spec.

Or did I misunderstand, and you were referring to the same thing?

Regards,
Chongfeng

Chongfeng Hu

unread,
Dec 14, 2021, 11:49:14 AM12/14/21
to Andrew Waterman, RISC-V SW Dev
Thanks Andrew!

If we agree that the last entry is redundant, curious why it was not put to full use in the first place? What I mean is, why wasn't the NAPOT range encoding defined like the following instead:

pmpaddr       pmpcfg.A   Match type and size
yyyy...yyy0   NAPOT      4-byte NAPOT range
yyyy...yy01   NAPOT      8-byte NAPOT range
yyyy...y011   NAPOT      16-byte NAPOT range

. . . . . . . . .
yy01...1111   NAPOT      2^XLEN-1 -byte NAPOT range
y011...1111   NAPOT      2^XLEN -byte NAPOT range
0111...1111   NAPOT      2^XLEN+1 -byte NAPOT range
1111...1111   NAPOT      2^XLEN+2 -byte NAPOT range

Namely, shift the "Match type and size" column down by one row? Then, all of the pmpaddr settings in NAPOT mode have full meaning, there's no redundant/wasted entries, and also we no long need the special NA4 mode to cover the four-byte regions (because it's now covered by the first entry in NAPOT mode above), thereby saving one encoding for future use (pmpcfg.A = 2)?

Regards,
Chongfeng

Chongfeng Hu

unread,
Dec 14, 2021, 12:01:01 PM12/14/21
to Andrew Waterman, RISC-V SW Dev
Ah, I realize why it is. Taking a look at the 2nd last entry for example, 0111...1111, if it were defined to represent a range of 2^XLEN+1, on 64 bit it would cover 2^55, half the entire space, so there needs to be a free bit available in pmpaddr to allow selecting the lower/higher half of the entire memory, but the encoding left no free bit to do so.

The current encoding scheme does take this into consideration I believe.

Richard Herveille

unread,
Dec 14, 2021, 3:35:08 PM12/14/21
to Chongfeng Hu, Andrew Waterman, RISC-V SW Dev
I never really understood why the choice was made to use the ‘111…111’ nomenclature, instead of an integer. Meaning instead of 30 1s, just write ‘30’ to the register 

Richard

On 14 Dec 2021, at 18:01, Chongfeng Hu <chongf...@gmail.com> wrote:



Chongfeng Hu

unread,
Dec 14, 2021, 3:43:06 PM12/14/21
to Richard Herveille, Andrew Waterman, RISC-V SW Dev
Richard,

Because the pmpaddr register serves 2 purposes: it packs both the range (which in your example was 30), *and* also the base physical address of the range. The "yyyy" notion in the NAPOT pmpaddr allows you to specify the base of the range.

For example, if your pmpaddr is set to binary 00 in NAPOT mode, then your range is [0x0, 0x7]; if it's set to binary 10, then it selects the range [0x8, 0xF], and so on, even though their range size are all 8 bytes long.

Regards,
Chongfeng
Reply all
Reply to author
Forward
0 new messages