Merge "Read-only xlat tables for BL31 memory" into integration

This commit is contained in:
Mark Dykes 2020-02-25 17:24:17 +00:00 committed by TrustedFirmware Code Review
commit 020ce8c9f6
15 changed files with 267 additions and 16 deletions

View File

@ -621,6 +621,12 @@ ifeq ($(MEASURED_BOOT),1)
endif
endif
ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1)
ifeq (${ALLOW_RO_XLAT_TABLES}, 1)
$(error "ALLOW_RO_XLAT_TABLES requires translation tables library v2")
endif
endif
################################################################################
# Process platform overrideable behaviour
################################################################################
@ -748,6 +754,7 @@ endif
# Build options checks
################################################################################
$(eval $(call assert_boolean,ALLOW_RO_XLAT_TABLES))
$(eval $(call assert_boolean,COLD_BOOT_SINGLE_CPU))
$(eval $(call assert_boolean,CREATE_KEYS))
$(eval $(call assert_boolean,CTX_INCLUDE_AARCH32_REGS))
@ -815,6 +822,7 @@ endif
# platform to overwrite the default options
################################################################################
$(eval $(call add_define,ALLOW_RO_XLAT_TABLES))
$(eval $(call add_define,ARM_ARCH_MAJOR))
$(eval $(call add_define,ARM_ARCH_MINOR))
$(eval $(call add_define,COLD_BOOT_SINGLE_CPU))

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -345,6 +345,16 @@ int xlat_change_mem_attributes_ctx(const xlat_ctx_t *ctx, uintptr_t base_va,
size_t size, uint32_t attr);
int xlat_change_mem_attributes(uintptr_t base_va, size_t size, uint32_t attr);
#if PLAT_RO_XLAT_TABLES
/*
* Change the memory attributes of the memory region encompassing the higher
* level translation tables to secure read-only data.
*
* Return 0 on success, a negative error code on error.
*/
int xlat_make_tables_readonly(void);
#endif
/*
* Query the memory attributes of a memory page in a set of translation tables.
*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -70,6 +70,9 @@ struct xlat_ctx {
*/
uint64_t (*tables)[XLAT_TABLE_ENTRIES];
int tables_num;
#if PLAT_RO_XLAT_TABLES
bool readonly_tables;
#endif
/*
* Keep track of how many regions are mapped in each table. The base
* table can't be unmapped so it isn't needed to keep track of it.
@ -122,6 +125,14 @@ struct xlat_ctx {
/* do nothing */
#endif /* PLAT_XLAT_TABLES_DYNAMIC */
#if PLAT_RO_XLAT_TABLES
#define XLAT_CTX_INIT_TABLE_ATTR() \
.readonly_tables = false,
#else
#define XLAT_CTX_INIT_TABLE_ATTR()
/* do nothing */
#endif
#define REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count, \
_xlat_tables_count, _virt_addr_space_size, \
_phy_addr_space_size, _xlat_regime, _section_name)\
@ -142,22 +153,63 @@ struct xlat_ctx {
XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count) \
\
static xlat_ctx_t _ctx_name##_xlat_ctx = { \
.va_max_address = (_virt_addr_space_size) - 1UL, \
.pa_max_address = (_phy_addr_space_size) - 1ULL, \
.va_max_address = (_virt_addr_space_size) - 1UL, \
.mmap = _ctx_name##_mmap, \
.mmap_num = (_mmap_count), \
.base_level = GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_size),\
.tables = _ctx_name##_xlat_tables, \
.tables_num = _xlat_tables_count, \
XLAT_CTX_INIT_TABLE_ATTR() \
XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name) \
.next_table = 0, \
.base_table = _ctx_name##_base_xlat_table, \
.base_table_entries = \
GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size),\
.tables = _ctx_name##_xlat_tables, \
.tables_num = _xlat_tables_count, \
XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name) \
.xlat_regime = (_xlat_regime), \
.max_pa = 0U, \
.max_va = 0U, \
.next_table = 0, \
.base_level = GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_size),\
.initialized = false, \
.xlat_regime = (_xlat_regime) \
}
#define REGISTER_XLAT_CONTEXT_RO_BASE_TABLE(_ctx_name, _mmap_count, \
_xlat_tables_count, _virt_addr_space_size, \
_phy_addr_space_size, _xlat_regime, _section_name)\
CASSERT(CHECK_PHY_ADDR_SPACE_SIZE(_phy_addr_space_size), \
assert_invalid_physical_addr_space_sizefor_##_ctx_name);\
\
static mmap_region_t _ctx_name##_mmap[_mmap_count + 1]; \
\
static uint64_t _ctx_name##_xlat_tables[_xlat_tables_count] \
[XLAT_TABLE_ENTRIES] \
__aligned(XLAT_TABLE_SIZE) __section(_section_name); \
\
static uint64_t _ctx_name##_base_xlat_table \
[GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)] \
__aligned(GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)\
* sizeof(uint64_t)) \
__section(".rodata"); \
\
XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count) \
\
static xlat_ctx_t _ctx_name##_xlat_ctx = { \
.pa_max_address = (_phy_addr_space_size) - 1ULL, \
.va_max_address = (_virt_addr_space_size) - 1UL, \
.mmap = _ctx_name##_mmap, \
.mmap_num = (_mmap_count), \
.tables = _ctx_name##_xlat_tables, \
.tables_num = _xlat_tables_count, \
XLAT_CTX_INIT_TABLE_ATTR() \
XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name) \
.next_table = 0, \
.base_table = _ctx_name##_base_xlat_table, \
.base_table_entries = \
GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size),\
.max_pa = 0U, \
.max_va = 0U, \
.base_level = GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_size),\
.initialized = false, \
.xlat_regime = (_xlat_regime) \
}
#endif /*__ASSEMBLER__*/

View File

@ -236,6 +236,11 @@ int arm_get_mbedtls_heap(void **heap_addr, size_t *heap_size);
*/
void arm_free_init_memory(void);
/*
* Make the higher level translation tables read-only
*/
void arm_xlat_make_tables_readonly(void);
/*
* Mandatory functions required in ARM standard platforms
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -30,7 +30,7 @@ loop_\op:
dc \op, x0
add x0, x0, x2
cmp x0, x1
b.lo loop_\op
b.lo loop_\op
dsb sy
exit_loop_\op:
ret
@ -140,7 +140,7 @@ loop3_\_op:
level_done:
add x10, x10, #2 // increment cache number
cmp x3, x10
b.hi loop1
b.hi loop1
msr csselr_el1, xzr // select cache level 0 in csselr
dsb sy // barrier to complete final cache operation
isb

View File

@ -0,0 +1,37 @@
#
# Copyright (c) 2020, ARM Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
ifeq (${USE_DEBUGFS}, 1)
$(error "Debugfs requires functionality from the dynamic translation \
library and is incompatible with ALLOW_RO_XLAT_TABLES.")
endif
ifeq (${ARCH},aarch32)
ifeq (${RESET_TO_SP_MIN},1)
$(error "RESET_TO_SP_MIN requires functionality from the dynamic \
translation library and is incompatible with \
ALLOW_RO_XLAT_TABLES.")
endif
else # if AArch64
ifeq (${PLAT},tegra)
$(error "Tegra requires functionality from the dynamic translation \
library and is incompatible with ALLOW_RO_XLAT_TABLES.")
endif
ifeq (${RESET_TO_BL31},1)
$(error "RESET_TO_BL31 requires functionality from the dynamic \
translation library and is incompatible with \
ALLOW_RO_XLAT_TABLES.")
endif
ifeq (${SPD},trusty)
$(error "Trusty requires functionality from the dynamic translation \
library and is incompatible with ALLOW_RO_XLAT_TABLES.")
endif
ifeq (${SPM_MM},1)
$(error "SPM_MM requires functionality to change memory region \
attributes, which is not possible once the translation tables \
have been made read-only.")
endif
endif

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
# Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@ -13,3 +13,7 @@ XLAT_TABLES_LIB_SRCS := $(addprefix lib/xlat_tables_v2/, \
XLAT_TABLES_LIB_V2 := 1
$(eval $(call add_define,XLAT_TABLES_LIB_V2))
ifeq (${ALLOW_RO_XLAT_TABLES}, 1)
include lib/xlat_tables_v2/ro_xlat_tables.mk
endif

View File

@ -1,9 +1,10 @@
/*
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <assert.h>
#include <platform_def.h>
@ -24,8 +25,14 @@ uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX];
* Allocate and initialise the default translation context for the BL image
* currently executing.
*/
#if PLAT_RO_XLAT_TABLES
REGISTER_XLAT_CONTEXT_RO_BASE_TABLE(tf, MAX_MMAP_REGIONS, MAX_XLAT_TABLES,
PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE,
EL_REGIME_INVALID, "xlat_table");
#else
REGISTER_XLAT_CONTEXT(tf, MAX_MMAP_REGIONS, MAX_XLAT_TABLES,
PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE);
#endif
void mmap_add_region(unsigned long long base_pa, uintptr_t base_va, size_t size,
unsigned int attr)
@ -119,6 +126,75 @@ int xlat_change_mem_attributes(uintptr_t base_va, size_t size, uint32_t attr)
return xlat_change_mem_attributes_ctx(&tf_xlat_ctx, base_va, size, attr);
}
#if PLAT_RO_XLAT_TABLES
/* Change the memory attributes of the descriptors which resolve the address
* range that belongs to the translation tables themselves, which are by default
* mapped as part of read-write data in the BL image's memory.
*
* Since the translation tables map themselves via these level 3 (page)
* descriptors, any change applied to them with the MMU on would introduce a
* chicken and egg problem because of the break-before-make sequence.
* Eventually, it would reach the descriptor that resolves the very table it
* belongs to and the invalidation (break step) would cause the subsequent write
* (make step) to it to generate an MMU fault. Therefore, the MMU is disabled
* before making the change.
*
* No assumption is made about what data this function needs, therefore all the
* caches are flushed in order to ensure coherency. A future optimization would
* be to only flush the required data to main memory.
*/
int xlat_make_tables_readonly(void)
{
assert(tf_xlat_ctx.initialized == true);
#ifdef __aarch64__
if (tf_xlat_ctx.xlat_regime == EL1_EL0_REGIME) {
disable_mmu_el1();
} else if (tf_xlat_ctx.xlat_regime == EL3_REGIME) {
disable_mmu_el3();
} else {
assert(tf_xlat_ctx.xlat_regime == EL2_REGIME);
return -1;
}
/* Flush all caches. */
dcsw_op_all(DCCISW);
#else /* !__aarch64__ */
assert(tf_xlat_ctx.xlat_regime == EL1_EL0_REGIME);
/* On AArch32, we flush the caches before disabling the MMU. The reason
* for this is that the dcsw_op_all AArch32 function pushes some
* registers onto the stack under the assumption that it is writing to
* cache, which is not true with the MMU off. This would result in the
* stack becoming corrupted and a wrong/junk value for the LR being
* restored at the end of the routine.
*/
dcsw_op_all(DC_OP_CISW);
disable_mmu_secure();
#endif
int rc = xlat_change_mem_attributes_ctx(&tf_xlat_ctx,
(uintptr_t)tf_xlat_ctx.tables,
tf_xlat_ctx.tables_num * XLAT_TABLE_SIZE,
MT_RO_DATA | MT_SECURE);
#ifdef __aarch64__
if (tf_xlat_ctx.xlat_regime == EL1_EL0_REGIME) {
enable_mmu_el1(0U);
} else {
assert(tf_xlat_ctx.xlat_regime == EL3_REGIME);
enable_mmu_el3(0U);
}
#else /* !__aarch64__ */
enable_mmu_svc_mon(0U);
#endif
if (rc == 0) {
tf_xlat_ctx.readonly_tables = true;
}
return rc;
}
#endif /* PLAT_RO_XLAT_TABLES */
/*
* If dynamic allocation of new regions is disabled then by the time we call the
* function enabling the MMU, we'll have registered all the memory regions to

View File

@ -207,6 +207,13 @@ USE_FCONF_BASED_IO := 0
# Build option to choose whether Trusted Firmware uses library at ROM
USE_ROMLIB := 0
# Build option to choose whether the xlat tables of BL images can be read-only.
# Note that this only serves as a higher level option to PLAT_RO_XLAT_TABLES,
# which is the per BL-image option that actually enables the read-only tables
# API. The reason for having this additional option is to have a common high
# level makefile where we can check for incompatible features/build options.
ALLOW_RO_XLAT_TABLES := 0
# Chain of trust.
COT := tbbr

View File

@ -292,7 +292,7 @@ ifeq (${ARCH},aarch32)
ifeq (${RESET_TO_SP_MIN},1)
BL32_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC=1
endif
else # if AArch64
else # AArch64
ifeq (${RESET_TO_BL31},1)
BL31_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC=1
endif
@ -301,6 +301,17 @@ else # if AArch64
endif
endif
ifeq (${ALLOW_RO_XLAT_TABLES}, 1)
ifeq (${ARCH},aarch32)
BL32_CFLAGS += -DPLAT_RO_XLAT_TABLES=1
else # AArch64
BL31_CFLAGS += -DPLAT_RO_XLAT_TABLES=1
ifeq (${SPD},tspd)
BL32_CFLAGS += -DPLAT_RO_XLAT_TABLES=1
endif
endif
endif
ifeq (${USE_DEBUGFS},1)
BL31_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC=1
endif

View File

@ -155,6 +155,14 @@ else
endif
endif
ifeq (${ALLOW_RO_XLAT_TABLES}, 1)
ifeq (${JUNO_AARCH32_EL3_RUNTIME}, 1)
BL32_CFLAGS += -DPLAT_RO_XLAT_TABLES=1
else
BL31_CFLAGS += -DPLAT_RO_XLAT_TABLES=1
endif
endif
# Add the FDT_SOURCES and options for Dynamic Config
FDT_SOURCES += plat/arm/board/juno/fdts/${PLAT}_fw_config.dts
TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb

View File

@ -256,9 +256,14 @@ void arm_bl31_plat_runtime_setup(void)
/* Initialize the runtime console */
arm_console_runtime_init();
#if RECLAIM_INIT_CODE
arm_free_init_memory();
#endif
#if PLAT_RO_XLAT_TABLES
arm_xlat_make_tables_readonly();
#endif
}
#if RECLAIM_INIT_CODE

View File

@ -25,6 +25,26 @@
* conflicts with the definition in plat/common. */
#pragma weak plat_get_syscnt_freq2
/*******************************************************************************
* Changes the memory attributes for the region of mapped memory where the BL
* image's translation tables are located such that the tables will have
* read-only permissions.
******************************************************************************/
#if PLAT_RO_XLAT_TABLES
void arm_xlat_make_tables_readonly(void)
{
int rc = xlat_make_tables_readonly();
if (rc != 0) {
ERROR("Failed to make translation tables read-only at EL%u.\n",
get_current_el());
panic();
}
INFO("Translation tables are now read-only at EL%u.\n",
get_current_el());
}
#endif
void arm_setup_romlib(void)
{

View File

@ -167,6 +167,10 @@ void arm_sp_min_plat_runtime_setup(void)
{
/* Initialize the runtime console */
arm_console_runtime_init();
#if PLAT_RO_XLAT_TABLES
arm_xlat_make_tables_readonly();
#endif
}
/*******************************************************************************

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -79,4 +79,8 @@ void tsp_plat_arch_setup(void)
setup_page_tables(bl_regions, plat_arm_get_mmap());
enable_mmu_el1(0);
#if PLAT_RO_XLAT_TABLES
arm_xlat_make_tables_readonly();
#endif
}