diff options
author | Yicheng Li <yichengli@chromium.org> | 2020-05-21 17:29:12 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-05-29 20:53:52 +0000 |
commit | 8f91341cdec812ec51da3915df27f1db2c34509c (patch) | |
tree | 69dc6f542d55393e928e99d44ee5d364f8bba348 /core | |
parent | c4734d29ea83d2be54fe189e6cbeb360fa266fb7 (diff) | |
download | chrome-ec-8f91341cdec812ec51da3915df27f1db2c34509c.tar.gz |
cortex-m: Lock RW flash using aligned MPU regions
On Cortex-M3, Cortex-M4, and Cortex-M7, the base address used for
an MPU region must be aligned to the size of the region:
https://developer.arm.com/docs/dui0553/a/cortex-m4-peripherals/optional-memory-protection-unit/mpu-region-base-address-register
https://developer.arm.com/docs/dui0552/a/cortex-m3-peripherals/optional-memory-protection-unit/mpu-region-base-address-register
https://developer.arm.com/docs/dui0646/a/cortex-m7-peripherals/optional-memory-protection-unit/mpu-region-base-address-register#BABDAHJG
Try to represent RW flash using aligned MPU regions before configuring
MPU. Otherwise configuring MPU will fail.
BRANCH=none
BUG=b:155410753
TEST=triggered mpu_lock_rw_flash() on bloonchipper and dartmonkey
and checked that configuring MPU succeeded.
TEST=on bloonchipper and dartmonkey, verified that the MPU
configurations make sense by adding logging.
Change-Id: Ib460354ea60e96d7b6ac4a4c12730b0db7c6aaac
Signed-off-by: Yicheng Li <yichengli@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2213132
Reviewed-by: Jett Rink <jettrink@chromium.org>
Diffstat (limited to 'core')
-rw-r--r-- | core/cortex-m/mpu.c | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/core/cortex-m/mpu.c b/core/cortex-m/mpu.c index e2a2a464e1..32ce6fe5ef 100644 --- a/core/cortex-m/mpu.c +++ b/core/cortex-m/mpu.c @@ -251,11 +251,33 @@ int mpu_lock_ro_flash(void) int mpu_lock_rw_flash(void) { /* Prevent execution from internal mapped RW flash */ - return mpu_config_region(REGION_STORAGE, - CONFIG_MAPPED_STORAGE_BASE + CONFIG_RW_MEM_OFF, - CONFIG_RW_SIZE, - MPU_ATTR_XN | MPU_ATTR_RW_RW | - MPU_ATTR_FLASH_MEMORY, 1); + const uint16_t mpu_attr = MPU_ATTR_XN | MPU_ATTR_RW_RW | + MPU_ATTR_FLASH_MEMORY; + const uint32_t rw_start_address = + CONFIG_MAPPED_STORAGE_BASE + CONFIG_RW_MEM_OFF; + + /* + * Least significant set bit of the address determines the max size of + * the region because on the Cortex-M3, Cortex-M4 and Cortex-M7, the + * address used for an MPU region must be aligned to the size. + */ + const int aligned_size_bit = + __fls(rw_start_address & -rw_start_address); + const uint32_t first_region_size = + MIN(BIT(aligned_size_bit), CONFIG_RW_SIZE); + const uint32_t second_region_address = + rw_start_address + first_region_size; + const uint32_t second_region_size = CONFIG_RW_SIZE - first_region_size; + int rv; + + rv = mpu_config_region(REGION_STORAGE, rw_start_address, + first_region_size, mpu_attr, 1); + if ((rv != EC_SUCCESS) || (second_region_size == 0)) + return rv; + + /* If this fails then it's impossible to represent with two regions. */ + return mpu_config_region(REGION_STORAGE2, second_region_address, + second_region_size, mpu_attr, 1); } #endif /* !CONFIG_EXTERNAL_STORAGE */ |