diff options
-rw-r--r-- | core/cortex-m/include/mpu.h | 8 | ||||
-rw-r--r-- | core/cortex-m/include/mpu_private.h | 1 | ||||
-rw-r--r-- | core/cortex-m/mpu.c | 45 | ||||
-rw-r--r-- | test/mpu.c | 23 |
4 files changed, 59 insertions, 18 deletions
diff --git a/core/cortex-m/include/mpu.h b/core/cortex-m/include/mpu.h index 81aefa6a75..610728b501 100644 --- a/core/cortex-m/include/mpu.h +++ b/core/cortex-m/include/mpu.h @@ -86,6 +86,14 @@ enum mpu_region { #define MPU_ATTR_FLASH_MEMORY 2 /* for flash memory */ #endif +/* Represent RW with at most 2 MPU regions. */ +#define MAX_RW_REGIONS 2 +struct mpu_rw_regions { + int num_regions; + uint32_t addr[MAX_RW_REGIONS]; + uint32_t size[MAX_RW_REGIONS]; +}; + /** * Enable MPU */ diff --git a/core/cortex-m/include/mpu_private.h b/core/cortex-m/include/mpu_private.h index 3e52b35c76..e6030114c2 100644 --- a/core/cortex-m/include/mpu_private.h +++ b/core/cortex-m/include/mpu_private.h @@ -20,5 +20,6 @@ int mpu_update_region(uint8_t region, uint32_t addr, uint8_t size_bit, uint16_t attr, uint8_t enable, uint8_t srd); int mpu_config_region(uint8_t region, uint32_t addr, uint32_t size, uint16_t attr, uint8_t enable); +struct mpu_rw_regions mpu_get_rw_regions(void); #endif /* __CROS_EC_MPU_PRIVATE_H */ diff --git a/core/cortex-m/mpu.c b/core/cortex-m/mpu.c index 0663ac72d9..d1db27d78e 100644 --- a/core/cortex-m/mpu.c +++ b/core/cortex-m/mpu.c @@ -248,36 +248,45 @@ int mpu_lock_ro_flash(void) MPU_ATTR_FLASH_MEMORY, 1); } -int mpu_lock_rw_flash(void) +/* Represent RW with at most 2 MPU regions. */ +struct mpu_rw_regions mpu_get_rw_regions(void) { - /* Prevent execution from internal mapped RW flash */ - 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; + int aligned_size_bit; + struct mpu_rw_regions regions = {}; + + regions.addr[0] = 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; + aligned_size_bit = + __fls(regions.addr[0] & -regions.addr[0]); + regions.size[0] = MIN(BIT(aligned_size_bit), CONFIG_RW_SIZE); + regions.addr[1] = regions.addr[0] + regions.size[0]; + regions.size[1] = CONFIG_RW_SIZE - regions.size[0]; + regions.num_regions = (regions.size[1] == 0) ? 1 : 2; + + return regions; +} + +int mpu_lock_rw_flash(void) +{ + /* Prevent execution from internal mapped RW flash */ + const uint16_t mpu_attr = MPU_ATTR_XN | MPU_ATTR_RW_RW | + MPU_ATTR_FLASH_MEMORY; + const struct mpu_rw_regions regions = mpu_get_rw_regions(); 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)) + rv = mpu_config_region(REGION_STORAGE, regions.addr[0], regions.size[0], + mpu_attr, 1); + if ((rv != EC_SUCCESS) || (regions.num_regions == 1)) 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); + return mpu_config_region(REGION_STORAGE2, regions.addr[1], + regions.size[1], mpu_attr, 1); } #endif /* !CONFIG_EXTERNAL_STORAGE */ diff --git a/test/mpu.c b/test/mpu.c index b8c881364d..5675633087 100644 --- a/test/mpu.c +++ b/test/mpu.c @@ -6,6 +6,7 @@ #include <stdbool.h> #include "mpu.h" #include "mpu_private.h" +#include "string.h" #include "system.h" #include "test_util.h" @@ -21,12 +22,22 @@ struct mpu_info mpu_info = { .num_mpu_regions = 8, .mpu_is_unified = true }; + +struct mpu_rw_regions expected_rw_regions = { .num_regions = 2, + .addr = { 0x08060000, + 0x08080000 }, + .size = { 0x20000, 0x80000 } }; #elif defined(CHIP_VARIANT_STM32H7X3) struct mpu_info mpu_info = { .has_mpu = true, .num_mpu_regions = 16, .mpu_is_unified = true }; + +struct mpu_rw_regions expected_rw_regions = { .num_regions = 1, + .addr = { 0x08100000, + 0x08200000 }, + .size = { 0x100000, 0 } }; #else #error "MPU info not defined for this chip. Please add it." #endif @@ -155,6 +166,16 @@ test_static int test_mpu_protect_code_ram(void) return EC_SUCCESS; } +test_static int test_mpu_get_rw_regions(void) +{ + struct mpu_rw_regions rw_regions = mpu_get_rw_regions(); + int rv = memcmp(&rw_regions, &expected_rw_regions, + sizeof(expected_rw_regions)); + + TEST_EQ(rv, 0, "%d"); + return EC_SUCCESS; +} + void run_test(void) { enum ec_image cur_image = system_get_image_copy(); @@ -192,6 +213,8 @@ void run_test(void) RUN_TEST(reset_mpu); RUN_TEST(test_mpu_protect_data_ram); RUN_TEST(reset_mpu); + RUN_TEST(test_mpu_get_rw_regions); + RUN_TEST(reset_mpu); /* This test must be last because it generates a panic */ RUN_TEST(test_mpu_update_region_valid_region); RUN_TEST(reset_mpu); |