From 322af23445fe7a86eaad335b8a0f2ed523f5c1df Mon Sep 17 00:00:00 2001 From: Raymond Mao Date: Wed, 28 Jun 2023 15:07:15 -0700 Subject: feat(qemu): implement firmware handoff on qemu Implement firmware handoff from BL2 to BL33 on qemu platform compliant to Firmware handoff specification v0.9. Change-Id: Id8d5206a71ef6ec97cf3c97995de328ebf0600cc Signed-off-by: Raymond Mao --- plat/qemu/common/qemu_bl2_setup.c | 82 +++++++++++++++++++++++++++++++++-- plat/qemu/common/qemu_common.c | 17 ++++++++ plat/qemu/common/qemu_image_load.c | 5 ++- plat/qemu/common/qemu_private.h | 4 +- plat/qemu/qemu/include/platform_def.h | 20 +++++++-- plat/qemu/qemu/platform.mk | 4 ++ 6 files changed, 123 insertions(+), 9 deletions(-) (limited to 'plat') diff --git a/plat/qemu/common/qemu_bl2_setup.c b/plat/qemu/common/qemu_bl2_setup.c index c4d235e0a..231f23a77 100644 --- a/plat/qemu/common/qemu_bl2_setup.c +++ b/plat/qemu/common/qemu_bl2_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -18,6 +18,9 @@ #include #include #include +#if TRANSFER_LIST +#include +#endif #include #include @@ -48,6 +51,9 @@ /* Data structure which holds the extents of the trusted SRAM for BL2 */ static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE); +#if TRANSFER_LIST +static struct transfer_list_header *bl2_tl; +#endif void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3) @@ -73,6 +79,9 @@ static void security_setup(void) static void update_dt(void) { +#if TRANSFER_LIST + struct transfer_list_entry *te; +#endif int ret; void *fdt = (void *)(uintptr_t)ARM_PRELOADED_DTB_BASE; @@ -95,16 +104,40 @@ static void update_dt(void) ret = fdt_pack(fdt); if (ret < 0) ERROR("Failed to pack Device Tree at %p: error %d\n", fdt, ret); + +#if TRANSFER_LIST + // create a TE + te = transfer_list_add(bl2_tl, TL_TAG_FDT, fdt_totalsize(fdt), fdt); + if (!te) { + ERROR("Failed to add FDT entry to Transfer List\n"); + return; + } +#endif } void bl2_platform_setup(void) { +#if TRANSFER_LIST + bl2_tl = transfer_list_init((void *)(uintptr_t)FW_HANDOFF_BASE, + FW_HANDOFF_SIZE); + if (!bl2_tl) { + ERROR("Failed to initialize Transfer List at 0x%lx\n", + (unsigned long)FW_HANDOFF_BASE); + } +#endif security_setup(); update_dt(); /* TODO Initialize timer */ } +void qemu_bl2_sync_transfer_list(void) +{ +#if TRANSFER_LIST + transfer_list_update_checksum(bl2_tl); +#endif +} + void bl2_plat_arch_setup(void) { const mmap_region_t bl_regions[] = { @@ -221,6 +254,10 @@ static int qemu_bl2_handle_post_image_load(unsigned int image_id) #if defined(SPD_spmd) bl_mem_params_node_t *bl32_mem_params = NULL; #endif +#if TRANSFER_LIST + struct transfer_list_header *ns_tl = NULL; + struct transfer_list_entry *te = NULL; +#endif assert(bl_mem_params); @@ -275,6 +312,8 @@ static int qemu_bl2_handle_post_image_load(unsigned int image_id) pager_mem_params->ep_info.lr_svc = bl_mem_params->ep_info.pc; #endif + bl_mem_params->ep_info.spsr = qemu_get_spsr_for_bl33_entry(); + #if ARM_LINUX_KERNEL_AS_BL33 /* * According to the file ``Documentation/arm64/booting.txt`` of @@ -287,12 +326,49 @@ static int qemu_bl2_handle_post_image_load(unsigned int image_id) bl_mem_params->ep_info.args.arg1 = 0U; bl_mem_params->ep_info.args.arg2 = 0U; bl_mem_params->ep_info.args.arg3 = 0U; +#elif TRANSFER_LIST + if (bl2_tl) { + // relocate the tl to pre-allocate NS memory + ns_tl = transfer_list_relocate(bl2_tl, + (void *)(uintptr_t)FW_NS_HANDOFF_BASE, + bl2_tl->max_size); + if (!ns_tl) { + ERROR("Relocate TL to 0x%lx failed\n", + (unsigned long)FW_NS_HANDOFF_BASE); + return -1; + } + NOTICE("Transfer list handoff to BL33\n"); + transfer_list_dump(ns_tl); + + te = transfer_list_find(ns_tl, TL_TAG_FDT); + + bl_mem_params->ep_info.args.arg1 = + TRANSFER_LIST_SIGNATURE | + REGISTER_CONVENTION_VERSION_MASK; + bl_mem_params->ep_info.args.arg3 = (uintptr_t)ns_tl; + + if (GET_RW(bl_mem_params->ep_info.spsr) == MODE_RW_32) { + // aarch32 + bl_mem_params->ep_info.args.arg0 = 0; + bl_mem_params->ep_info.args.arg2 = te ? + (uintptr_t)transfer_list_entry_data(te) + : 0; + } else { + // aarch64 + bl_mem_params->ep_info.args.arg0 = te ? + (uintptr_t)transfer_list_entry_data(te) + : 0; + bl_mem_params->ep_info.args.arg2 = 0; + } + } else { + // Legacy handoff + bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr(); + } #else /* BL33 expects to receive the primary CPU MPID (through r0) */ bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr(); -#endif +#endif // ARM_LINUX_KERNEL_AS_BL33 - bl_mem_params->ep_info.spsr = qemu_get_spsr_for_bl33_entry(); break; #ifdef SPD_spmd #if SPMD_SPM_AT_SEL2 diff --git a/plat/qemu/common/qemu_common.c b/plat/qemu/common/qemu_common.c index 98be4910d..d4488a4bd 100644 --- a/plat/qemu/common/qemu_common.c +++ b/plat/qemu/common/qemu_common.c @@ -47,6 +47,14 @@ #define MAP_FLASH1 MAP_REGION_FLAT(QEMU_FLASH1_BASE, QEMU_FLASH1_SIZE, \ MT_MEMORY | MT_RO | MT_SECURE) +#ifdef FW_HANDOFF_BASE +#define MAP_FW_HANDOFF MAP_REGION_FLAT(FW_HANDOFF_BASE, FW_HANDOFF_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) +#endif +#ifdef FW_NS_HANDOFF_BASE +#define MAP_FW_NS_HANDOFF MAP_REGION_FLAT(FW_NS_HANDOFF_BASE, FW_HANDOFF_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) +#endif /* * Table of regions for various BL stages to map using the MMU. * This doesn't include TZRAM as the 'mem_layout' argument passed to @@ -84,6 +92,9 @@ static const mmap_region_t plat_qemu_mmap[] = { QEMU_SP_IMAGE_MMAP, #else MAP_BL32_MEM, +#endif +#ifdef MAP_FW_HANDOFF + MAP_FW_HANDOFF, #endif {0} }; @@ -98,6 +109,12 @@ static const mmap_region_t plat_qemu_mmap[] = { #ifdef MAP_DEVICE2 MAP_DEVICE2, #endif +#ifdef MAP_FW_HANDOFF + MAP_FW_HANDOFF, +#endif +#ifdef MAP_FW_NS_HANDOFF + MAP_FW_NS_HANDOFF, +#endif #if SPM_MM MAP_NS_DRAM0, QEMU_SPM_BUF_EL3_MMAP, diff --git a/plat/qemu/common/qemu_image_load.c b/plat/qemu/common/qemu_image_load.c index 9970d1de7..2b02a67ed 100644 --- a/plat/qemu/common/qemu_image_load.c +++ b/plat/qemu/common/qemu_image_load.c @@ -1,11 +1,13 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include +#include "qemu_private.h" + /******************************************************************************* * This function is a wrapper of a common function which flushes the data * structures so that they are visible in memory for the next BL image. @@ -13,6 +15,7 @@ void plat_flush_next_bl_params(void) { flush_bl_params_desc(); + qemu_bl2_sync_transfer_list(); } /******************************************************************************* diff --git a/plat/qemu/common/qemu_private.h b/plat/qemu/common/qemu_private.h index e80a88d5f..c8912b22f 100644 --- a/plat/qemu/common/qemu_private.h +++ b/plat/qemu/common/qemu_private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2023, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -40,4 +40,6 @@ int qemu_set_nt_fw_info( size_t log_size, uintptr_t *ns_log_addr); +void qemu_bl2_sync_transfer_list(void); + #endif /* QEMU_PRIVATE_H */ diff --git a/plat/qemu/qemu/include/platform_def.h b/plat/qemu/qemu/include/platform_def.h index 93a3ce842..903c809dd 100644 --- a/plat/qemu/qemu/include/platform_def.h +++ b/plat/qemu/qemu/include/platform_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -151,9 +151,17 @@ * current BL3-1 debug size plus a little space for growth. */ #define BL31_BASE (BL31_LIMIT - 0x60000) -#define BL31_LIMIT (BL_RAM_BASE + BL_RAM_SIZE) +#define BL31_LIMIT (BL_RAM_BASE + BL_RAM_SIZE - FW_HANDOFF_SIZE) #define BL31_PROGBITS_LIMIT BL1_RW_BASE +#if TRANSFER_LIST +#define FW_HANDOFF_BASE BL31_LIMIT +#define FW_HANDOFF_LIMIT (FW_HANDOFF_BASE + FW_HANDOFF_SIZE) +#define FW_HANDOFF_SIZE 0x4000 +#else +#define FW_HANDOFF_SIZE 0 +#endif + /* * BL3-2 specific defines. @@ -172,16 +180,20 @@ # define BL32_MEM_BASE BL_RAM_BASE # define BL32_MEM_SIZE BL_RAM_SIZE # define BL32_BASE BL32_SRAM_BASE -# define BL32_LIMIT BL32_SRAM_LIMIT +# define BL32_LIMIT (BL32_SRAM_LIMIT - FW_HANDOFF_SIZE) #elif BL32_RAM_LOCATION_ID == SEC_DRAM_ID # define BL32_MEM_BASE SEC_DRAM_BASE # define BL32_MEM_SIZE SEC_DRAM_SIZE # define BL32_BASE BL32_DRAM_BASE -# define BL32_LIMIT BL32_DRAM_LIMIT +# define BL32_LIMIT (BL32_DRAM_LIMIT - FW_HANDOFF_SIZE) #else # error "Unsupported BL32_RAM_LOCATION_ID value" #endif +#if TRANSFER_LIST +#define FW_NS_HANDOFF_BASE (NS_IMAGE_OFFSET - FW_HANDOFF_SIZE) +#endif + #define NS_IMAGE_OFFSET (NS_DRAM0_BASE + 0x20000000) #define NS_IMAGE_MAX_SIZE (NS_DRAM0_SIZE - 0x20000000) diff --git a/plat/qemu/qemu/platform.mk b/plat/qemu/qemu/platform.mk index 16e89c1fe..e902c1214 100644 --- a/plat/qemu/qemu/platform.mk +++ b/plat/qemu/qemu/platform.mk @@ -39,6 +39,10 @@ $(eval $(call add_define,SPMC_OPTEE)) add-lib-optee := yes endif +ifeq (${TRANSFER_LIST},1) +include lib/transfer_list/transfer_list.mk +endif + ifeq ($(NEED_BL32),yes) $(eval $(call add_define,QEMU_LOAD_BL32)) endif -- cgit v1.2.3