summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/cortex-m/include/mpu.h8
-rw-r--r--core/cortex-m/include/mpu_private.h1
-rw-r--r--core/cortex-m/mpu.c45
-rw-r--r--test/mpu.c23
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);