| From eb096e4c03b80f9f31e5d15ca06e5a38e4112664 Mon Sep 17 00:00:00 2001 |
| From: Bence Balogh <bence.balogh@arm.com> |
| Date: Tue, 7 Nov 2023 20:25:49 +0100 |
| Subject: [PATCH 1/2] platform: corstone1000: Update MPU configuration |
| |
| In Armv6-M the MPU requires the regions to be aligned with |
| region sizes. |
| The commit aligns the different code/data sections using the |
| alignment macros. The code/data sections can be covered by |
| multiple MPU regions in order to save memory. |
| |
| Small adjustments had to be made in the memory layout in order to |
| not overflow the flash: |
| - Decreased TFM_PARTITION_SIZE |
| - Increased S_UNPRIV_DATA_SIZE |
| |
| Added checks to the MPU configuration function for checking the |
| MPU constraints: |
| - Base address has to be aligned to the size |
| - The minimum MPU region size is 0x100 |
| - The MPU can have 8 regions at most |
| |
| Change-Id: I059468e8aba0822bb354fd1cd4987ac2bb1f34d1 |
| Signed-off-by: Bence Balogh <bence.balogh@arm.com> |
| Upstream-Status: Submitted [https://review.trustedfirmware.org/c/TF-M/trusted-firmware-m/+/25393] |
| |
| --- |
| .../target/arm/corstone1000/CMakeLists.txt | 19 +++++ |
| .../arm/corstone1000/create-flash-image.sh | 8 +- |
| .../arm/corstone1000/partition/flash_layout.h | 2 +- |
| .../arm/corstone1000/partition/region_defs.h | 6 +- |
| .../arm/corstone1000/tfm_hal_isolation.c | 83 +++++++++++++++---- |
| 5 files changed, 93 insertions(+), 25 deletions(-) |
| |
| diff --git a/platform/ext/target/arm/corstone1000/CMakeLists.txt b/platform/ext/target/arm/corstone1000/CMakeLists.txt |
| index e6cf15b11..8817f514c 100644 |
| --- a/platform/ext/target/arm/corstone1000/CMakeLists.txt |
| +++ b/platform/ext/target/arm/corstone1000/CMakeLists.txt |
| @@ -22,6 +22,25 @@ target_compile_definitions(platform_region_defs |
| INTERFACE |
| $<$<BOOL:${TFM_S_REG_TEST}>:TFM_S_REG_TEST> |
| ) |
| + |
| +# The Armv6-M MPU requires that the MPU regions be aligned to the region sizes. |
| +# The minimal region size is 0x100 bytes. |
| +# |
| +# The alignments have to be a power of two and ideally bigger than the section size (which |
| +# can be checked in the map file). |
| +# In some cases the alignment value is smaller than the actual section |
| +# size to save memory. In that case, multiple MPU region has to be configured to cover it. |
| +# |
| +# To save memory, the attributes are set to XN_EXEC_OK and AP_RO_PRIV_UNPRIV for |
| +# the SRAM so the PSA_ROT_LINKER_CODE, TFM_UNPRIV_CODE and APP_ROT_LINKER_CODE don't have to |
| +# be aligned. The higher-priority regions will overwrite these attributes if needed. |
| +# The RAM is also located in the SRAM so it has to be configured to overwrite these default |
| +# attributes. |
| +target_compile_definitions(platform_region_defs |
| + INTERFACE |
| + TFM_LINKER_APP_ROT_LINKER_DATA_ALIGNMENT=0x2000 |
| + TFM_LINKER_SP_META_PTR_ALIGNMENT=0x100 |
| +) |
| #========================= Platform common defs ===============================# |
| |
| # Specify the location of platform specific build dependencies. |
| diff --git a/platform/ext/target/arm/corstone1000/create-flash-image.sh b/platform/ext/target/arm/corstone1000/create-flash-image.sh |
| index 2522d3674..a6be61384 100755 |
| --- a/platform/ext/target/arm/corstone1000/create-flash-image.sh |
| +++ b/platform/ext/target/arm/corstone1000/create-flash-image.sh |
| @@ -8,7 +8,7 @@ |
| |
| ###################################################################### |
| # This script is to create a flash gpt image for corstone platform |
| -# |
| +# |
| # Flash image layout: |
| # |------------------------------| |
| # | Protective MBR | |
| @@ -82,15 +82,15 @@ sgdisk --mbrtogpt \ |
| --new=4:56:+4K --typecode=4:$PRIVATE_METADATA_TYPE_UUID --partition-guid=4:$(uuidgen) --change-name=4:'private_metadata_replica_1' \ |
| --new=5:64:+4k --typecode=5:$PRIVATE_METADATA_TYPE_UUID --partition-guid=5:$(uuidgen) --change-name=5:'private_metadata_replica_2' \ |
| --new=6:72:+100k --typecode=6:$SE_BL2_TYPE_UUID --partition-guid=6:$(uuidgen) --change-name=6:'bl2_primary' \ |
| - --new=7:272:+376K --typecode=7:$TFM_TYPE_UUID --partition-guid=7:$(uuidgen) --change-name=7:'tfm_primary' \ |
| + --new=7:272:+368K --typecode=7:$TFM_TYPE_UUID --partition-guid=7:$(uuidgen) --change-name=7:'tfm_primary' \ |
| --new=8:32784:+100k --typecode=8:$SE_BL2_TYPE_UUID --partition-guid=8:$(uuidgen) --change-name=8:'bl2_secondary' \ |
| - --new=9:32984:+376K --typecode=9:$TFM_TYPE_UUID --partition-guid=9:$(uuidgen) --change-name=9:'tfm_secondary' \ |
| + --new=9:32984:+368K --typecode=9:$TFM_TYPE_UUID --partition-guid=9:$(uuidgen) --change-name=9:'tfm_secondary' \ |
| --new=10:65496:65501 --partition-guid=10:$(uuidgen) --change-name=10:'reserved_2' \ |
| $IMAGE |
| |
| [ $? -ne 0 ] && echo "Error occurs while writing the GPT layout" && exit 1 |
| |
| -# Write partitions |
| +# Write partitions |
| # conv=notrunc avoids truncation to keep the geometry of the image. |
| dd if=$BIN_DIR/bl2_signed.bin of=${IMAGE} seek=72 conv=notrunc |
| dd if=$BIN_DIR/tfm_s_signed.bin of=${IMAGE} seek=272 conv=notrunc |
| diff --git a/platform/ext/target/arm/corstone1000/partition/flash_layout.h b/platform/ext/target/arm/corstone1000/partition/flash_layout.h |
| index 568c8de28..7fffd94c6 100644 |
| --- a/platform/ext/target/arm/corstone1000/partition/flash_layout.h |
| +++ b/platform/ext/target/arm/corstone1000/partition/flash_layout.h |
| @@ -134,7 +134,7 @@ |
| |
| /* Bank configurations */ |
| #define BANK_PARTITION_SIZE (0xFE0000) /* 15.875 MB */ |
| -#define TFM_PARTITION_SIZE (0x5E000) /* 376 KB */ |
| +#define TFM_PARTITION_SIZE (0x5C000) /* 368 KB */ |
| |
| /************************************************************/ |
| /* Bank : Images flash offsets are with respect to the bank */ |
| diff --git a/platform/ext/target/arm/corstone1000/partition/region_defs.h b/platform/ext/target/arm/corstone1000/partition/region_defs.h |
| index 99e822f51..64ab786e5 100644 |
| --- a/platform/ext/target/arm/corstone1000/partition/region_defs.h |
| +++ b/platform/ext/target/arm/corstone1000/partition/region_defs.h |
| @@ -1,8 +1,10 @@ |
| /* |
| - * Copyright (c) 2017-2022 Arm Limited. All rights reserved. |
| + * Copyright (c) 2017-2023 Arm Limited. All rights reserved. |
| * Copyright (c) 2021-2023 Cypress Semiconductor Corporation (an Infineon company) |
| * or an affiliate of Cypress Semiconductor Corporation. All rights reserved. |
| * |
| + * SPDX-License-Identifier: Apache-2.0 |
| + * |
| * 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 |
| @@ -53,7 +55,7 @@ |
| |
| #define S_DATA_START (SRAM_BASE + TFM_PARTITION_SIZE) |
| #define S_DATA_SIZE (SRAM_SIZE - TFM_PARTITION_SIZE) |
| -#define S_UNPRIV_DATA_SIZE (0x2160) |
| +#define S_UNPRIV_DATA_SIZE (0x4000) |
| #define S_DATA_LIMIT (S_DATA_START + S_DATA_SIZE - 1) |
| #define S_DATA_PRIV_START (S_DATA_START + S_UNPRIV_DATA_SIZE) |
| |
| diff --git a/platform/ext/target/arm/corstone1000/tfm_hal_isolation.c b/platform/ext/target/arm/corstone1000/tfm_hal_isolation.c |
| index 01f7687bc..98e795dde 100644 |
| --- a/platform/ext/target/arm/corstone1000/tfm_hal_isolation.c |
| +++ b/platform/ext/target/arm/corstone1000/tfm_hal_isolation.c |
| @@ -1,5 +1,5 @@ |
| /* |
| - * Copyright (c) 2020-2022, Arm Limited. All rights reserved. |
| + * Copyright (c) 2020-2023, Arm Limited. All rights reserved. |
| * Copyright (c) 2022 Cypress Semiconductor Corporation (an Infineon |
| * company) or an affiliate of Cypress Semiconductor Corporation. All rights |
| * reserved. |
| @@ -14,9 +14,11 @@ |
| #include "tfm_hal_isolation.h" |
| #include "mpu_config.h" |
| #include "mmio_defs.h" |
| +#include "flash_layout.h" |
| |
| #define PROT_BOUNDARY_VAL \ |
| ((1U << HANDLE_ATTR_PRIV_POS) & HANDLE_ATTR_PRIV_MASK) |
| +#define MPU_REGION_MIN_SIZE (0x100) |
| |
| #ifdef CONFIG_TFM_ENABLE_MEMORY_PROTECT |
| |
| @@ -31,20 +33,38 @@ REGION_DECLARE(Image$$, TFM_SP_META_PTR, $$ZI$$Base); |
| REGION_DECLARE(Image$$, TFM_SP_META_PTR, $$ZI$$Limit); |
| #endif /* CONFIG_TFM_PARTITION_META */ |
| |
| -static void configure_mpu(uint32_t rnr, uint32_t base, uint32_t limit, |
| - uint32_t is_xn_exec, uint32_t ap_permissions) |
| +static enum tfm_hal_status_t configure_mpu(uint32_t rnr, uint32_t base, |
| + uint32_t limit, uint32_t is_xn_exec, uint32_t ap_permissions) |
| { |
| - uint32_t size; /* region size */ |
| + uint32_t rbar_size_field; /* region size as it is used in the RBAR */ |
| uint32_t rasr; /* region attribute and size register */ |
| uint32_t rbar; /* region base address register */ |
| |
| - size = get_rbar_size_field(limit - base); |
| + rbar_size_field = get_rbar_size_field(limit - base); |
| + |
| + /* The MPU region's base address has to be aligned to the region |
| + * size for a valid MPU configuration */ |
| + if ((base % (1 << (rbar_size_field + 1))) != 0) { |
| + return TFM_HAL_ERROR_INVALID_INPUT; |
| + } |
| + |
| + /* The MPU supports only 8 memory regions */ |
| + if (rnr > 7) { |
| + return TFM_HAL_ERROR_INVALID_INPUT; |
| + } |
| + |
| + /* The minimum size for a region is 0x100 bytes */ |
| + if((limit - base) < MPU_REGION_MIN_SIZE) { |
| + return TFM_HAL_ERROR_INVALID_INPUT; |
| + } |
| |
| rasr = ARM_MPU_RASR(is_xn_exec, ap_permissions, TEX, NOT_SHAREABLE, |
| - NOT_CACHEABLE, NOT_BUFFERABLE, SUB_REGION_DISABLE, size); |
| + NOT_CACHEABLE, NOT_BUFFERABLE, SUB_REGION_DISABLE, rbar_size_field); |
| rbar = base & MPU_RBAR_ADDR_Msk; |
| |
| ARM_MPU_SetRegionEx(rnr, rbar, rasr); |
| + |
| + return TFM_HAL_SUCCESS; |
| } |
| |
| #endif /* CONFIG_TFM_ENABLE_MEMORY_PROTECT */ |
| @@ -56,33 +76,60 @@ enum tfm_hal_status_t tfm_hal_set_up_static_boundaries( |
| uint32_t rnr = TFM_ISOLATION_REGION_START_NUMBER; /* current region number */ |
| uint32_t base; /* start address */ |
| uint32_t limit; /* end address */ |
| + enum tfm_hal_status_t ret; |
| |
| ARM_MPU_Disable(); |
| |
| - /* TFM Core unprivileged code region */ |
| - base = (uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_CODE_START, $$RO$$Base); |
| - limit = (uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_CODE_END, $$RO$$Limit); |
| - |
| - configure_mpu(rnr++, base, limit, XN_EXEC_OK, AP_RO_PRIV_UNPRIV); |
| - |
| - /* RO region */ |
| - base = (uint32_t)®ION_NAME(Image$$, TFM_APP_CODE_START, $$Base); |
| - limit = (uint32_t)®ION_NAME(Image$$, TFM_APP_CODE_END, $$Base); |
| + /* Armv6-M MPU allows region overlapping. The region with the higher RNR |
| + * will decide the attributes. |
| + * |
| + * The default attributes are set to XN_EXEC_OK and AP_RO_PRIV_UNPRIV for the |
| + * whole SRAM so the PSA_ROT_LINKER_CODE, TFM_UNPRIV_CODE and APP_ROT_LINKER_CODE |
| + * don't have to be aligned and memory space can be saved. |
| + * This region has the lowest RNR so the next regions can overwrite these |
| + * attributes if it's needed. |
| + */ |
| + base = SRAM_BASE; |
| + limit = SRAM_BASE + SRAM_SIZE; |
| + |
| + ret = configure_mpu(rnr++, base, limit, |
| + XN_EXEC_OK, AP_RW_PRIV_UNPRIV); |
| + if (ret != TFM_HAL_SUCCESS) { |
| + return ret; |
| + } |
| |
| - configure_mpu(rnr++, base, limit, XN_EXEC_OK, AP_RO_PRIV_UNPRIV); |
| |
| /* RW, ZI and stack as one region */ |
| base = (uint32_t)®ION_NAME(Image$$, TFM_APP_RW_STACK_START, $$Base); |
| limit = (uint32_t)®ION_NAME(Image$$, TFM_APP_RW_STACK_END, $$Base); |
| |
| - configure_mpu(rnr++, base, limit, XN_EXEC_NOT_OK, AP_RW_PRIV_UNPRIV); |
| + /* The section size can be bigger than the alignment size, else the code would |
| + * not fit into the memory. Because of this, the sections can use multiple MPU |
| + * regions. */ |
| + do { |
| + ret = configure_mpu(rnr++, base, base + TFM_LINKER_APP_ROT_LINKER_DATA_ALIGNMENT, |
| + XN_EXEC_NOT_OK, AP_RW_PRIV_UNPRIV); |
| + if (ret != TFM_HAL_SUCCESS) { |
| + return ret; |
| + } |
| + base += TFM_LINKER_APP_ROT_LINKER_DATA_ALIGNMENT; |
| + } while (base < limit); |
| + |
| |
| #ifdef CONFIG_TFM_PARTITION_META |
| /* TFM partition metadata pointer region */ |
| base = (uint32_t)®ION_NAME(Image$$, TFM_SP_META_PTR, $$ZI$$Base); |
| limit = (uint32_t)®ION_NAME(Image$$, TFM_SP_META_PTR, $$ZI$$Limit); |
| |
| - configure_mpu(rnr++, base, limit, XN_EXEC_NOT_OK, AP_RW_PRIV_UNPRIV); |
| + do { |
| + ret = configure_mpu(rnr++, base, base + TFM_LINKER_SP_META_PTR_ALIGNMENT, |
| + XN_EXEC_NOT_OK, AP_RW_PRIV_UNPRIV); |
| + if (ret != TFM_HAL_SUCCESS) { |
| + return ret; |
| + } |
| + base += TFM_LINKER_SP_META_PTR_ALIGNMENT; |
| + } while (base < limit); |
| + |
| #endif |
| |
| arm_mpu_enable(); |