From 0f5b9eaf947e2ff9ef6472647800c7faa770662a Mon Sep 17 00:00:00 2001 From: Russ Butler Date: Fri, 5 Oct 2018 18:45:11 -0500 Subject: [PATCH] Add an initial MPU API Add a minimalistic HAL MPU API with the ability to prevent execution in ram. --- hal/mbed_mpu_api.c | 149 +++++++++++++++++++++++++++++++++++++++++++++ hal/mpu_api.h | 80 ++++++++++++++++++++++++ 2 files changed, 229 insertions(+) create mode 100644 hal/mbed_mpu_api.c create mode 100644 hal/mpu_api.h diff --git a/hal/mbed_mpu_api.c b/hal/mbed_mpu_api.c new file mode 100644 index 0000000000..765b6d6b85 --- /dev/null +++ b/hal/mbed_mpu_api.c @@ -0,0 +1,149 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "hal/mpu_api.h" +#include "cmsis.h" + +void mbed_mpu_init() +{ + mbed_mpu_enable_ram_xn(false); +} + +void mbed_mpu_free() +{ + mbed_mpu_enable_ram_xn(false); +} + +void mbed_mpu_enable_ram_xn(bool enable) +{ +#if MBED_MPU_ENABLED + // Flush memory writes before configuring the MPU. + __DSB(); + + const uint32_t regions = (MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos; + + // Disable the MCU + MPU->CTRL = 0; + + // Reset all mapping + for (uint32_t i = 0; i < regions; i++) { + ARM_MPU_ClrRegion(i); + } + + if (!enable) { + return; + } + + /* + * ARMv6m and ARMv7m memory map: + * + * Start End Name Executable by default Mbed MPU protection + * 0x00000000 - 0x1FFFFFFF Code Yes Execute disabled for second half + * 0x20000000 - 0x3FFFFFFF SRAM Yes Execute disabled + * 0x40000000 - 0x5FFFFFFF Peripheral No + * 0x60000000 - 0x7FFFFFFF RAM Yes Execute disabled + * 0x80000000 - 0x9FFFFFFF RAM Yes Execute disabled + * 0xA0000000 - 0xBFFFFFFF Device No + * 0xC0000000 - 0xDFFFFFFF Device No + * 0xE0000000 - 0xFFFFFFFF System No + */ + + if (regions >= 3) { + // Select region 0 and used it for the WT rom region + // - RAM 0x10000000 - 0x1FFFFFFF + MPU->RNR = 0; + // Set address to 0 + MPU->RBAR = 0; + // Configure and enable region + MPU->RASR = + MPU_RASR_ENABLE_Msk | + ARM_MPU_RASR( + 1, // DisableExec + ARM_MPU_AP_FULL, // AccessPermission + 0, // TypeExtField + 0, // IsShareable + 1, // IsCacheable + 0, // IsBufferable + // SubRegionDisable + (1 << 0) | // Disable Sub-region + (1 << 1) | // Disable Sub-region + (1 << 2) | // Disable Sub-region + (1 << 3) | // Disable Sub-region + (0 << 4) | // Enable Sub-region RAM 0x10000000 - 0x1FFFFFFF + (0 << 5) | + (0 << 6) | + (0 << 7), + ARM_MPU_REGION_SIZE_512MB // Size + ); + + // Select region 1 and used it for WBWA ram regions + // - SRAM 0x20000000 - 0x3FFFFFFF + // - RAM 0x60000000 - 0x7FFFFFFF + MPU->RNR = 1; + // Set address to 0 + MPU->RBAR = 0; + // Configure and enable region + MPU->RASR = + MPU_RASR_ENABLE_Msk | + ARM_MPU_RASR( + 1, // DisableExec + ARM_MPU_AP_FULL, // AccessPermission + 1, // TypeExtField + 0, // IsShareable + 1, // IsCacheable + 1, // IsBufferable + // SubRegionDisable + (1 << 0) | // Disable Sub-region + (0 << 1) | // Enable Sub-region SRAM 0x20000000 - 0x3FFFFFFF + (1 << 2) | // Disable Sub-region + (0 << 3) | // Enable Sub-region RAM 0x60000000 - 0x7FFFFFFF + (1 << 4) | // Disable Sub-region + (1 << 5) | // Disable Sub-region + (1 << 6) | // Disable Sub-region + (1 << 7), // Disable Sub-region + ARM_MPU_REGION_SIZE_4GB // Size + ); + + // Select region 2 and used it for the WT ram region + // - RAM RAM 0x80000000 - 0x9FFFFFFF + MPU->RNR = 2; + // Set address + MPU->RBAR = 0x80000000; + // Configure and enable region + MPU->RASR = + MPU_RASR_ENABLE_Msk | + ARM_MPU_RASR( + 1, // DisableExec + ARM_MPU_AP_FULL, // AccessPermission + 0, // TypeExtField + 0, // IsShareable + 1, // IsCacheable + 0, // IsBufferable + ~0U, // SubRegionDisable + ARM_MPU_REGION_SIZE_512MB // Size + ); + } + + // Enable the MPU + MPU->CTRL = + (1 << MPU_CTRL_PRIVDEFENA_Pos) | // Use the default memory map for unmapped addresses + (1 << MPU_CTRL_HFNMIENA_Pos) | // Keep MPU turned on for faults + (1 << MPU_CTRL_ENABLE_Pos); // Enable MPU + + // Ensure changes take effect + __ISB(); + __DSB(); +#endif +} diff --git a/hal/mpu_api.h b/hal/mpu_api.h new file mode 100644 index 0000000000..dfdc6e4ce4 --- /dev/null +++ b/hal/mpu_api.h @@ -0,0 +1,80 @@ + +/** \addtogroup hal */ +/** @{*/ +/* mbed Microcontroller Library + * Copyright (c) 2018-2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBED_MPU_API_H +#define MBED_MPU_API_H + +#include +#include "cmsis.h" + +#ifndef MBED_MPU_ENABLED + +#if ((__ARM_ARCH_7M__ == 1U) || \ + (__ARM_ARCH_7EM__ == 1U) || \ + (__ARM_ARCH_6M__ == 1U)) +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +#define MBED_MPU_ENABLED 1U +#else +#define MBED_MPU_ENABLED 0U +#endif +#elif ((__ARM_ARCH_7A__ == 1U) || \ + (__ARM_ARCH_8M_BASE__ == 1U) || \ + (__ARM_ARCH_8M_MAIN__ == 1U)) +#define MBED_MPU_ENABLED 0U +#else +#error "Unknown architecture for MPU" +#endif + +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Initialize the MPU + * + * Initialize or re-initialize the memory protection unit. + * It is implementation defined what region are protected + * by the MPU after initialization. + */ +void mbed_mpu_init(void); + +/** + * Enable or disable ram MPU protection + * + * This function is used to mark all of RAM as execute never. + * When enabled code is only allowed to execute from flash. + * + * @param enable true to disable execution in ram, false otherwise + */ +void mbed_mpu_enable_ram_xn(bool enable); + +/** Deinitialize the MPU + * + * Powerdown the MPU in preparation for powerdown, reset or jumping to another application. + */ +void mbed_mpu_free(void); + +#ifdef __cplusplus +} +#endif + +#endif + +/** @}*/