Skip to content

Commit

Permalink
mpu: Change the disable_mpu API
Browse files Browse the repository at this point in the history
This patch does a few things:
 - Convert the disable_mpu() function to clear_mpu()
 - Make the disable_mpu() function a NOP on ARMv7 and RV32
 - Rename the enable/disable functions to be app specific

Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
  • Loading branch information
alistair23 committed Aug 17, 2020
1 parent f5f0913 commit 128782d
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 19 deletions.
13 changes: 9 additions & 4 deletions arch/cortex-m3/src/mpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,12 @@ impl CortexMRegion {
impl kernel::mpu::MPU for MPU {
type MpuConfig = CortexMConfig;

fn enable_mpu(&self) {
fn clear_mpu(&self) {
let regs = &*self.registers;
regs.ctrl.write(Control::ENABLE::CLEAR);
}

fn enable_app_mpu(&self) {
let regs = &*self.registers;

// Enable the MPU, disable it during HardFault/NMI handlers, and allow
Expand All @@ -372,9 +377,9 @@ impl kernel::mpu::MPU for MPU {
.write(Control::ENABLE::SET + Control::HFNMIENA::CLEAR + Control::PRIVDEFENA::SET);
}

fn disable_mpu(&self) {
let regs = &*self.registers;
regs.ctrl.write(Control::ENABLE::CLEAR);
fn disable_app_mpu(&self) {
// The MPU is not enabled for privileged mode, so we don't have to do
// anything
}

fn number_total_regions(&self) -> usize {
Expand Down
13 changes: 9 additions & 4 deletions arch/rv32i/src/pmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,9 +244,7 @@ impl PMPConfig {
impl kernel::mpu::MPU for PMP {
type MpuConfig = PMPConfig;

fn enable_mpu(&self) {}

fn disable_mpu(&self) {
fn clear_mpu(&self) {
// We want to disable all of the hardware entries, so we use `$x` here,
// and not `$x / 2`.
for x in 0..$x {
Expand Down Expand Up @@ -299,10 +297,17 @@ impl kernel::mpu::MPU for PMP {
csr::CSR.pmpcfg[0].modify(csr::pmpconfig::pmpcfg::w0::SET);
csr::CSR.pmpcfg[0].modify(csr::pmpconfig::pmpcfg::x0::SET);
csr::CSR.pmpcfg[0].modify(csr::pmpconfig::pmpcfg::a0::TOR);
// MPU is not configured for any process now
// PMP is not configured for any process now
self.last_configured_for.take();
}

fn enable_app_mpu(&self) {}

fn disable_app_mpu(&self) {
// PMP is not enabled for machine mode, so we don't have to do
// anything
}

fn number_total_regions(&self) -> usize {
$x / 2
}
Expand Down
2 changes: 1 addition & 1 deletion boards/nano33ble/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ pub unsafe fn reset_handler() {
CHIP = Some(chip);

// Need to disable the MPU because the bootloader seems to set it up.
chip.mpu().disable_mpu();
chip.mpu().clear_mpu();

// Configure the USB stack to enable a serial port over CDC-ACM.
cdc.enable();
Expand Down
25 changes: 17 additions & 8 deletions kernel/src/platform/mpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,20 +93,29 @@ pub trait MPU {
/// current state to help with debugging.
type MpuConfig: Default + Display = MpuConfigDefault;

/// Enables the MPU.
/// Clears the MPU.
///
/// This function will clear any access control enforced by the
/// MPU where possible.
/// On some hardware it is impossible to reset the MPU after it has
/// been locked, in this case this function wont change those regions.
fn clear_mpu(&self) {}

/// Enables the MPU for userspace apps.
///
/// This function must enable the permission restrictions on the various
/// regions protected by the MPU.
fn enable_mpu(&self) {}
fn enable_app_mpu(&self) {}

/// Disables the MPU.
/// Disables the MPU for userspace apps.
///
/// This function must completely disable any access control enforced by the
/// MPU. This will be called before the kernel starts to execute as on some
/// This function must disable any access control that was previously setup
/// for an app if it will interfere with the kernel.
/// This will be called before the kernel starts to execute as on some
/// platforms the MPU rules apply to privileged code as well, and therefore
/// the MPU must be completely disabled for the kernel to effectively manage
/// processes.
fn disable_mpu(&self) {}
/// some of the MPU configuration must be disabled for the kernel to effectively
/// manage processes.
fn disable_app_mpu(&self) {}

/// Returns the maximum number of regions supported by the MPU.
fn number_total_regions(&self) -> usize {
Expand Down
4 changes: 2 additions & 2 deletions kernel/src/sched.rs
Original file line number Diff line number Diff line change
Expand Up @@ -610,11 +610,11 @@ impl Kernel {
// generate an interrupt when the timeslice has expired. The
// underlying timer is not affected.
process.setup_mpu();
chip.mpu().enable_mpu();
chip.mpu().enable_app_mpu();
scheduler_timer.arm();
let context_switch_reason = process.switch_to();
scheduler_timer.disarm();
chip.mpu().disable_mpu();
chip.mpu().disable_app_mpu();

// Now the process has returned back to the kernel. Check
// why and handle the process as appropriate.
Expand Down

0 comments on commit 128782d

Please sign in to comment.