Merge changes from topic "mp/group0_support" into integration

* changes:
  docs(spm): support for handling Group0 interrupts
  feat(spmd): introduce platform handler for Group0 interrupt
  feat(spmd): add support for FFA_EL3_INTR_HANDLE_32 ABI
  feat(spmd): register handler for group0 interrupt from NWd
This commit is contained in:
Olivier Deprez 2023-05-03 18:15:40 +02:00 committed by TrustedFirmware Code Review
commit 17f9732da5
11 changed files with 189 additions and 6 deletions

View file

@ -1318,6 +1318,25 @@ A brief description of the events:
direct request to SP2 by invoking FFA_RUN.
- 9) SPMC resumes the pre-empted vCPU of SP2.
EL3 interrupt handling
~~~~~~~~~~~~~~~~~~~~~~
In GICv3 based systems, EL3 interrupts are configured as Group0 secure
interrupts. Execution traps to SPMC when a Group0 interrupt triggers while an
SP is running. Further, SPMC running at S-EL2 uses FFA_EL3_INTR_HANDLE ABI to
request EL3 platform firmware to handle a pending Group0 interrupt.
Similarly, SPMD registers a handler with interrupt management framework to
delegate handling of Group0 interrupt to the platform if the interrupt triggers
in normal world.
- Platform hook
- plat_spmd_handle_group0_interrupt
SPMD provides platform hook to handle Group0 secure interrupts. In the
current design, SPMD expects the platform not to delegate handling to the
NWd (such as through SDEI) while processing Group0 interrupts.
Power management
----------------
@ -1557,4 +1576,4 @@ Client <https://developer.arm.com/documentation/den0006/d/>`__
--------------
*Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.*
*Copyright (c) 2020-2023, Arm Limited and Contributors. All rights reserved.*

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020-2022, Arm Limited. All rights reserved.
* Copyright (c) 2020-2023, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -24,7 +24,7 @@
/* The macros below are used to identify FFA calls from the SMC function ID */
#define FFA_FNUM_MIN_VALUE U(0x60)
#define FFA_FNUM_MAX_VALUE U(0x8B)
#define FFA_FNUM_MAX_VALUE U(0x8C)
#define is_ffa_fid(fid) __extension__ ({ \
__typeof__(fid) _fid = (fid); \
((GET_SMC_NUM(_fid) >= FFA_FNUM_MIN_VALUE) && \
@ -118,6 +118,7 @@
#define FFA_FNUM_MSG_SEND2 U(0x86)
#define FFA_FNUM_SECONDARY_EP_REGISTER U(0x87)
#define FFA_FNUM_PARTITION_INFO_GET_REGS U(0x8B)
#define FFA_FNUM_EL3_INTR_HANDLE U(0x8C)
/* FFA SMC32 FIDs */
#define FFA_ERROR FFA_FID(SMC_32, FFA_FNUM_ERROR)
@ -163,6 +164,7 @@
#define FFA_MEM_FRAG_TX FFA_FID(SMC_32, FFA_FNUM_MEM_FRAG_TX)
#define FFA_SPM_ID_GET FFA_FID(SMC_32, FFA_FNUM_SPM_ID_GET)
#define FFA_NORMAL_WORLD_RESUME FFA_FID(SMC_32, FFA_FNUM_NORMAL_WORLD_RESUME)
#define FFA_EL3_INTR_HANDLE FFA_FID(SMC_32, FFA_FNUM_EL3_INTR_HANDLE)
/* FFA SMC64 FIDs */
#define FFA_ERROR_SMC64 FFA_FID(SMC_64, FFA_FNUM_ERROR)

View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
#if defined(SPD_spmd)
/*
* A dummy implementation of the platform handler for Group0 secure interrupt.
*/
int plat_spmd_handle_group0_interrupt(uint32_t intid)
{
(void)intid;
return -1;
}
#endif /*defined(SPD_spmd)*/

View file

@ -56,6 +56,7 @@ BL31_SOURCES += drivers/cfi/v2m/v2m_flash.c \
plat/arm/board/corstone1000/common/corstone1000_security.c \
plat/arm/board/corstone1000/common/corstone1000_plat.c \
plat/arm/board/corstone1000/common/corstone1000_pm.c \
plat/arm/board/corstone1000/common/corstone1000_bl31_setup.c \
${CORSTONE1000_CPU_LIBS} \
${CORSTONE1000_GIC_SOURCES}

View file

@ -0,0 +1,17 @@
/*
* Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
int plat_spmd_handle_group0_interrupt(uint32_t intid)
{
/*
* As of now, there are no sources of Group0 secure interrupt enabled
* for FVP.
*/
(void)intid;
return -1;
}

View file

@ -512,3 +512,7 @@ ifeq (${PLATFORM_TEST_EA_FFH}, 1)
endif
BL31_SOURCES += plat/arm/board/fvp/aarch64/fvp_ea.c
endif
ifeq (${SPD},spmd)
BL31_SOURCES += plat/arm/board/fvp/fvp_spmd.c
endif

View file

@ -159,3 +159,14 @@ void bl31_platform_setup(void)
if ((plat_info.multichip_mode) && (plat_info.remote_ddr_size != 0))
remote_dmc_ecc_setup(plat_info.remote_ddr_size);
}
#if defined(SPD_spmd)
/*
* A dummy implementation of the platform handler for Group0 secure interrupt.
*/
int plat_spmd_handle_group0_interrupt(uint32_t intid)
{
(void)intid;
return -1;
}
#endif /*defined(SPD_spmd)*/

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -245,6 +245,15 @@ static uint64_t hikey_debug_fiq_handler(uint32_t id,
return 0;
}
#elif defined(SPD_spmd) && (SPMD_SPM_AT_SEL2 == 1)
/*
* A dummy implementation of the platform handler for Group0 secure interrupt.
*/
int plat_spmd_handle_group0_interrupt(uint32_t intid)
{
(void)intid;
return -1;
}
#endif
void bl31_plat_runtime_setup(void)

View file

@ -1,6 +1,6 @@
/*
* 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
*/
@ -162,3 +162,14 @@ int plat_spmc_shmem_reclaim(struct ffa_mtd *desc)
return 0;
}
#endif
#if defined(SPD_spmd) && (SPMD_SPM_AT_SEL2 == 1)
/*
* A dummy implementation of the platform handler for Group0 secure interrupt.
*/
int plat_spmd_handle_group0_interrupt(uint32_t intid)
{
(void)intid;
return -1;
}
#endif /*defined(SPD_spmd) && (SPMD_SPM_AT_SEL2 == 1)*/

View file

@ -249,6 +249,74 @@ static uint64_t spmd_secure_interrupt_handler(uint32_t id,
SMC_RET0(&ctx->cpu_ctx);
}
/*******************************************************************************
* spmd_group0_interrupt_handler_nwd
* Group0 secure interrupt in the normal world are trapped to EL3. Delegate the
* handling of the interrupt to the platform handler, and return only upon
* successfully handling the Group0 interrupt.
******************************************************************************/
static uint64_t spmd_group0_interrupt_handler_nwd(uint32_t id,
uint32_t flags,
void *handle,
void *cookie)
{
uint32_t intid;
/* Sanity check the security state when the exception was generated. */
assert(get_interrupt_src_ss(flags) == NON_SECURE);
/* Sanity check the pointer to this cpu's context. */
assert(handle == cm_get_context(NON_SECURE));
assert(id == INTR_ID_UNAVAILABLE);
assert(plat_ic_get_pending_interrupt_type() == INTR_TYPE_EL3);
intid = plat_ic_get_pending_interrupt_id();
if (plat_spmd_handle_group0_interrupt(intid) < 0) {
ERROR("Group0 interrupt %u not handled\n", intid);
panic();
}
return 0U;
}
/*******************************************************************************
* spmd_handle_group0_intr_swd
* SPMC delegates handling of Group0 secure interrupt to EL3 firmware using
* FFA_EL3_INTR_HANDLE SMC call. Further, SPMD delegates the handling of the
* interrupt to the platform handler, and returns only upon successfully
* handling the Group0 interrupt.
******************************************************************************/
static uint64_t spmd_handle_group0_intr_swd(void *handle)
{
uint32_t intid;
/* Sanity check the pointer to this cpu's context */
assert(handle == cm_get_context(SECURE));
assert(plat_ic_get_pending_interrupt_type() == INTR_TYPE_EL3);
intid = plat_ic_get_pending_interrupt_id();
/*
* TODO: Currently due to a limitation in SPMD implementation, the
* platform handler is expected to not delegate handling to NWd while
* processing Group0 secure interrupt.
*/
if (plat_spmd_handle_group0_interrupt(intid) < 0) {
/* Group0 interrupt was not handled by the platform. */
ERROR("Group0 interrupt %u not handled\n", intid);
panic();
}
/* Return success. */
SMC_RET8(handle, FFA_SUCCESS_SMC32, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
FFA_PARAM_MBZ);
}
#if ENABLE_RME && SPMD_SPM_AT_SEL2 && !RESET_TO_BL31
static int spmd_dynamic_map_mem(uintptr_t base_addr, size_t size,
unsigned int attr, uintptr_t *align_addr,
@ -492,6 +560,16 @@ static int spmd_spmc_init(void *pm_addr)
panic();
}
/*
* Register an interrupt handler routing Group0 interrupts to SPMD
* while the NWd is running.
*/
rc = register_interrupt_type_handler(INTR_TYPE_EL3,
spmd_group0_interrupt_handler_nwd,
flags);
if (rc != 0) {
panic();
}
return 0;
}
@ -1089,6 +1167,12 @@ uint64_t spmd_smc_handler(uint32_t smc_fid,
handle, flags);
break; /* Not reached */
#endif
case FFA_EL3_INTR_HANDLE:
if (secure_origin) {
return spmd_handle_group0_intr_swd(handle);
} else {
return spmd_ffa_error_return(handle, FFA_ERROR_DENIED);
}
default:
WARN("SPM: Unsupported call 0x%08x\n", smc_fid);
return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2019-2023, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -93,6 +93,13 @@ spmd_spm_core_context_t *spmd_get_context(void);
int spmd_pm_secondary_ep_register(uintptr_t entry_point);
bool spmd_check_address_in_binary_image(uint64_t address);
/*
* Platform hook in EL3 firmware to handle for Group0 secure interrupt.
* Return values:
* 0 = success
* otherwise it returns a negative value
*/
int plat_spmd_handle_group0_interrupt(uint32_t id);
#endif /* __ASSEMBLER__ */
#endif /* SPMD_PRIVATE_H */