From 79621f0038b789de23ecc8891024f7cf6aa65999 Mon Sep 17 00:00:00 2001 From: Daniel Boulby Date: Tue, 28 Aug 2018 17:44:48 +0100 Subject: [PATCH 1/9] xlat: Change check in mmap_add and mmap_add_ctx() Depending on the build flags it is possible that some of the memory regions mapped in page table setup could have a size of 0. In this case we simply want to do nothing but still wish to map the other regions in the array. Therefore we cannot only use size == 0 as the termination logic for the loop. Since an attributes field with value 0 means that the region is device memory, read only, secure and executable. Device memory can't be executable, so this combination should never be used and it is safe to use as a terminator value. Therefore by changing the termination logic to use attributes instead of size we prevent terminating the loop when we don't intend to. Change-Id: I92fc7f689ab08543497be6be4896dace2ed7b66a Signed-off-by: Daniel Boulby --- lib/xlat_tables/xlat_tables_common.c | 2 +- lib/xlat_tables_v2/xlat_tables_core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/xlat_tables/xlat_tables_common.c b/lib/xlat_tables/xlat_tables_common.c index ca67f2a09..a9aaeee8d 100644 --- a/lib/xlat_tables/xlat_tables_common.c +++ b/lib/xlat_tables/xlat_tables_common.c @@ -176,7 +176,7 @@ void mmap_add(const mmap_region_t *mm) { const mmap_region_t *mm_cursor = mm; - while (mm_cursor->size != 0U) { + while (mm_cursor->attr != 0U) { mmap_add_region(mm_cursor->base_pa, mm_cursor->base_va, mm_cursor->size, mm_cursor->attr); mm_cursor++; diff --git a/lib/xlat_tables_v2/xlat_tables_core.c b/lib/xlat_tables_v2/xlat_tables_core.c index 003718e76..d9837ff82 100644 --- a/lib/xlat_tables_v2/xlat_tables_core.c +++ b/lib/xlat_tables_v2/xlat_tables_core.c @@ -815,7 +815,7 @@ void mmap_add_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm) { const mmap_region_t *mm_cursor = mm; - while (mm_cursor->size != 0U) { + while (mm_cursor->attr != 0U) { mmap_add_region_ctx(ctx, mm_cursor); mm_cursor++; } From 8d30b4987b00a8cf938ee8ae225f3bab346a60c9 Mon Sep 17 00:00:00 2001 From: Daniel Boulby Date: Wed, 19 Sep 2018 14:20:46 +0100 Subject: [PATCH 2/9] Remove unused ROMLIB memory region macro Remove ARM_MAP_BL_ROMLIB memory region macro as it is now split into two regions for code and data Change-Id: Ic17b5b584933c196db29fe83051d7e0a8e92911c Signed-off-by: Daniel Boulby --- plat/arm/common/arm_bl31_setup.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c index 364e46a9c..ce799b0ff 100644 --- a/plat/arm/common/arm_bl31_setup.c +++ b/plat/arm/common/arm_bl31_setup.c @@ -253,12 +253,6 @@ void bl31_plat_runtime_setup(void) ******************************************************************************/ void arm_bl31_plat_arch_setup(void) { - -#define ARM_MAP_BL_ROMLIB MAP_REGION_FLAT( \ - BL31_BASE, \ - BL31_END - BL31_BASE, \ - MT_MEMORY | MT_RW | MT_SECURE) - const mmap_region_t bl_regions[] = { MAP_BL31_TOTAL, ARM_MAP_BL_RO, From 1a4b46d5836d766ba6092206119be030f54462dd Mon Sep 17 00:00:00 2001 From: Daniel Boulby Date: Wed, 19 Sep 2018 14:22:33 +0100 Subject: [PATCH 3/9] Set the IMAGE_BLx flag for the linker preprocessor Change-Id: Ibc91f119c99413ded59a9db3db918d22f0517bc1 Signed-off-by: Daniel Boulby --- make_helpers/build_macros.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk index 92a0f6e86..520725bbb 100644 --- a/make_helpers/build_macros.mk +++ b/make_helpers/build_macros.mk @@ -252,10 +252,11 @@ endef define MAKE_LD $(eval DEP := $(1).d) +$(eval IMAGE := IMAGE_BL$(call uppercase,$(3))) $(1): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | bl$(3)_dirs @echo " PP $$<" - $$(Q)$$(CPP) $$(CPPFLAGS) -P -D__ASSEMBLY__ -D__LINKER__ $(MAKE_DEP) -o $$@ $$< + $$(Q)$$(CPP) $$(CPPFLAGS) -P -D__ASSEMBLY__ -D__LINKER__ $(MAKE_DEP) -D$(IMAGE) -o $$@ $$< -include $(DEP) From 1dcc28cfbac5dae3992ad9581f9ea68f6cb339c1 Mon Sep 17 00:00:00 2001 From: Daniel Boulby Date: Tue, 18 Sep 2018 11:45:51 +0100 Subject: [PATCH 4/9] Introduce RECLAIM_INIT_CODE build flag This patch introduces a build flag "RECLAIM_INIT_CODE" to mark boot time code which allows platforms to place this memory in an appropriate section to be reclaimed later. This features is primarily targeted for BL31. Appropriate documentation updates are also done. Change-Id: If0ca062851614805d769c332c771083d46599194 Signed-off-by: Daniel Boulby --- Makefile | 1 + docs/firmware-design.rst | 23 +++++++++++++++++++++++ include/lib/libc/cdefs.h | 9 +++++++++ make_helpers/defaults.mk | 4 ++++ 4 files changed, 37 insertions(+) diff --git a/Makefile b/Makefile index 23a1b0a37..d487eae7f 100644 --- a/Makefile +++ b/Makefile @@ -634,6 +634,7 @@ $(eval $(call add_define,PSCI_EXTENDED_STATE_ID)) $(eval $(call add_define,RAS_EXTENSION)) $(eval $(call add_define,RESET_TO_BL31)) $(eval $(call add_define,SEPARATE_CODE_AND_RODATA)) +$(eval $(call add_define,RECLAIM_INIT_CODE)) $(eval $(call add_define,SMCCC_MAJOR_VERSION)) $(eval $(call add_define,SPD_${SPD})) $(eval $(call add_define,SPIN_ON_BL1_EXIT)) diff --git a/docs/firmware-design.rst b/docs/firmware-design.rst index 79bdec98f..7cc74855d 100644 --- a/docs/firmware-design.rst +++ b/docs/firmware-design.rst @@ -2336,6 +2336,29 @@ implement: SUBSCRIBE_TO_EVENT(foo, foo_handler); + +Reclaiming the BL31 initialization code +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A significant amount of the code used for the initialization of BL31 is never +needed again after boot time. In order to reduce the runtime memory +footprint, the memory used for this code can be reclaimed after initialization +has finished and be used for runtime data. + +The build option ``RECLAIM_INIT_CODE`` can be set to mark this boot time code +with a ``.text.init.*`` attribute which can be filtered and placed suitably +within the BL image for later reclaimation by the platform. The platform can +specify the fiter and the memory region for this init section in BL31 via the +plat.ld.S linker script. For example, on the FVP, this section is placed +overlapping the secondary CPU stacks so that after the cold boot is done, this +memory can be reclaimed for the stacks. The init memory section is initially +mapped with ``RO``, ``EXECUTE`` attributes. After BL31 initilization has +completed, the FVP changes the attributes of this section to ``RW``, +``EXECUTE_NEVER`` allowing it to be used for runtime data. The memory attributes +are changed within the ``bl31_plat_runtime_setup`` platform hook. The init +section section can be reclaimed for any data which is accessed after cold +boot initialization and it is upto the platform to make the decision. + Performance Measurement Framework --------------------------------- diff --git a/include/lib/libc/cdefs.h b/include/lib/libc/cdefs.h index b1d10ccce..0d0072254 100644 --- a/include/lib/libc/cdefs.h +++ b/include/lib/libc/cdefs.h @@ -14,6 +14,15 @@ #define __unused __attribute__((__unused__)) #define __aligned(x) __attribute__((__aligned__(x))) #define __section(x) __attribute__((__section__(x))) +#if RECLAIM_INIT_CODE +/* + * Add each function to a section that is unique so the functions can still + * be garbage collected + */ +#define __init __section(".text.init." __FILE__ "." __XSTRING(__LINE__)) +#else +#define __init +#endif #define __printflike(fmtarg, firstvararg) \ __attribute__((__format__ (__printf__, fmtarg, firstvararg))) diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index 7df4cd286..435de20e3 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -146,6 +146,10 @@ SDEI_SUPPORT := 0 # platform Makefile is free to override this value. SEPARATE_CODE_AND_RODATA := 0 +# If the BL31 image initialisation code is recalimed after use for the secondary +# cores stack +RECLAIM_INIT_CODE := 0 + # Default to SMCCC Version 1.X SMCCC_MAJOR_VERSION := 1 From 87c851349847a608f12623b7fd397956982e41b6 Mon Sep 17 00:00:00 2001 From: Daniel Boulby Date: Thu, 20 Sep 2018 14:12:46 +0100 Subject: [PATCH 5/9] Mark BL31 initialization functions Mark the initialization functions in BL31, such as context management, EHF, RAS and PSCI as __init so that they can be reclaimed by the platform when no longer needed Change-Id: I7446aeee3dde8950b0f410cb766b7a2312c20130 Signed-off-by: Daniel Boulby --- bl31/bl31_main.c | 4 ++-- bl31/ehf.c | 2 +- common/runtime_svc.c | 2 +- lib/el3_runtime/aarch64/context_mgmt.c | 2 +- lib/extensions/ras/ras_common.c | 2 +- lib/psci/psci_common.c | 2 +- lib/psci/psci_setup.c | 8 ++++---- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/bl31/bl31_main.c b/bl31/bl31_main.c index 4b7f63c21..62bea010b 100644 --- a/bl31/bl31_main.c +++ b/bl31/bl31_main.c @@ -57,7 +57,7 @@ uintptr_t get_arm_std_svc_args(unsigned int svc_mask) /******************************************************************************* * Simple function to initialise all BL31 helper libraries. ******************************************************************************/ -void bl31_lib_init(void) +void __init bl31_lib_init(void) { cm_init(); } @@ -149,7 +149,7 @@ uint32_t bl31_get_next_image_type(void) * This function programs EL3 registers and performs other setup to enable entry * into the next image after BL31 at the next ERET. ******************************************************************************/ -void bl31_prepare_next_image_entry(void) +void __init bl31_prepare_next_image_entry(void) { entry_point_info_t *next_image_info; uint32_t image_type; diff --git a/bl31/ehf.c b/bl31/ehf.c index 3d6d674bf..fa036cb1c 100644 --- a/bl31/ehf.c +++ b/bl31/ehf.c @@ -451,7 +451,7 @@ static uint64_t ehf_el3_interrupt_handler(uint32_t id, uint32_t flags, /* * Initialize the EL3 exception handling. */ -void ehf_init(void) +void __init ehf_init(void) { unsigned int flags = 0; int ret __unused; diff --git a/common/runtime_svc.c b/common/runtime_svc.c index ad564f566..03f7f7ef3 100644 --- a/common/runtime_svc.c +++ b/common/runtime_svc.c @@ -93,7 +93,7 @@ static int32_t validate_rt_svc_desc(const rt_svc_desc_t *desc) * The unique oen is used as an index into the 'rt_svc_descs_indices' array. * The index of the runtime service descriptor is stored at this index. ******************************************************************************/ -void runtime_svc_init(void) +void __init runtime_svc_init(void) { int rc = 0; unsigned int index, start_idx, end_idx; diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c index ee5fe4f9d..acc8d6d26 100644 --- a/lib/el3_runtime/aarch64/context_mgmt.c +++ b/lib/el3_runtime/aarch64/context_mgmt.c @@ -36,7 +36,7 @@ * which will used for programming an entry into a lower EL. The same context * will used to save state upon exception entry from that EL. ******************************************************************************/ -void cm_init(void) +void __init cm_init(void) { /* * The context management library has only global data to intialize, but diff --git a/lib/extensions/ras/ras_common.c b/lib/extensions/ras/ras_common.c index 2e65eebb9..f39e5f5f1 100644 --- a/lib/extensions/ras/ras_common.c +++ b/lib/extensions/ras/ras_common.c @@ -128,7 +128,7 @@ static int ras_interrupt_handler(uint32_t intr_raw, uint32_t flags, return 0; } -void ras_init(void) +void __init ras_init(void) { #if ENABLE_ASSERTIONS /* Check RAS interrupts are sorted */ diff --git a/lib/psci/psci_common.c b/lib/psci/psci_common.c index b877b4ba2..adce843aa 100644 --- a/lib/psci/psci_common.c +++ b/lib/psci/psci_common.c @@ -216,7 +216,7 @@ static void psci_set_req_local_pwr_state(unsigned int pwrlvl, /****************************************************************************** * This function initializes the psci_req_local_pwr_states. *****************************************************************************/ -void psci_init_req_local_pwr_states(void) +void __init psci_init_req_local_pwr_states(void) { /* Initialize the requested state of all non CPU power domains as OFF */ unsigned int pwrlvl; diff --git a/lib/psci/psci_setup.c b/lib/psci/psci_setup.c index e59e163ea..6b3081eb5 100644 --- a/lib/psci/psci_setup.c +++ b/lib/psci/psci_setup.c @@ -32,7 +32,7 @@ unsigned int psci_caps; * Function which initializes the 'psci_non_cpu_pd_nodes' or the * 'psci_cpu_pd_nodes' corresponding to the power level. ******************************************************************************/ -static void psci_init_pwr_domain_node(unsigned char node_idx, +static void __init psci_init_pwr_domain_node(unsigned char node_idx, unsigned int parent_idx, unsigned char level) { @@ -80,7 +80,7 @@ static void psci_init_pwr_domain_node(unsigned char node_idx, * mapping of the CPUs to indices via plat_core_pos_by_mpidr() and * plat_my_core_pos() APIs. *******************************************************************************/ -static void psci_update_pwrlvl_limits(void) +static void __init psci_update_pwrlvl_limits(void) { int j, cpu_idx; unsigned int nodes_idx[PLAT_MAX_PWR_LVL] = {0}; @@ -107,7 +107,7 @@ static void psci_update_pwrlvl_limits(void) * informs the number of root power domains. The parent nodes of the root nodes * will point to an invalid entry(-1). ******************************************************************************/ -static void populate_power_domain_tree(const unsigned char *topology) +static void __init populate_power_domain_tree(const unsigned char *topology) { unsigned int i, j = 0U, num_nodes_at_lvl = 1U, num_nodes_at_next_lvl; unsigned int node_index = 0U, num_children; @@ -184,7 +184,7 @@ static void populate_power_domain_tree(const unsigned char *topology) * | CPU 0 | CPU 1 | CPU 2 | CPU 3 | * ------------------------------------------------ ******************************************************************************/ -int psci_setup(const psci_lib_args_t *lib_args) +int __init psci_setup(const psci_lib_args_t *lib_args) { const unsigned char *topology_tree; From 4d010d0dc0793d2ea1545c1671a2fc2d151e6af5 Mon Sep 17 00:00:00 2001 From: Daniel Boulby Date: Tue, 18 Sep 2018 13:26:03 +0100 Subject: [PATCH 6/9] plat/arm: Mark arm platform initialization functions Mark the initialization functions found in the BL31 boot sequence as __init so they can be reclaimed when no longer needed. Change-Id: I687a89346419c7710ef5097feaa325d83c527697 Signed-off-by: Daniel Boulby --- plat/arm/board/fvp/drivers/pwrc/fvp_pwrc.c | 4 ++-- plat/arm/board/fvp/fvp_bl31_setup.c | 4 ++-- plat/arm/board/fvp/fvp_common.c | 4 ++-- plat/arm/common/arm_bl31_setup.c | 8 ++++---- plat/arm/common/arm_common.c | 2 +- plat/arm/common/arm_console.c | 2 +- plat/arm/common/arm_pm.c | 2 +- plat/arm/css/drivers/mhu/css_mhu.c | 4 ++-- plat/arm/css/drivers/scp/css_pm_scmi.c | 2 +- plat/arm/css/sgi/sgi_interconnect.c | 2 +- plat/arm/css/sgm/sgm_interconnect.c | 4 +++- 11 files changed, 20 insertions(+), 18 deletions(-) diff --git a/plat/arm/board/fvp/drivers/pwrc/fvp_pwrc.c b/plat/arm/board/fvp/drivers/pwrc/fvp_pwrc.c index 5948e149f..b17446c10 100644 --- a/plat/arm/board/fvp/drivers/pwrc/fvp_pwrc.c +++ b/plat/arm/board/fvp/drivers/pwrc/fvp_pwrc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -70,7 +70,7 @@ void fvp_pwrc_write_pcoffr(u_register_t mpidr) } /* Nothing else to do here apart from initializing the lock */ -void plat_arm_pwrc_setup(void) +void __init plat_arm_pwrc_setup(void) { arm_lock_init(); } diff --git a/plat/arm/board/fvp/fvp_bl31_setup.c b/plat/arm/board/fvp/fvp_bl31_setup.c index ea1170859..1c8804f10 100644 --- a/plat/arm/board/fvp/fvp_bl31_setup.c +++ b/plat/arm/board/fvp/fvp_bl31_setup.c @@ -10,8 +10,8 @@ #include #include "fvp_private.h" -void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, - u_register_t arg2, u_register_t arg3) +void __init bl31_early_platform_setup2(u_register_t arg0, + u_register_t arg1, u_register_t arg2, u_register_t arg3) { arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c index 3f7857eb8..aa4f8398d 100644 --- a/plat/arm/board/fvp/fvp_common.c +++ b/plat/arm/board/fvp/fvp_common.c @@ -241,7 +241,7 @@ const struct secure_partition_boot_info *plat_get_secure_partition_boot_info( * these platforms. This information is stored in a per-BL array to allow the * code to take the correct path.Per BL platform configuration. ******************************************************************************/ -void fvp_config_setup(void) +void __init fvp_config_setup(void) { unsigned int rev, hbi, bld, arch, sys_id; @@ -331,7 +331,7 @@ void fvp_config_setup(void) } -void fvp_interconnect_init(void) +void __init fvp_interconnect_init(void) { #if FVP_INTERCONNECT_DRIVER == FVP_CCN if (ccn_get_part0_id(PLAT_ARM_CCN_BASE) != CCN_502_PART0_ID) { diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c index ce799b0ff..c54566390 100644 --- a/plat/arm/common/arm_bl31_setup.c +++ b/plat/arm/common/arm_bl31_setup.c @@ -71,7 +71,7 @@ struct entry_point_info *bl31_plat_get_next_image_ep_info(uint32_t type) * while creating page tables. BL2 has flushed this information to memory, so * we are guaranteed to pick up good data. ******************************************************************************/ -void arm_bl31_early_platform_setup(void *from_bl2, uintptr_t soc_fw_config, +void __init arm_bl31_early_platform_setup(void *from_bl2, uintptr_t soc_fw_config, uintptr_t hw_config, void *plat_params_from_bl2) { /* Initialize the console to provide early debug support */ @@ -235,7 +235,7 @@ void arm_bl31_plat_runtime_setup(void) arm_console_runtime_init(); } -void bl31_platform_setup(void) +void __init bl31_platform_setup(void) { arm_bl31_platform_setup(); } @@ -251,7 +251,7 @@ void bl31_plat_runtime_setup(void) * architectural setup (bl31_arch_setup()) does not do anything platform * specific. ******************************************************************************/ -void arm_bl31_plat_arch_setup(void) +void __init arm_bl31_plat_arch_setup(void) { const mmap_region_t bl_regions[] = { MAP_BL31_TOTAL, @@ -273,7 +273,7 @@ void arm_bl31_plat_arch_setup(void) arm_setup_romlib(); } -void bl31_plat_arch_setup(void) +void __init bl31_plat_arch_setup(void) { arm_bl31_plat_arch_setup(); } diff --git a/plat/arm/common/arm_common.c b/plat/arm/common/arm_common.c index 28ff5d9b9..ae06ef280 100644 --- a/plat/arm/common/arm_common.c +++ b/plat/arm/common/arm_common.c @@ -41,7 +41,7 @@ void arm_setup_romlib(void) * - Coherent memory region, if applicable. */ -void arm_setup_page_tables(const mmap_region_t bl_regions[], +void __init arm_setup_page_tables(const mmap_region_t bl_regions[], const mmap_region_t plat_regions[]) { #if LOG_LEVEL >= LOG_LEVEL_VERBOSE diff --git a/plat/arm/common/arm_console.c b/plat/arm/common/arm_console.c index 6c8587fc4..bd3dca17f 100644 --- a/plat/arm/common/arm_console.c +++ b/plat/arm/common/arm_console.c @@ -19,7 +19,7 @@ static console_pl011_t arm_runtime_console; #endif /* Initialize the console to provide early debug support */ -void arm_console_boot_init(void) +void __init arm_console_boot_init(void) { #if MULTI_CONSOLE_API int rc = console_pl011_register(PLAT_ARM_BOOT_UART_BASE, diff --git a/plat/arm/common/arm_pm.c b/plat/arm/common/arm_pm.c index bf548c10c..85efc7dd2 100644 --- a/plat/arm/common/arm_pm.c +++ b/plat/arm/common/arm_pm.c @@ -208,7 +208,7 @@ void plat_arm_program_trusted_mailbox(uintptr_t address) * The ARM Standard platform definition of platform porting API * `plat_setup_psci_ops`. ******************************************************************************/ -int plat_setup_psci_ops(uintptr_t sec_entrypoint, +int __init plat_setup_psci_ops(uintptr_t sec_entrypoint, const plat_psci_ops_t **psci_ops) { *psci_ops = plat_arm_psci_override_pm_ops(&plat_arm_psci_pm_ops); diff --git a/plat/arm/css/drivers/mhu/css_mhu.c b/plat/arm/css/drivers/mhu/css_mhu.c index 30492a695..7b3331756 100644 --- a/plat/arm/css/drivers/mhu/css_mhu.c +++ b/plat/arm/css/drivers/mhu/css_mhu.c @@ -81,7 +81,7 @@ void mhu_secure_message_end(unsigned int slot_id) arm_lock_release(); } -void mhu_secure_init(void) +void __init mhu_secure_init(void) { arm_lock_init(); @@ -93,7 +93,7 @@ void mhu_secure_init(void) assert(mmio_read_32(PLAT_CSS_MHU_BASE + CPU_INTR_S_STAT) == 0); } -void plat_arm_pwrc_setup(void) +void __init plat_arm_pwrc_setup(void) { mhu_secure_init(); } diff --git a/plat/arm/css/drivers/scp/css_pm_scmi.c b/plat/arm/css/drivers/scp/css_pm_scmi.c index 258c1c29c..d280101d6 100644 --- a/plat/arm/css/drivers/scp/css_pm_scmi.c +++ b/plat/arm/css/drivers/scp/css_pm_scmi.c @@ -328,7 +328,7 @@ static int scmi_ap_core_init(scmi_channel_t *ch) return 0; } -void plat_arm_pwrc_setup(void) +void __init plat_arm_pwrc_setup(void) { channel.info = &plat_css_scmi_plat_info; channel.lock = ARM_LOCK_GET_INSTANCE; diff --git a/plat/arm/css/sgi/sgi_interconnect.c b/plat/arm/css/sgi/sgi_interconnect.c index f4e7676a4..325b5b152 100644 --- a/plat/arm/css/sgi/sgi_interconnect.c +++ b/plat/arm/css/sgi/sgi_interconnect.c @@ -17,7 +17,7 @@ /****************************************************************************** * Helper function to initialize ARM interconnect driver. *****************************************************************************/ -void plat_arm_interconnect_init(void) +void __init plat_arm_interconnect_init(void) { } diff --git a/plat/arm/css/sgm/sgm_interconnect.c b/plat/arm/css/sgm/sgm_interconnect.c index 301ea84f0..5b45341b9 100644 --- a/plat/arm/css/sgm/sgm_interconnect.c +++ b/plat/arm/css/sgm/sgm_interconnect.c @@ -4,6 +4,8 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include + /* * As the SGM platform supports FCM (with automatic interconnect * enter/exit), we should not do anything in these interface functions. @@ -13,7 +15,7 @@ /****************************************************************************** * Helper function to initialize ARM interconnect driver. *****************************************************************************/ -void plat_arm_interconnect_init(void) +void __init plat_arm_interconnect_init(void) { } From aff2863fe616901fc4194381c7ab1839aa70d373 Mon Sep 17 00:00:00 2001 From: Daniel Boulby Date: Thu, 30 Aug 2018 16:48:56 +0100 Subject: [PATCH 7/9] Mark xlat tables initialization code Mark the xlat tables code only used in BL31 initialization as __init to be reclaimed once no longer needed Change-Id: I3106bfd994706a57c578624573bcfa525fbbd3c4 Signed-off-by: Daniel Boulby --- lib/xlat_tables_v2/xlat_tables_context.c | 2 +- lib/xlat_tables_v2/xlat_tables_core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/xlat_tables_v2/xlat_tables_context.c b/lib/xlat_tables_v2/xlat_tables_context.c index 4a4cb946c..f18077452 100644 --- a/lib/xlat_tables_v2/xlat_tables_context.c +++ b/lib/xlat_tables_v2/xlat_tables_context.c @@ -56,7 +56,7 @@ int mmap_remove_dynamic_region(uintptr_t base_va, size_t size) #endif /* PLAT_XLAT_TABLES_DYNAMIC */ -void init_xlat_tables(void) +void __init init_xlat_tables(void) { assert(tf_xlat_ctx.xlat_regime == EL_REGIME_INVALID); diff --git a/lib/xlat_tables_v2/xlat_tables_core.c b/lib/xlat_tables_v2/xlat_tables_core.c index d9837ff82..3b6c6bcb2 100644 --- a/lib/xlat_tables_v2/xlat_tables_core.c +++ b/lib/xlat_tables_v2/xlat_tables_core.c @@ -1012,7 +1012,7 @@ int mmap_remove_dynamic_region_ctx(xlat_ctx_t *ctx, uintptr_t base_va, #endif /* PLAT_XLAT_TABLES_DYNAMIC */ -void init_xlat_tables_ctx(xlat_ctx_t *ctx) +void __init init_xlat_tables_ctx(xlat_ctx_t *ctx) { assert(ctx != NULL); assert(!ctx->initialized); From c9263e62a749610c880bdc693e4e644bd9091611 Mon Sep 17 00:00:00 2001 From: Daniel Boulby Date: Tue, 18 Sep 2018 13:36:39 +0100 Subject: [PATCH 8/9] Mark GICV3, CCI and CCN boot time code as init Mark the GICv3, CCI and CCN code only used in Bl31 initialization with __init to be reclaimed once no longer needed. Change-Id: I3d77f36758450d9d1d87ecc60bc1c63fe4082667 Signed-off-by: Daniel Boulby --- drivers/arm/cci/cci.c | 3 ++- drivers/arm/ccn/ccn.c | 6 +++--- drivers/arm/gic/v3/gicv3_main.c | 4 ++-- drivers/arm/smmu/smmu_v3.c | 9 +++++---- plat/arm/common/arm_cci.c | 4 ++-- plat/arm/common/arm_ccn.c | 4 ++-- plat/arm/common/arm_gicv3.c | 4 ++-- 7 files changed, 18 insertions(+), 16 deletions(-) diff --git a/drivers/arm/cci/cci.c b/drivers/arm/cci/cci.c index 91245d46c..605971cac 100644 --- a/drivers/arm/cci/cci.c +++ b/drivers/arm/cci/cci.c @@ -107,7 +107,8 @@ static int get_slave_ports(unsigned int part_num) } #endif /* ENABLE_ASSERTIONS */ -void cci_init(uintptr_t base, const int *map, unsigned int num_cci_masters) +void __init cci_init(uintptr_t base, const int *map, + unsigned int num_cci_masters) { assert(map != NULL); assert(base != 0U); diff --git a/drivers/arm/ccn/ccn.c b/drivers/arm/ccn/ccn.c index afb7d9d3b..910cd7cd2 100644 --- a/drivers/arm/ccn/ccn.c +++ b/drivers/arm/ccn/ccn.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 */ @@ -167,7 +167,7 @@ static unsigned int ccn_get_rn_master_info(uintptr_t periphbase, * It compares this with the information provided by the platform to determine * the validity of the latter. ******************************************************************************/ -static void ccn_validate_plat_params(const ccn_desc_t *plat_desc) +static void __init ccn_validate_plat_params(const ccn_desc_t *plat_desc) { unsigned int master_id, num_rn_masters; rn_info_t info = { {0} }; @@ -208,7 +208,7 @@ static void ccn_validate_plat_params(const ccn_desc_t *plat_desc) * simultaneous CCN operations at runtime (only BL31) to add and remove Request * nodes from coherency. ******************************************************************************/ -void ccn_init(const ccn_desc_t *plat_desc) +void __init ccn_init(const ccn_desc_t *plat_desc) { #if ENABLE_ASSERTIONS ccn_validate_plat_params(plat_desc); diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c index 5af7e4027..60f2e108a 100644 --- a/drivers/arm/gic/v3/gicv3_main.c +++ b/drivers/arm/gic/v3/gicv3_main.c @@ -55,7 +55,7 @@ static spinlock_t gic_lock; * This function initialises the ARM GICv3 driver in EL3 with provided platform * inputs. ******************************************************************************/ -void gicv3_driver_init(const gicv3_driver_data_t *plat_driver_data) +void __init gicv3_driver_init(const gicv3_driver_data_t *plat_driver_data) { unsigned int gic_version; @@ -129,7 +129,7 @@ void gicv3_driver_init(const gicv3_driver_data_t *plat_driver_data) * This function initialises the GIC distributor interface based upon the data * provided by the platform while initialising the driver. ******************************************************************************/ -void gicv3_distif_init(void) +void __init gicv3_distif_init(void) { unsigned int bitmap = 0; diff --git a/drivers/arm/smmu/smmu_v3.c b/drivers/arm/smmu/smmu_v3.c index ddb99634e..78a9ffa6d 100644 --- a/drivers/arm/smmu/smmu_v3.c +++ b/drivers/arm/smmu/smmu_v3.c @@ -4,21 +4,22 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include #include #include #include -static inline uint32_t smmuv3_read_s_idr1(uintptr_t base) +static inline uint32_t __init smmuv3_read_s_idr1(uintptr_t base) { return mmio_read_32(base + SMMU_S_IDR1); } -static inline uint32_t smmuv3_read_s_init(uintptr_t base) +static inline uint32_t __init smmuv3_read_s_init(uintptr_t base) { return mmio_read_32(base + SMMU_S_INIT); } -static inline void smmuv3_write_s_init(uintptr_t base, uint32_t value) +static inline void __init smmuv3_write_s_init(uintptr_t base, uint32_t value) { mmio_write_32(base + SMMU_S_INIT, value); } @@ -34,7 +35,7 @@ static inline bool smmuv3_inval_pending(uintptr_t base) * * Returns 0 on success, and -1 on failure. */ -int smmuv3_init(uintptr_t smmu_base) +int __init smmuv3_init(uintptr_t smmu_base) { uint32_t idr1_reg; diff --git a/plat/arm/common/arm_cci.c b/plat/arm/common/arm_cci.c index fc24cc353..6505b9174 100644 --- a/plat/arm/common/arm_cci.c +++ b/plat/arm/common/arm_cci.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -27,7 +27,7 @@ static const int cci_map[] = { /****************************************************************************** * Helper function to initialize ARM CCI driver. *****************************************************************************/ -void plat_arm_interconnect_init(void) +void __init plat_arm_interconnect_init(void) { cci_init(PLAT_ARM_CCI_BASE, cci_map, ARRAY_SIZE(cci_map)); } diff --git a/plat/arm/common/arm_ccn.c b/plat/arm/common/arm_ccn.c index 84a529f42..ddf3286d7 100644 --- a/plat/arm/common/arm_ccn.c +++ b/plat/arm/common/arm_ccn.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -34,7 +34,7 @@ CASSERT(PLAT_ARM_CLUSTER_COUNT == ARRAY_SIZE(master_to_rn_id_map), /****************************************************************************** * Helper function to initialize ARM CCN driver. *****************************************************************************/ -void plat_arm_interconnect_init(void) +void __init plat_arm_interconnect_init(void) { ccn_init(&arm_ccn_desc); } diff --git a/plat/arm/common/arm_gicv3.c b/plat/arm/common/arm_gicv3.c index b8ffd6bc4..e9e8a74d9 100644 --- a/plat/arm/common/arm_gicv3.c +++ b/plat/arm/common/arm_gicv3.c @@ -68,7 +68,7 @@ static const gicv3_driver_data_t arm_gic_data __unused = { .mpidr_to_core_pos = arm_gicv3_mpidr_hash }; -void plat_arm_gic_driver_init(void) +void __init plat_arm_gic_driver_init(void) { /* * The GICv3 driver is initialized in EL3 and does not need @@ -85,7 +85,7 @@ void plat_arm_gic_driver_init(void) /****************************************************************************** * ARM common helper to initialize the GIC. Only invoked by BL31 *****************************************************************************/ -void plat_arm_gic_init(void) +void __init plat_arm_gic_init(void) { gicv3_distif_init(); gicv3_rdistif_init(plat_my_core_pos()); From cb4adb0d8c36e6650b8b74d27e8c7417067e8cd5 Mon Sep 17 00:00:00 2001 From: Daniel Boulby Date: Tue, 18 Sep 2018 11:52:49 +0100 Subject: [PATCH 9/9] FVP: Reclaim init code for the stack Map the initialization code for BL31 to overlap with the memory required for the secondary cores stack. Once BL31 has been initialized the memory can be remapped to RW data so that it can be used for secondary cores stacks. By moving code from .text to .text.init the size of the BL31 image is decreased by a page. Split arm_common.ld.S into two linker scripts, one for tzc_dram (arm_tzc_dram.ld.S) and one for reclaiming initialization code (arm_reclaim_init.ld.S) so that platforms can chose which memory regions they wish to include. Change-Id: I648e88f3eda1aa71765744cf34343ecda9320b32 Signed-off-by: Daniel Boulby --- include/plat/arm/common/arm_def.h | 2 +- include/plat/arm/common/arm_reclaim_init.ld.S | 36 ++++++++++++++++++ .../{arm_common.ld.S => arm_tzc_dram.ld.S} | 6 +-- include/plat/arm/common/plat_arm.h | 6 +++ plat/arm/board/fvp/include/plat.ld.S | 3 +- plat/arm/board/fvp/platform.mk | 3 ++ plat/arm/common/arm_bl31_setup.c | 38 ++++++++++++++++++- plat/arm/common/arm_common.c | 1 + plat/arm/common/arm_common.mk | 11 ++++++ 9 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 include/plat/arm/common/arm_reclaim_init.ld.S rename include/plat/arm/common/{arm_common.ld.S => arm_tzc_dram.ld.S} (87%) diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h index 23cd12f51..8d81af960 100644 --- a/include/plat/arm/common/arm_def.h +++ b/include/plat/arm/common/arm_def.h @@ -280,7 +280,7 @@ * The max number of regions like RO(code), coherent and data required by * different BL stages which need to be mapped in the MMU. */ -# define ARM_BL_REGIONS 4 +#define ARM_BL_REGIONS 5 #define MAX_MMAP_REGIONS (PLAT_ARM_MMAP_ENTRIES + \ ARM_BL_REGIONS) diff --git a/include/plat/arm/common/arm_reclaim_init.ld.S b/include/plat/arm/common/arm_reclaim_init.ld.S new file mode 100644 index 000000000..8f22170fe --- /dev/null +++ b/include/plat/arm/common/arm_reclaim_init.ld.S @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ARM_RECLAIM_INIT_LD_S +#define ARM_RECLAIM_INIT_LD_S + +SECTIONS +{ + .init __STACKS_START__ : { + . = . + PLATFORM_STACK_SIZE; + . = ALIGN(PAGE_SIZE); + __INIT_CODE_START__ = .; + /* + * Exclude PSCI initialization functions to ensure the init section + * does not become larger than the overlaid stack region + */ + *(EXCLUDE_FILE (*psci_setup.o).text.init*) + __INIT_CODE_UNALIGNED__ = .; + . = ALIGN(PAGE_SIZE); + __INIT_CODE_END__ = .; + } >RAM + +#ifdef BL31_PROGBITS_LIMIT + ASSERT(__INIT_CODE_END__ <= BL31_PROGBITS_LIMIT, + "BL31 init has exceeded progbits limit.") +#endif + +#if RECLAIM_INIT_CODE + ASSERT(__INIT_CODE_END__ <= __STACKS_END__, + "Init code ends past the end of the stacks") +#endif +} + +#endif /* ARM_RECLAIM_INIT_LD_S */ diff --git a/include/plat/arm/common/arm_common.ld.S b/include/plat/arm/common/arm_tzc_dram.ld.S similarity index 87% rename from include/plat/arm/common/arm_common.ld.S rename to include/plat/arm/common/arm_tzc_dram.ld.S index 3f6e29b0a..df951e117 100644 --- a/include/plat/arm/common/arm_common.ld.S +++ b/include/plat/arm/common/arm_tzc_dram.ld.S @@ -3,8 +3,8 @@ * * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef __ARM_COMMON_LD_S__ -#define __ARM_COMMON_LD_S__ +#ifndef ARM_TZC_DRAM_LD_S__ +#define ARM_TZC_DRAM_LD_S__ #include @@ -27,4 +27,4 @@ SECTIONS } >EL3_SEC_DRAM } -#endif /* __ARM_COMMON_LD_S__ */ +#endif /* ARM_TZC_DRAM_LD_S__ */ diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h index 3f344abce..d543894d7 100644 --- a/include/plat/arm/common/plat_arm.h +++ b/include/plat/arm/common/plat_arm.h @@ -220,6 +220,12 @@ void arm_bl2_dyn_cfg_init(void); void arm_bl1_set_mbedtls_heap(void); int arm_get_mbedtls_heap(void **heap_addr, size_t *heap_size); +/* + * Free the memory storing initialization code only used during an images boot + * time so it can be reclaimed for runtime data + */ +void arm_free_init_memory(void); + /* * Mandatory functions required in ARM standard platforms */ diff --git a/plat/arm/board/fvp/include/plat.ld.S b/plat/arm/board/fvp/include/plat.ld.S index 24c3debd9..f2a3ea6a4 100644 --- a/plat/arm/board/fvp/include/plat.ld.S +++ b/plat/arm/board/fvp/include/plat.ld.S @@ -6,6 +6,7 @@ #ifndef __PLAT_LD_S__ #define __PLAT_LD_S__ -#include +#include +#include #endif /* __PLAT_LD_S__ */ diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index 4cd6a24de..9bd3bde65 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -201,6 +201,9 @@ ENABLE_AMU := 1 # Enable dynamic mitigation support by default DYNAMIC_WORKAROUND_CVE_2018_3639 := 1 +# Enable reclaiming of BL31 initialisation code for secondary cores stacks for FVP +RECLAIM_INIT_CODE := 1 + ifeq (${ENABLE_AMU},1) BL31_SOURCES += lib/cpus/aarch64/cortex_a75_pubsub.c \ lib/cpus/aarch64/cortex_ares_pubsub.c \ diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c index c54566390..ed2c3fbce 100644 --- a/plat/arm/common/arm_bl31_setup.c +++ b/plat/arm/common/arm_bl31_setup.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include /* * Placeholder variables for copying the arguments that have been passed to @@ -35,10 +37,20 @@ CASSERT(BL31_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_bl31_base_overflows); #pragma weak bl31_plat_arch_setup #pragma weak bl31_plat_get_next_image_ep_info -#define MAP_BL31_TOTAL MAP_REGION_FLAT( \ +#define MAP_BL31_TOTAL MAP_REGION_FLAT( \ BL31_BASE, \ BL31_END - BL31_BASE, \ MT_MEMORY | MT_RW | MT_SECURE) +#if RECLAIM_INIT_CODE +IMPORT_SYM(unsigned long, __INIT_CODE_START__, BL_INIT_CODE_BASE); +IMPORT_SYM(unsigned long, __INIT_CODE_END__, BL_INIT_CODE_END); + +#define MAP_BL_INIT_CODE MAP_REGION_FLAT( \ + BL_INIT_CODE_BASE, \ + BL_INIT_CODE_END \ + - BL_INIT_CODE_BASE, \ + MT_CODE | MT_SECURE) +#endif /******************************************************************************* * Return a pointer to the 'entry_point_info' structure of the next image for the @@ -233,8 +245,29 @@ 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 RECLAIM_INIT_CODE +/* + * Zero out and make RW memory used to store image boot time code so it can + * be reclaimed during runtime + */ +void arm_free_init_memory(void) +{ + int ret = xlat_change_mem_attributes(BL_INIT_CODE_BASE, + BL_INIT_CODE_END - BL_INIT_CODE_BASE, + MT_RW_DATA); + + if (ret != 0) { + ERROR("Could not reclaim initialization code"); + panic(); + } +} +#endif + void __init bl31_platform_setup(void) { arm_bl31_platform_setup(); @@ -255,6 +288,9 @@ void __init arm_bl31_plat_arch_setup(void) { const mmap_region_t bl_regions[] = { MAP_BL31_TOTAL, +#if RECLAIM_INIT_CODE + MAP_BL_INIT_CODE, +#endif ARM_MAP_BL_RO, #if USE_ROMLIB ARM_MAP_ROMLIB_CODE, diff --git a/plat/arm/common/arm_common.c b/plat/arm/common/arm_common.c index ae06ef280..a21d189e9 100644 --- a/plat/arm/common/arm_common.c +++ b/plat/arm/common/arm_common.c @@ -38,6 +38,7 @@ void arm_setup_romlib(void) * as an array specifying the generic memory regions which can be; * - Code section; * - Read-only data section; + * - Init code section, if applicable * - Coherent memory region, if applicable. */ diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk index a8df5bad3..276f7801c 100644 --- a/plat/arm/common/arm_common.mk +++ b/plat/arm/common/arm_common.mk @@ -273,3 +273,14 @@ endif include ${IMG_PARSER_LIB_MK} endif + +# RECLAIM_INIT_CODE can only be set when LOAD_IMAGE_V2=2 and xlat tables v2 +# are used +ifeq (${RECLAIM_INIT_CODE}, 1) + ifeq (${LOAD_IMAGE_V2}, 0) + $(error "LOAD_IMAGE_V2 must be enabled to use RECLAIM_INIT_CODE") + endif + ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1) + $(error "To reclaim init code xlat tables v2 must be used") + endif +endif