From 7c2fe62f1347bb94d82e9fdd3bc5eaebedaf0bc7 Mon Sep 17 00:00:00 2001 From: Raghu Krishnamurthy Date: Mon, 25 Jul 2022 14:44:33 -0700 Subject: [PATCH] fix(bl31): allow use of EHF with S-EL2 SPMC Currently, when SPMC at S-EL2 is used, we cannot use the RAS framework to handle Group 0 interrupts. This is required on platforms where first level of triaging needs to occur at EL3, before forwarding RAS handling to a secure partition running atop an SPMC (hafnium). The RAS framework depends on EHF and EHF registers for Group 0 interrupts to be trapped to EL3 when execution is both in secure world and normal world. However, an FF-A compliant SPMC requires secure interrupts to be trapped by the SPMC when execution is in S-EL0/S-EL1. Consequently, the SPMC (hafnium) is incompatible with EHF, since it is not re-entrant, and a Group 0 interrupt trapped to EL3 when execution is in secure world, cannot be forwarded to an SP running atop SPMC. This patch changes EHF to only register for Group 0 interrupts to be trapped to EL3 when execution is in normal world and also makes it a valid routing model to do so, when EL3_EXCEPTION_HANDLING is set (when enabling the RAS framework). Signed-off-by: Raghu Krishnamurthy Change-Id: I72d4cf4d8ecc549a832d1c36055fbe95866747fe --- bl31/ehf.c | 11 +++++++++-- docs/getting_started/build-options.rst | 7 +++++-- include/bl31/interrupt_mgmt.h | 16 ++++++++++++---- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/bl31/ehf.c b/bl31/ehf.c index 745f165d4..b328380d1 100644 --- a/bl31/ehf.c +++ b/bl31/ehf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -475,9 +475,16 @@ void __init ehf_init(void) assert((exception_data.pri_bits >= 1U) || (exception_data.pri_bits < 8U)); - /* Route EL3 interrupts when in Secure and Non-secure. */ + /* Route EL3 interrupts when in Non-secure. */ set_interrupt_rm_flag(flags, NON_SECURE); + + /* + * Route EL3 interrupts when in secure, only when SPMC is not present + * in S-EL2. + */ +#if !(defined(SPD_spmd) && (SPMD_SPM_AT_SEL2 == 1)) set_interrupt_rm_flag(flags, SECURE); +#endif /* !(defined(SPD_spmd) && (SPMD_SPM_AT_SEL2 == 1)) */ /* Register handler for EL3 interrupts */ ret = register_interrupt_type_handler(INTR_TYPE_EL3, diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst index dc1894150..72322178b 100644 --- a/docs/getting_started/build-options.rst +++ b/docs/getting_started/build-options.rst @@ -461,8 +461,11 @@ Common build options - ``EL3_EXCEPTION_HANDLING``: When set to ``1``, enable handling of exceptions targeted at EL3. When set ``0`` (default), no exceptions are expected or - handled at EL3, and a panic will result. This is supported only for AArch64 - builds. + handled at EL3, and a panic will result. The exception to this rule is when + ``SPMD_SPM_AT_SEL2`` is set to ``1``, in which case, only exceptions + occuring during normal world execution, are trapped to EL3. Any exception + trapped during secure world execution are trapped to the SPMC. This is + supported only for AArch64 builds. - ``EVENT_LOG_LEVEL``: Chooses the log level to use for Measured Boot when ``MEASURED_BOOT`` is enabled. For a list of valid values, see ``LOG_LEVEL``. diff --git a/include/bl31/interrupt_mgmt.h b/include/bl31/interrupt_mgmt.h index 935bf7766..694f1f0a1 100644 --- a/include/bl31/interrupt_mgmt.h +++ b/include/bl31/interrupt_mgmt.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2022, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -107,15 +107,23 @@ static inline int32_t validate_ns_interrupt_rm(uint32_t x) static inline int32_t validate_el3_interrupt_rm(uint32_t x) { -#if EL3_EXCEPTION_HANDLING +#if defined (EL3_EXCEPTION_HANDLING) && !(defined(SPD_spmd) && (SPMD_SPM_AT_SEL2 == 1)) /* * With EL3 exception handling, EL3 interrupts are always routed to EL3 - * from both Secure and Non-secure, and therefore INTR_EL3_VALID_RM1 is - * the only valid routing model. + * from both Secure and Non-secure, when the SPMC does not live in S-EL2. + * Therefore INTR_EL3_VALID_RM1 is the only valid routing model. */ if (x == INTR_EL3_VALID_RM1) return 0; #else + /* + * When EL3_EXCEPTION_HANDLING is not defined both routing modes are + * valid. This is the most common case. The exception to this rule is + * when EL3_EXCEPTION_HANDLING is defined but also when the SPMC lives + * at S-EL2. In this case, Group0 Interrupts are trapped to the SPMC + * when running in S-EL0 and S-EL1. The SPMC may handle the interrupt + * itself, delegate it to an SP or forward to EL3 for handling. + */ if ((x == INTR_EL3_VALID_RM0) || (x == INTR_EL3_VALID_RM1)) return 0; #endif