Files
arm-trusted-firmware/include/bl1/bl1.h
T
Boyan Karatotev 14320bce3a feat(el3-runtime): translate EL3 handled exceptions to C and always call prepare_el3_entry
Exception handling in BL31 is tricky business and to satisfy the varying
requirements of the different code paths it has thus far largely been
written in assembly. However, assembly is extremely tedious to read and
modify. Similar to context management, it is desirable to have as much
as possible in C. C code is generally easier to follow and can enable
the compiler to do more optimisations on surrounding code.

Most exceptions that BL31 deals with are the synchronous exceptions and
those are processed within BL31. They already get prepared for EL3 entry
and after the initial dispatch end up in C. So the dispatch can also be
converted in C. Interrupt exceptions are very similar so are converted
too. Finally, asynchronous external aborts share some code with
synchronous external aborts and may end up being processed deeper in
BL31. So they can safely be prepared for EL3 entry too and converted to
C so that they can share code properly.

The IMP DEF exceptions are not part of this refactor as their speed may
be important. There is currently little that uses them, but they can be
converted to C too once their use expands and usage allows it.

This refactor allows to expand the responsibilities of
prepare_el3_entry(). Its role is already to prepare context for
executing within EL3 but with this patch EL3 execution is synonymous
with C runtime execution. So it's given the responsibility of saving
spsr and elr as well as putting the runtime stack in.

When a synchronous exception happens, the only possible paths are to
enter the C EL3 runtime, exiting via el3_exit(), or to panic. In the EL3
runtime case, we always need prepare_el3_entry() and the runtime stack,
whereas in the panic case, this doesn't matter as we will never return.
So hoist the prepare_el3_entry() call and the changing of the stacks as
early as possible and make the rest of the code agnostic of this.

This patch also gets rid of smc_prohibited. It is an optimisation by
skipping prepare_el3_entry() when a bad smc call happens. However, speed
doesn't matter in this case as this is an erroneous case.

Change-Id: I411af9d17ef4046a736b1f4f5f8fbc9c28e66106
Signed-off-by: Boyan Karatotev <boyan.karatotev@arm.com>
2025-12-19 07:51:40 +00:00

98 lines
2.0 KiB
C

/*
* Copyright (c) 2015-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef BL1_H
#define BL1_H
#include <common/bl_common.h>
/*
* Defines for BL1 SMC function ids.
*/
#define BL1_SMC_CALL_COUNT 0x0
#define BL1_SMC_UID 0x1
/* SMC #0x2 reserved */
#define BL1_SMC_VERSION 0x3
/*
* Corresponds to the function ID of the SMC that
* the BL1 exception handler service to execute BL31.
*/
#define BL1_SMC_RUN_IMAGE 0x4
/*
* BL1 SMC version
*/
#define BL1_SMC_MAJOR_VER UL(0x0)
#define BL1_SMC_MINOR_VER UL(0x1)
/*
* Defines for FWU SMC function ids.
*/
#define FWU_SMC_IMAGE_COPY 0x10
#define FWU_SMC_IMAGE_AUTH 0x11
#define FWU_SMC_IMAGE_EXECUTE 0x12
#define FWU_SMC_IMAGE_RESUME 0x13
#define FWU_SMC_SEC_IMAGE_DONE 0x14
#define FWU_SMC_UPDATE_DONE 0x15
#define FWU_SMC_IMAGE_RESET 0x16
/*
* Number of FWU calls (above) implemented
*/
#define FWU_NUM_SMC_CALLS 7
#if TRUSTED_BOARD_BOOT
# define BL1_NUM_SMC_CALLS (FWU_NUM_SMC_CALLS + 4)
#else
# define BL1_NUM_SMC_CALLS 4
#endif
/*
* The macros below are used to identify FWU
* calls from the SMC function ID
*/
#define FWU_SMC_FID_START FWU_SMC_IMAGE_COPY
#define FWU_SMC_FID_END FWU_SMC_IMAGE_RESET
#define is_fwu_fid(_fid) \
((_fid >= FWU_SMC_FID_START) && (_fid <= FWU_SMC_FID_END))
#ifndef __ASSEMBLER__
#include <lib/cassert.h>
struct entry_point_info;
u_register_t bl1_smc_wrapper_aarch32(uint32_t smc_fid,
void *cookie,
void *handle,
unsigned int flags);
u_register_t bl1_smc_handler(unsigned int smc_fid,
u_register_t x1,
u_register_t x2,
u_register_t x3,
u_register_t x4,
void *cookie,
void *handle,
unsigned int flags);
void bl1_print_next_bl_ep_info(const struct entry_point_info *bl_ep_info);
void bl1_main(void);
void bl1_plat_prepare_exit(entry_point_info_t *ep_info);
/*
* Check if the total number of FWU SMC calls are as expected.
*/
CASSERT(FWU_NUM_SMC_CALLS ==
(FWU_SMC_FID_END - FWU_SMC_FID_START + 1),
assert_FWU_NUM_SMC_CALLS_mismatch);
#endif /* __ASSEMBLER__ */
#endif /* BL1_H */