aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Vargas <roberto.vargas@arm.com>2018-01-05 16:00:05 +0000
committerRoberto Vargas <roberto.vargas@arm.com>2018-05-01 15:25:25 +0100
commit638b034cc34ecdc54b9c790d5192229a027c8156 (patch)
treefc634c377f4eae6f510fe43e558a273358672d9f
parenta8d9550b527107b85703d7b4e93073e653ae95f7 (diff)
ARM platforms: Demonstrate mem_protect from el3_runtime
Previously mem_protect used to be only supported from BL2. This is not helpful in the case when ARM TF-A BL2 is not used. This patch demonstrates mem_protect from el3_runtime firmware on ARM Platforms specifically when RESET_TO_BL31 or RESET_TO_SP_MIN flag is set as BL2 may be absent in these cases. The Non secure DRAM is dynamically mapped into EL3 mmap tables temporarily and then the protected regions are then cleared. This avoids the need to map the non secure DRAM permanently to BL31/sp_min. The stack size is also increased, because DYNAMIC_XLAT_TABLES require a bigger stack. Change-Id: Ia44c594192ed5c5adc596c0cff2c7cc18c001fde Signed-off-by: Roberto Vargas <roberto.vargas@arm.com>
-rw-r--r--include/lib/utils.h14
-rw-r--r--include/plat/arm/board/common/board_arm_def.h8
-rw-r--r--include/plat/arm/common/plat_arm.h3
-rw-r--r--include/plat/arm/css/common/css_def.h2
-rw-r--r--lib/utils/mem_region.c55
-rw-r--r--plat/arm/board/common/board_css_common.c5
-rw-r--r--plat/arm/board/fvp/fvp_pm.c6
-rw-r--r--plat/arm/board/fvp/include/platform_def.h16
-rw-r--r--plat/arm/board/juno/include/platform_def.h17
-rw-r--r--plat/arm/common/arm_bl2_setup.c2
-rw-r--r--plat/arm/common/arm_bl31_setup.c4
-rw-r--r--plat/arm/common/arm_nor_psci_mem_protect.c60
-rw-r--r--plat/arm/common/sp_min/arm_sp_min_setup.c5
-rw-r--r--plat/arm/css/common/css_pm.c9
14 files changed, 176 insertions, 30 deletions
diff --git a/include/lib/utils.h b/include/lib/utils.h
index 3d215c32..f367a1f4 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 @@ typedef struct mem_region {
*/
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 12a21fb7..845f1403 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 f79450ce..612a63a8 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -166,7 +166,8 @@ void arm_system_pwr_domain_resume(void);
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 a2c0b4e8..deea1bb4 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 31c6231f..24c2c1de 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 @@ void clear_mem_regions(mem_region_t *tbl, size_t nregions)
}
}
+#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 c1c3e66a..c4e83a42 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[] = {
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 0fa83a5c..065ecc11 100644
--- a/plat/arm/board/fvp/fvp_pm.c
+++ b/plat/arm/board/fvp/fvp_pm.c
@@ -412,13 +412,7 @@ plat_psci_ops_t plat_arm_psci_pm_ops = {
*/
.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 2d014903..b1adbee2 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 <arm_def.h>
#include <arm_spm_def.h>
#include <board_arm_def.h>
@@ -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 b4223987..c8349413 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 <arm_def.h>
#include <board_arm_def.h>
#include <board_css_def.h>
@@ -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 8a6c7680..dc7cd680 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -219,7 +219,7 @@ void arm_bl2_platform_setup(void)
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 963c4d2b..3c70f9de 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -206,6 +206,10 @@ void arm_bl31_platform_setup(void)
*/
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 3167a42a..c01e4ed5 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 <psci.h>
#include <utils.h>
+
+/*
+ * 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 arm_psci_read_mem_protect(int *enabled)
int tmp;
tmp = *(int *) PLAT_ARM_MEM_PROT_ADDR;
- *enabled = (tmp == 1);
+ *enabled = (tmp == 1) ? 1 : 0;
return 0;
}
@@ -46,7 +58,7 @@ int arm_nor_psci_write_mem_protect(int val)
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 @@ int arm_nor_psci_write_mem_protect(int val)
* 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 7b5477ec..9a6c0740 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 @@ void sp_min_platform_setup(void)
*/
#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 4a615e1c..3df5b781 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 @@ plat_psci_ops_t plat_arm_psci_pm_ops = {
.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,