-
-
Notifications
You must be signed in to change notification settings - Fork 771
OpenTitan: Enable PMP for kernel regions #2422
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
0f59f3c
to
f5b4cdd
Compare
f5b4cdd
to
c9ba6cd
Compare
// This is PMP support for kernel regions | ||
// PMP does not allow a deny by default option, so all regions not marked | ||
// with the below commands will have full access. | ||
// This is still a useful implementation as it can be used to limit the | ||
// kernels access, for example removing execute permission from regions | ||
// we don't need to execute from and removing write permissions from | ||
// executable reions. | ||
let mut mpu_config = rv32i::pmp::PMPConfig::default(); | ||
// The kernel stack | ||
chip.pmp | ||
.allocate_kernel_region( | ||
&_sstack as *const u8, | ||
&_estack as *const u8 as usize - &_sstack as *const u8 as usize, | ||
mpu::Permissions::ReadWriteOnly, | ||
&mut mpu_config, | ||
) | ||
.unwrap(); | ||
// The kernel text | ||
chip.pmp | ||
.allocate_kernel_region( | ||
&_stext as *const u8, | ||
&_etext as *const u8 as usize - &_stext as *const u8 as usize, | ||
mpu::Permissions::ReadExecuteOnly, | ||
&mut mpu_config, | ||
) | ||
.unwrap(); | ||
// The kernel relocate data | ||
chip.pmp | ||
.allocate_kernel_region( | ||
&_srelocate as *const u8, | ||
&_erelocate as *const u8 as usize - &_srelocate as *const u8 as usize, | ||
mpu::Permissions::ReadWriteOnly, | ||
&mut mpu_config, | ||
) | ||
.unwrap(); | ||
// The kernel BSS | ||
chip.pmp | ||
.allocate_kernel_region( | ||
&_szero as *const u8, | ||
&_ezero as *const u8 as usize - &_szero as *const u8 as usize, | ||
mpu::Permissions::ReadWriteOnly, | ||
&mut mpu_config, | ||
) | ||
.unwrap(); | ||
|
||
chip.pmp.enable_kernel_mpu(&mut mpu_config); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not put all of this in chips/earlgrey? Our chips already (historically) use the linker symbols, but they could also just be passed in to a function. But configuring the PMP seems like a reasonable chip-level operation, and a different board implementation might want to use the exact same code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good question. It doesn't really matter too much.
I feel that it fits in boards/
as that is where other similar operations are. For example the stack size is allocated in boards, so I feel that stack protection should also be in boards.
We also only want to enable this after debug is setup (in case something goes wrong), so it makes sense in boards.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The board can still call it, and decide when (or if) to call it, just the code would exist in a more central location.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can, but the board will still end up calling it so I don't think we would really save anything.
The HIL for allocate_kernel_region()
also says: "It is expected that this function is called in reset_handler()
."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have bad memories of duplicated code in main.rs, that's all. Components helped a lot, but I'm wary of setting things up so that code will get copied, and then changes require updating all RISC-V boards (which I do not recommend :)).
This is also similar to load_processes, which is only stored in process.rs for convenience, but is most definitely a board-level function/task. It's just copying it to every main.rs wasn't scalable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would still required changes in all RISC-V if it's in chips.
I still think here is a good place. Maybe arch would work though, then it can just be called from all the boards.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally, this would not even be architecture specific, and tock could by default limit access on all platforms in the same way that this does for OT. But I think it is fine to leave it here for now and worry about code duplication once it actually exists.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, just a question about /boards vs. /chips.
// This is PMP support for kernel regions | ||
// PMP does not allow a deny by default option, so all regions not marked | ||
// with the below commands will have full access. | ||
// This is still a useful implementation as it can be used to limit the | ||
// kernels access, for example removing execute permission from regions | ||
// we don't need to execute from and removing write permissions from | ||
// executable reions. | ||
let mut mpu_config = rv32i::pmp::PMPConfig::default(); | ||
// The kernel stack | ||
chip.pmp | ||
.allocate_kernel_region( | ||
&_sstack as *const u8, | ||
&_estack as *const u8 as usize - &_sstack as *const u8 as usize, | ||
mpu::Permissions::ReadWriteOnly, | ||
&mut mpu_config, | ||
) | ||
.unwrap(); | ||
// The kernel text | ||
chip.pmp | ||
.allocate_kernel_region( | ||
&_stext as *const u8, | ||
&_etext as *const u8 as usize - &_stext as *const u8 as usize, | ||
mpu::Permissions::ReadExecuteOnly, | ||
&mut mpu_config, | ||
) | ||
.unwrap(); | ||
// The kernel relocate data | ||
chip.pmp | ||
.allocate_kernel_region( | ||
&_srelocate as *const u8, | ||
&_erelocate as *const u8 as usize - &_srelocate as *const u8 as usize, | ||
mpu::Permissions::ReadWriteOnly, | ||
&mut mpu_config, | ||
) | ||
.unwrap(); | ||
// The kernel BSS | ||
chip.pmp | ||
.allocate_kernel_region( | ||
&_szero as *const u8, | ||
&_ezero as *const u8 as usize - &_szero as *const u8 as usize, | ||
mpu::Permissions::ReadWriteOnly, | ||
&mut mpu_config, | ||
) | ||
.unwrap(); | ||
|
||
chip.pmp.enable_kernel_mpu(&mut mpu_config); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally, this would not even be architecture specific, and tock could by default limit access on all platforms in the same way that this does for OT. But I think it is fine to leave it here for now and worry about code duplication once it actually exists.
Signed-off-by: Alistair Francis <[email protected]>
c9ba6cd
to
8440dbf
Compare
Signed-off-by: Alistair Francis <[email protected]>
8440dbf
to
d902dee
Compare
Ok, all updated! |
bors r+ |
2422: OpenTitan: Enable PMP for kernel regions r=bradjc a=alistair23 ### Pull Request Overview This PR applies on top of tock#2420 This PR adds support for marking regions of the kernel as protected by PMP. This allows some regions to have reduced permissions applied to them. This can be used to restrict write/execute to different regions used by the kernel. ### Testing Strategy Boot Tock and an app on OpenTitan FPGA and QEMU. ### TODO or Help Wanted ### Documentation Updated - [X] Updated the relevant files in `/docs`, or no updates are required. ### Formatting - [X] Ran `make prepush`. Co-authored-by: Alistair Francis <[email protected]>
Pull Request Overview
This PR applies on top of #2420
This PR adds support for marking regions of the kernel as protected by PMP.
This allows some regions to have reduced permissions applied to them. This can be used to restrict write/execute to different regions used by the kernel.
Testing Strategy
Boot Tock and an app on OpenTitan FPGA and QEMU.
TODO or Help Wanted
Documentation Updated
/docs
, or no updates are required.Formatting
make prepush
.