I’m trying to program the PMP address registers and I can’t write any value in the ram space. I believe it extends from 0x8000_0000 to 0x8000_3FFF. If I try to write 0x8000_1000 to the address then read the contents, it only shows up as 0x1000. Can the RAM not be protected by PMP?
EDIT
Reading some more content, I believe I am misunderstanding how the addressing range works. Still don’t under stand it yet though.
You’re trying to use pmpaddr1 to encode a NAPOT range from 0x80003920 to 0x80003C20?
That is size 0x300 which is not a POT (Power Of Two) so NAPOT can not be used.
0x20000EA7 is
0010 0000 0000 0000 0000 1110 1010 0111
Which makes the first 0 bit from the right bit 3, so this value encodes a region of size 2^(3+3) = 64 = 0x40 bytes, at address
1000 0000 0000 0000 0011 1010 1000 0000
i.e. 0x800003c80 to (0x800003c80 + 0x40) = 0x800003cc0
The calculation in the previous message for NAPOT range 0x8000_0000 to 0x8000_4000 is correct.
Note that pmpaddr0 equal to 0x20040000 as a TOR is enabling RWX for all addresses from 0x0 to 0x80100000. Any address in this range will match this entry and succeed, so in particular if later entries cover your desired range 0x80003920 to 0x80003C20 those entries will never be used.
I misunderstood how TOR works, I thought you put the actual address in. Now I see that that value is also bit-shifted. Yeah, after I posted I realized my mistake on the NAPOT not being a power of two size. This makes it much clearer. Thanks
I’m trying to protect my u-mode application’s stack frame from overflow. It is working sort of. I initialize an array of size “x” bytes to zeros. I set the stack pointer to the address of the top of the array etc, then mret. pmpaddr1 is set to the address of the bottom of the stack frame, and pmpaddr2 is top of stack fram, both TOR.
_____ <- 0x80003fff Top of RAM
| |
| | <- 0x80003ED8 MTVAL after StoreFault Trap
| |
| | <- 0x80003CD0 Top of array for u-mode stack frame, sp set here on MRET and pmpaddr2 (TOR)
| |
| | <- 0x80003AD0 Bottom of array for u-mode stack frame and pmpaddr1
|_____|
When User mode is entered and I begin calling functions, a store fault is incurred. Why is the stack pointer higher than it is when I manually set it? Shouldn’t the stack grow from higher addresses to lower ones? My array for testing was 512 bytes, the difference between the stack pointer and the mtval was 520 bytes. If I change the array size, the difference is always the array size plus 8 bytes. What am I not understanding?
I think I figured it out anyways.
Following the SiFive user-mode-example on github, they create a stack frame for user mode to use before they drop privilege.
1. create array with 16 byte alignment and initialize with zeros
2. determine the address of the end of the array (my_stack + sizeof(my_stack) in C)
3. setup mstatus appropriately
4. set the stack pointer to the address calculated in #2
5. MRET
Before I MRET into user mode, I added pmp configurations to encapsulate the user stack frame to prevent stack overflows. However, I was never able to enter user mode because it always trapped with a StoreFault. Reading the stack pointer showed that it was outside of the user stack frame by a lot.
It turns out, that when I was setting the stack pointer before the MRET, I was using &stack_ptr instead of just stack_ptr. This fixes my problem, I probably should have posted some code before, but it is Rust code so I wan’t sure. A lot of my issues I encounter are borderline between Rust and RISC-V which makes it hard to know which forum to post my question on, plus I’m new to embedded development in general.