diff --git a/include/lib/utils.h b/include/lib/utils.h index 3d215c3..f367a1f 100644 --- a/include/lib/utils.h +++ b/include/lib/utils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -29,6 +29,18 @@ */ void clear_mem_regions(mem_region_t *tbl, size_t nregions); +/* + * zero_normalmem all the regions defined in region. It dynamically + * maps chunks of 'chunk_size' in 'va' virtual address and clears them. + * For this reason memory regions must be multiple of chunk_size and + * must be aligned to it as well. chunk_size and va can be selected + * in a way that they minimize the number of entries used in the + * translation tables. + */ +void clear_map_dyn_mem_regions(mem_region_t *region, + size_t nregions, + uintptr_t va, + size_t chunk_size); /* * checks that a region (addr + nbytes-1) of memory is totally covered by diff --git a/include/plat/arm/board/common/board_arm_def.h b/include/plat/arm/board/common/board_arm_def.h index 12a21fb..845f140 100644 --- a/include/plat/arm/board/common/board_arm_def.h +++ b/include/plat/arm/board/common/board_arm_def.h @@ -30,7 +30,11 @@ #elif defined(IMAGE_BL2U) # define PLATFORM_STACK_SIZE 0x200 #elif defined(IMAGE_BL31) +#ifdef PLAT_XLAT_TABLES_DYNAMIC +# define PLATFORM_STACK_SIZE 0x800 +#else # define PLATFORM_STACK_SIZE 0x400 +#endif #elif defined(IMAGE_BL32) # define PLATFORM_STACK_SIZE 0x440 #endif @@ -59,11 +63,11 @@ # define PLAT_SP_IMAGE_MMAP_REGIONS 7 # define PLAT_SP_IMAGE_MAX_XLAT_TABLES 10 # else -# define PLAT_ARM_MMAP_ENTRIES 7 +# define PLAT_ARM_MMAP_ENTRIES 8 # define MAX_XLAT_TABLES 5 # endif #elif defined(IMAGE_BL32) -# define PLAT_ARM_MMAP_ENTRIES 7 +# define PLAT_ARM_MMAP_ENTRIES 8 # define MAX_XLAT_TABLES 5 #else # define PLAT_ARM_MMAP_ENTRIES 11 diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h index f79450c..612a63a 100644 --- a/include/plat/arm/common/plat_arm.h +++ b/include/plat/arm/common/plat_arm.h @@ -166,7 +166,8 @@ void arm_program_trusted_mailbox(uintptr_t address); int arm_psci_read_mem_protect(int *enabled); int arm_nor_psci_write_mem_protect(int val); -void arm_nor_psci_do_mem_protect(void); +void arm_nor_psci_do_static_mem_protect(void); +void arm_nor_psci_do_dyn_mem_protect(void); int arm_psci_mem_protect_chk(uintptr_t base, u_register_t length); /* Topology utility function */ diff --git a/include/plat/arm/css/common/css_def.h b/include/plat/arm/css/common/css_def.h index a2c0b4e..deea1bb 100644 --- a/include/plat/arm/css/common/css_def.h +++ b/include/plat/arm/css/common/css_def.h @@ -172,7 +172,7 @@ #endif /* CSS_LOAD_SCP_IMAGES */ /* Load address of Non-Secure Image for CSS platform ports */ -#define PLAT_ARM_NS_IMAGE_OFFSET 0xE0000000 +#define PLAT_ARM_NS_IMAGE_OFFSET U(0xE0000000) /* TZC related constants */ #define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT_ALL diff --git a/lib/utils/mem_region.c b/lib/utils/mem_region.c index 31c6231..24c2c1d 100644 --- a/lib/utils/mem_region.c +++ b/lib/utils/mem_region.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -40,6 +40,59 @@ } } +#if defined(PLAT_XLAT_TABLES_DYNAMIC) +/* + * zero_normalmem all the regions defined in regions. + * It assumes that MMU is enabled and the memory is Normal memory. + * regions must be a valid pointer to a memory mem_region_t array, + * nregions is the size of the array. va is the virtual address + * where we want to map the physical pages that are going to + * be cleared, and chunk is the amount of memory mapped and + * cleared in every iteration. + */ +void clear_map_dyn_mem_regions(mem_region_t *regions, + size_t nregions, + uintptr_t va, + size_t chunk) +{ + uintptr_t begin; + int r; + size_t size; + const mmap_attr_t attr = MT_MEMORY|MT_RW|MT_NS; + + assert(regions != NULL); + assert(nregions > 0 && chunk > 0); + + for ( ; nregions--; regions++) { + begin = regions->base; + size = regions->nbytes; + if ((begin & (chunk-1)) != 0 || (size & (chunk-1)) != 0) { + INFO("PSCI: Not correctly aligned region\n"); + panic(); + } + + while (size > 0) { + r = mmap_add_dynamic_region(begin, va, chunk, attr); + if (r != 0) { + INFO("PSCI: mmap_add_dynamic_region failed with %d\n", r); + panic(); + } + + zero_normalmem((void *) va, chunk); + + r = mmap_remove_dynamic_region(va, chunk); + if (r != 0) { + INFO("PSCI: mmap_remove_dynamic_region failed with %d\n", r); + panic(); + } + + begin += chunk; + size -= chunk; + } + } +} +#endif + /* * This function checks that a region (addr + nbytes-1) of memory is totally * covered by one of the regions defined in tbl. diff --git a/plat/arm/board/common/board_css_common.c b/plat/arm/board/common/board_css_common.c index c1c3e66..c4e83a4 100644 --- a/plat/arm/board/common/board_css_common.c +++ b/plat/arm/board/common/board_css_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -73,6 +73,9 @@ const mmap_region_t plat_arm_mmap[] = { #ifdef AARCH32 ARM_MAP_SHARED_RAM, +#ifdef PLAT_ARM_MEM_PROT_ADDR + ARM_V2M_MAP_MEM_PROTECT, +#endif #endif V2M_MAP_IOFPGA, CSS_MAP_DEVICE, diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c index 0fa83a5..065ecc1 100644 --- a/plat/arm/board/fvp/fvp_pm.c +++ b/plat/arm/board/fvp/fvp_pm.c @@ -412,13 +412,7 @@ */ .get_sys_suspend_power_state = fvp_get_sys_suspend_power_state, #endif -#if !RESET_TO_BL31 && !RESET_TO_SP_MIN - /* - * mem_protect is not supported in RESET_TO_BL31 and RESET_TO_SP_MIN, - * as that would require mapping in all of NS DRAM into BL31 or BL32. - */ .mem_protect_chk = arm_psci_mem_protect_chk, .read_mem_protect = arm_psci_read_mem_protect, .write_mem_protect = arm_nor_psci_write_mem_protect, -#endif }; diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h index 2d01490..b1adbee 100644 --- a/plat/arm/board/fvp/include/platform_def.h +++ b/plat/arm/board/fvp/include/platform_def.h @@ -7,6 +7,17 @@ #ifndef __PLATFORM_DEF_H__ #define __PLATFORM_DEF_H__ +/* Enable the dynamic translation tables library. */ +#ifdef AARCH32 +# if defined(IMAGE_BL32) && RESET_TO_SP_MIN +# define PLAT_XLAT_TABLES_DYNAMIC 1 +# endif +#else +# if defined(IMAGE_BL31) && RESET_TO_BL31 +# define PLAT_XLAT_TABLES_DYNAMIC 1 +# endif +#endif /* AARCH32 */ + #include #include #include @@ -40,6 +51,9 @@ #define PLAT_ARM_TRUSTED_DRAM_BASE 0x06000000 #define PLAT_ARM_TRUSTED_DRAM_SIZE 0x02000000 /* 32 MB */ +/* virtual address used by dynamic mem_protect for chunk_base */ +#define PLAT_ARM_MEM_PROTEC_VA_FRAME 0xc0000000 + /* No SCP in FVP */ #define PLAT_ARM_SCP_TZC_DRAM1_SIZE ULL(0x0) @@ -48,7 +62,7 @@ /* * Load address of BL33 for this platform port */ -#define PLAT_ARM_NS_IMAGE_OFFSET (ARM_DRAM1_BASE + 0x8000000) +#define PLAT_ARM_NS_IMAGE_OFFSET (ARM_DRAM1_BASE + U(0x8000000)) /* diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h index b422398..c834941 100644 --- a/plat/arm/board/juno/include/platform_def.h +++ b/plat/arm/board/juno/include/platform_def.h @@ -7,6 +7,18 @@ #ifndef __PLATFORM_DEF_H__ #define __PLATFORM_DEF_H__ +/* Enable the dynamic translation tables library. */ +#ifdef AARCH32 +# if defined(IMAGE_BL32) && RESET_TO_SP_MIN +# define PLAT_XLAT_TABLES_DYNAMIC 1 +# endif +#else +# if defined(IMAGE_BL31) && RESET_TO_BL31 +# define PLAT_XLAT_TABLES_DYNAMIC 1 +# endif +#endif /* AARCH32 */ + + #include #include #include @@ -44,6 +56,9 @@ /* Use the bypass address */ #define PLAT_ARM_TRUSTED_ROM_BASE V2M_FLASH0_BASE + BL1_ROM_BYPASS_OFFSET +/* virtual address used by dynamic mem_protect for chunk_base */ +#define PLAT_ARM_MEM_PROTEC_VA_FRAME 0xc0000000 + /* * Actual ROM size on Juno is 64 KB, but TBB currently requires at least 80 KB * in debug mode. We can test TBB on Juno bypassing the ROM and using 128 KB of @@ -90,7 +105,7 @@ #endif #ifdef IMAGE_BL32 -# define PLAT_ARM_MMAP_ENTRIES 5 +# define PLAT_ARM_MMAP_ENTRIES 6 # define MAX_XLAT_TABLES 4 #endif diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c index 8a6c768..dc7cd68 100644 --- a/plat/arm/common/arm_bl2_setup.c +++ b/plat/arm/common/arm_bl2_setup.c @@ -219,7 +219,7 @@ plat_arm_security_setup(); #if defined(PLAT_ARM_MEM_PROT_ADDR) - arm_nor_psci_do_mem_protect(); + arm_nor_psci_do_static_mem_protect(); #endif } diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c index 963c4d2..3c70f9d 100644 --- a/plat/arm/common/arm_bl31_setup.c +++ b/plat/arm/common/arm_bl31_setup.c @@ -206,6 +206,10 @@ */ plat_arm_security_setup(); +#if defined(PLAT_ARM_MEM_PROT_ADDR) + arm_nor_psci_do_dyn_mem_protect(); +#endif /* PLAT_ARM_MEM_PROT_ADDR */ + #endif /* RESET_TO_BL31 */ /* Enable and initialize the System level generic timer */ diff --git a/plat/arm/common/arm_nor_psci_mem_protect.c b/plat/arm/common/arm_nor_psci_mem_protect.c index 3167a42..c01e4ed 100644 --- a/plat/arm/common/arm_nor_psci_mem_protect.c +++ b/plat/arm/common/arm_nor_psci_mem_protect.c @@ -12,10 +12,22 @@ #include #include + +/* + * DRAM1 is used also to load the NS boot loader. For this reason we + * cannot clear the full DRAM1, because in that case we would clear + * the NS images (especially for RESET_TO_BL31 and RESET_TO_SPMIN cases). + * For this reason we reserve 64 MB for the NS images and protect the RAM + * until the end of DRAM1. + * We limit the size of DRAM2 to 1 GB to avoid big delays while booting + */ +#define DRAM1_NS_IMAGE_LIMIT (PLAT_ARM_NS_IMAGE_OFFSET + (32 << TWO_MB_SHIFT)) +#define DRAM1_PROTECTED_SIZE (ARM_NS_DRAM1_END+1u - DRAM1_NS_IMAGE_LIMIT) + static mem_region_t arm_ram_ranges[] = { - {ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_SIZE}, + {DRAM1_NS_IMAGE_LIMIT, DRAM1_PROTECTED_SIZE}, #ifdef AARCH64 - {ARM_DRAM2_BASE, ARM_DRAM2_SIZE}, + {ARM_DRAM2_BASE, 1u << ONE_GB_SHIFT}, #endif }; @@ -29,7 +41,7 @@ int tmp; tmp = *(int *) PLAT_ARM_MEM_PROT_ADDR; - *enabled = (tmp == 1); + *enabled = (tmp == 1) ? 1 : 0; return 0; } @@ -46,7 +58,7 @@ return -1; } - if (enable) { + if (enable != 0) { /* * If we want to write a value different than 0 * then we have to erase the full block because @@ -71,15 +83,47 @@ * Function used for required psci operations performed when * system boots ******************************************************************************/ -void arm_nor_psci_do_mem_protect(void) +/* + * PLAT_MEM_PROTECT_VA_FRAME is a address specifically + * selected in a way that is not needed an additional + * translation table for memprotect. It happens because + * we use a chunk of size 2MB and it means that it can + * be mapped in a level 2 table and the level 2 table + * for 0xc0000000 is already used and the entry for + * 0xc0000000 is not used. + */ +#if defined(PLAT_XLAT_TABLES_DYNAMIC) +void arm_nor_psci_do_dyn_mem_protect(void) { int enable; arm_psci_read_mem_protect(&enable); - if (!enable) + if (enable == 0) return; - INFO("PSCI: Overwritting non secure memory\n"); - clear_mem_regions(arm_ram_ranges, ARRAY_SIZE(arm_ram_ranges)); + + INFO("PSCI: Overwriting non secure memory\n"); + clear_map_dyn_mem_regions(arm_ram_ranges, + ARRAY_SIZE(arm_ram_ranges), + PLAT_ARM_MEM_PROTEC_VA_FRAME, + 1 << TWO_MB_SHIFT); +} +#endif + +/******************************************************************************* + * Function used for required psci operations performed when + * system boots and dynamic memory is not used. + ******************************************************************************/ +void arm_nor_psci_do_static_mem_protect(void) +{ + int enable; + + arm_psci_read_mem_protect(&enable); + if (enable == 0) + return; + + INFO("PSCI: Overwriting non secure memory\n"); + clear_mem_regions(arm_ram_ranges, + ARRAY_SIZE(arm_ram_ranges)); arm_nor_psci_write_mem_protect(0); } diff --git a/plat/arm/common/sp_min/arm_sp_min_setup.c b/plat/arm/common/sp_min/arm_sp_min_setup.c index 7b5477e..9a6c074 100644 --- a/plat/arm/common/sp_min/arm_sp_min_setup.c +++ b/plat/arm/common/sp_min/arm_sp_min_setup.c @@ -162,6 +162,11 @@ */ #if RESET_TO_SP_MIN plat_arm_security_setup(); + +#if defined(PLAT_ARM_MEM_PROT_ADDR) + arm_nor_psci_do_dyn_mem_protect(); +#endif /* PLAT_ARM_MEM_PROT_ADDR */ + #endif /* Enable and initialize the System level generic timer */ diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c index 4a615e1..3df5b78 100644 --- a/plat/arm/css/common/css_pm.c +++ b/plat/arm/css/common/css_pm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -303,11 +303,8 @@ .translate_power_state_by_mpidr = css_translate_power_state_by_mpidr, .get_node_hw_state = css_node_hw_state, .get_sys_suspend_power_state = css_get_sys_suspend_power_state, -/* - * mem_protect is not supported in RESET_TO_BL31 and RESET_TO_SP_MIN, - * as that would require mapping in all of NS DRAM into BL31 or BL32. - */ -#if defined(PLAT_ARM_MEM_PROT_ADDR) && !RESET_TO_BL31 && !RESET_TO_SP_MIN + +#if defined(PLAT_ARM_MEM_PROT_ADDR) .mem_protect_chk = arm_psci_mem_protect_chk, .read_mem_protect = arm_psci_read_mem_protect, .write_mem_protect = arm_nor_psci_write_mem_protect,