From dcb31ff79096fc88b45df8068e5de83b93f833ed Mon Sep 17 00:00:00 2001 From: Florian Lugou Date: Wed, 8 Sep 2021 12:40:24 +0200 Subject: [PATCH] feat(gic): add APIs to raise NS and S-EL1 SGIs This patch adds two helper functions: - plat_ic_raise_ns_sgi to raise a NS SGI - plat_ic_raise_s_el1_sgi to raise a S-EL1 SGI Signed-off-by: Florian Lugou Change-Id: I6f262dd1da1d77fec3f850eb74189e726b8e24da --- drivers/arm/gic/v2/gicv2_main.c | 5 ++-- drivers/arm/gic/v3/gicv3_main.c | 22 ++++++++++++++--- include/arch/aarch32/arch_helpers.h | 4 ++++ include/arch/aarch64/arch.h | 1 + include/arch/aarch64/arch_helpers.h | 1 + include/drivers/arm/gicv2.h | 8 +++++-- include/drivers/arm/gicv3.h | 9 ++++++- include/plat/common/platform.h | 2 ++ plat/common/plat_gicv2.c | 37 ++++++++++++++++++++++++++++- plat/common/plat_gicv3.c | 29 +++++++++++++++++++++- plat/st/stm32mp1/stm32mp1_pm.c | 2 +- 11 files changed, 109 insertions(+), 11 deletions(-) diff --git a/drivers/arm/gic/v2/gicv2_main.c b/drivers/arm/gic/v2/gicv2_main.c index 939d09718..1925a13ac 100644 --- a/drivers/arm/gic/v2/gicv2_main.c +++ b/drivers/arm/gic/v2/gicv2_main.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * Portions copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -417,7 +418,7 @@ void gicv2_set_interrupt_type(unsigned int id, unsigned int type) * The proc_num parameter must be the linear index of the target PE in the * system. ******************************************************************************/ -void gicv2_raise_sgi(int sgi_num, int proc_num) +void gicv2_raise_sgi(int sgi_num, bool ns, int proc_num) { unsigned int sgir_val, target; @@ -437,7 +438,7 @@ void gicv2_raise_sgi(int sgi_num, int proc_num) target = driver_data->target_masks[proc_num]; assert(target != 0U); - sgir_val = GICV2_SGIR_VALUE(SGIR_TGT_SPECIFIC, target, sgi_num); + sgir_val = GICV2_SGIR_VALUE(SGIR_TGT_SPECIFIC, target, ns, sgi_num); /* * Ensure that any shared variable updates depending on out of band diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c index 8ead43b96..bc93f9315 100644 --- a/drivers/arm/gic/v3/gicv3_main.c +++ b/drivers/arm/gic/v3/gicv3_main.c @@ -1095,11 +1095,12 @@ void gicv3_set_interrupt_type(unsigned int id, unsigned int proc_num, } /******************************************************************************* - * This function raises the specified Secure Group 0 SGI. + * This function raises the specified SGI of the specified group. * * The target parameter must be a valid MPIDR in the system. ******************************************************************************/ -void gicv3_raise_secure_g0_sgi(unsigned int sgi_num, u_register_t target) +void gicv3_raise_sgi(unsigned int sgi_num, gicv3_irq_group_t group, + u_register_t target) { unsigned int tgt, aff3, aff2, aff1, aff0; uint64_t sgi_val; @@ -1129,7 +1130,22 @@ void gicv3_raise_secure_g0_sgi(unsigned int sgi_num, u_register_t target) * interrupt trigger are observed before raising SGI. */ dsbishst(); - write_icc_sgi0r_el1(sgi_val); + + switch (group) { + case GICV3_G0: + write_icc_sgi0r_el1(sgi_val); + break; + case GICV3_G1NS: + write_icc_asgi1r(sgi_val); + break; + case GICV3_G1S: + write_icc_sgi1r(sgi_val); + break; + default: + assert(false); + break; + } + isb(); } diff --git a/include/arch/aarch32/arch_helpers.h b/include/arch/aarch32/arch_helpers.h index 033098915..95d056f45 100644 --- a/include/arch/aarch32/arch_helpers.h +++ b/include/arch/aarch32/arch_helpers.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * Portions copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -282,6 +283,7 @@ DEFINE_COPROCR_RW_FUNCS(icc_eoir0_el1, ICC_EOIR0) DEFINE_COPROCR_RW_FUNCS(icc_eoir1_el1, ICC_EOIR1) DEFINE_COPROCR_RW_FUNCS_64(icc_sgi0r_el1, ICC_SGI0R_EL1_64) DEFINE_COPROCR_WRITE_FUNC_64(icc_sgi1r, ICC_SGI1R_EL1_64) +DEFINE_COPROCR_WRITE_FUNC_64(icc_asgi1r, ICC_ASGI1R_EL1_64) DEFINE_COPROCR_RW_FUNCS(sdcr, SDCR) DEFINE_COPROCR_RW_FUNCS(hdcr, HDCR) @@ -402,6 +404,8 @@ static inline unsigned int get_current_el(void) #define read_ctr_el0() read_ctr() #define write_icc_sgi0r_el1(_v) write64_icc_sgi0r_el1(_v) +#define write_icc_sgi1r(_v) write64_icc_sgi1r(_v) +#define write_icc_asgi1r(_v) write64_icc_asgi1r(_v) #define read_daif() read_cpsr() #define write_daif(flags) write_cpsr(flags) diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h index 3a2a032fd..8d3e31db0 100644 --- a/include/arch/aarch64/arch.h +++ b/include/arch/aarch64/arch.h @@ -79,6 +79,7 @@ ******************************************************************************/ #define ICC_IGRPEN1_EL1 S3_0_C12_C12_7 #define ICC_SGI1R S3_0_C12_C11_5 +#define ICC_ASGI1R S3_0_C12_C11_6 #define ICC_SRE_EL1 S3_0_C12_C12_5 #define ICC_SRE_EL2 S3_4_C12_C9_5 #define ICC_SRE_EL3 S3_6_C12_C12_5 diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h index 10b0a0b97..8c6155400 100644 --- a/include/arch/aarch64/arch_helpers.h +++ b/include/arch/aarch64/arch_helpers.h @@ -492,6 +492,7 @@ DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_eoir0_el1, ICC_EOIR0_EL1) DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_eoir1_el1, ICC_EOIR1_EL1) DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_sgi0r_el1, ICC_SGI0R_EL1) DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sgi1r, ICC_SGI1R) +DEFINE_RENAME_SYSREG_RW_FUNCS(icc_asgi1r, ICC_ASGI1R) DEFINE_RENAME_SYSREG_READ_FUNC(amcfgr_el0, AMCFGR_EL0) DEFINE_RENAME_SYSREG_READ_FUNC(amcgcr_el0, AMCGCR_EL0) diff --git a/include/drivers/arm/gicv2.h b/include/drivers/arm/gicv2.h index b960194db..cfc168d5b 100644 --- a/include/drivers/arm/gicv2.h +++ b/include/drivers/arm/gicv2.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Portions copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -50,13 +51,15 @@ #define SGIR_TGTLSTFLT_MASK U(0x3) #define SGIR_TGTLST_SHIFT 16 #define SGIR_TGTLST_MASK U(0xff) +#define SGIR_NSATT (U(0x1) << 16) #define SGIR_INTID_MASK ULL(0xf) #define SGIR_TGT_SPECIFIC U(0) -#define GICV2_SGIR_VALUE(tgt_lst_flt, tgt, intid) \ +#define GICV2_SGIR_VALUE(tgt_lst_flt, tgt, nsatt, intid) \ ((((tgt_lst_flt) & SGIR_TGTLSTFLT_MASK) << SGIR_TGTLSTFLT_SHIFT) | \ (((tgt) & SGIR_TGTLST_MASK) << SGIR_TGTLST_SHIFT) | \ + ((nsatt) ? SGIR_NSATT : U(0)) | \ ((intid) & SGIR_INTID_MASK)) /******************************************************************************* @@ -127,6 +130,7 @@ #ifndef __ASSEMBLER__ #include +#include #include #include @@ -185,7 +189,7 @@ void gicv2_enable_interrupt(unsigned int id); void gicv2_disable_interrupt(unsigned int id); void gicv2_set_interrupt_priority(unsigned int id, unsigned int priority); void gicv2_set_interrupt_type(unsigned int id, unsigned int type); -void gicv2_raise_sgi(int sgi_num, int proc_num); +void gicv2_raise_sgi(int sgi_num, bool ns, int proc_num); void gicv2_set_spi_routing(unsigned int id, int proc_num); void gicv2_set_interrupt_pending(unsigned int id); void gicv2_clear_interrupt_pending(unsigned int id); diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h index 8371dd529..1c71149b2 100644 --- a/include/drivers/arm/gicv3.h +++ b/include/drivers/arm/gicv3.h @@ -354,6 +354,12 @@ #include #include +typedef enum { + GICV3_G1S, + GICV3_G1NS, + GICV3_G0 +} gicv3_irq_group_t; + static inline uintptr_t gicv3_redist_size(uint64_t typer_val) { #if GIC_ENABLE_V4_EXTN @@ -575,7 +581,8 @@ void gicv3_set_interrupt_priority(unsigned int id, unsigned int proc_num, unsigned int priority); void gicv3_set_interrupt_type(unsigned int id, unsigned int proc_num, unsigned int type); -void gicv3_raise_secure_g0_sgi(unsigned int sgi_num, u_register_t target); +void gicv3_raise_sgi(unsigned int sgi_num, gicv3_irq_group_t group, + u_register_t target); void gicv3_set_spi_routing(unsigned int id, unsigned int irm, u_register_t mpidr); void gicv3_set_interrupt_pending(unsigned int id, unsigned int proc_num); diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h index 184606a12..31607c2e9 100644 --- a/include/plat/common/platform.h +++ b/include/plat/common/platform.h @@ -104,6 +104,8 @@ int plat_ic_has_interrupt_type(unsigned int type); void plat_ic_set_interrupt_type(unsigned int id, unsigned int type); void plat_ic_set_interrupt_priority(unsigned int id, unsigned int priority); void plat_ic_raise_el3_sgi(int sgi_num, u_register_t target); +void plat_ic_raise_ns_sgi(int sgi_num, u_register_t target); +void plat_ic_raise_s_el1_sgi(int sgi_num, u_register_t target); void plat_ic_set_spi_routing(unsigned int id, unsigned int routing_mode, u_register_t mpidr); void plat_ic_set_interrupt_pending(unsigned int id); diff --git a/plat/common/plat_gicv2.c b/plat/common/plat_gicv2.c index 4c76f1bd1..0f988dc74 100644 --- a/plat/common/plat_gicv2.c +++ b/plat/common/plat_gicv2.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Portions copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -34,6 +35,8 @@ #pragma weak plat_ic_set_interrupt_priority #pragma weak plat_ic_set_interrupt_type #pragma weak plat_ic_raise_el3_sgi +#pragma weak plat_ic_raise_ns_sgi +#pragma weak plat_ic_raise_s_el1_sgi #pragma weak plat_ic_set_spi_routing /* @@ -247,12 +250,44 @@ void plat_ic_raise_el3_sgi(int sgi_num, u_register_t target) /* Verify that this is a secure SGI */ assert(plat_ic_get_interrupt_type(sgi_num) == INTR_TYPE_EL3); - gicv2_raise_sgi(sgi_num, id); + gicv2_raise_sgi(sgi_num, false, id); #else assert(false); #endif } +void plat_ic_raise_ns_sgi(int sgi_num, u_register_t target) +{ + int id; + + /* Target must be a valid MPIDR in the system */ + id = plat_core_pos_by_mpidr(target); + assert(id >= 0); + + /* Verify that this is a non-secure SGI */ + assert(plat_ic_get_interrupt_type(sgi_num) == INTR_TYPE_NS); + + gicv2_raise_sgi(sgi_num, true, id); +} + +void plat_ic_raise_s_el1_sgi(int sgi_num, u_register_t target) +{ +#if GICV2_G0_FOR_EL3 + assert(false); +#else + int id; + + /* Target must be a valid MPIDR in the system */ + id = plat_core_pos_by_mpidr(target); + assert(id >= 0); + + /* Verify that this is a secure EL1 SGI */ + assert(plat_ic_get_interrupt_type(sgi_num) == INTR_TYPE_S_EL1); + + gicv2_raise_sgi(sgi_num, false, id); +#endif +} + void plat_ic_set_spi_routing(unsigned int id, unsigned int routing_mode, u_register_t mpidr) { diff --git a/plat/common/plat_gicv3.c b/plat/common/plat_gicv3.c index 4a8a7eefe..2c3a06730 100644 --- a/plat/common/plat_gicv3.c +++ b/plat/common/plat_gicv3.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Portions copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -39,6 +40,8 @@ #pragma weak plat_ic_set_interrupt_priority #pragma weak plat_ic_set_interrupt_type #pragma weak plat_ic_raise_el3_sgi +#pragma weak plat_ic_raise_ns_sgi +#pragma weak plat_ic_raise_s_el1_sgi #pragma weak plat_ic_set_spi_routing #pragma weak plat_ic_set_interrupt_pending #pragma weak plat_ic_clear_interrupt_pending @@ -242,7 +245,31 @@ void plat_ic_raise_el3_sgi(int sgi_num, u_register_t target) assert(plat_ic_get_interrupt_type((unsigned int)sgi_num) == INTR_TYPE_EL3); - gicv3_raise_secure_g0_sgi((unsigned int)sgi_num, target); + gicv3_raise_sgi((unsigned int)sgi_num, GICV3_G0, target); +} + +void plat_ic_raise_ns_sgi(int sgi_num, u_register_t target) +{ + /* Target must be a valid MPIDR in the system */ + assert(plat_core_pos_by_mpidr(target) >= 0); + + /* Verify that this is a non-secure SGI */ + assert(plat_ic_get_interrupt_type((unsigned int)sgi_num) == + INTR_TYPE_NS); + + gicv3_raise_sgi((unsigned int)sgi_num, GICV3_G1NS, target); +} + +void plat_ic_raise_s_el1_sgi(int sgi_num, u_register_t target) +{ + /* Target must be a valid MPIDR in the system */ + assert(plat_core_pos_by_mpidr(target) >= 0); + + /* Verify that this is a secure EL1 SGI */ + assert(plat_ic_get_interrupt_type((unsigned int)sgi_num) == + INTR_TYPE_S_EL1); + + gicv3_raise_sgi((unsigned int)sgi_num, GICV3_G1S, target); } void plat_ic_set_spi_routing(unsigned int id, unsigned int routing_mode, diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c index 389215129..6e438c44e 100644 --- a/plat/st/stm32mp1/stm32mp1_pm.c +++ b/plat/st/stm32mp1/stm32mp1_pm.c @@ -87,7 +87,7 @@ static int stm32_pwr_domain_on(u_register_t mpidr) clk_disable(RTCAPB); /* Generate an IT to core 1 */ - gicv2_raise_sgi(ARM_IRQ_SEC_SGI_0, STM32MP_SECONDARY_CPU); + gicv2_raise_sgi(ARM_IRQ_SEC_SGI_0, false, STM32MP_SECONDARY_CPU); return PSCI_E_SUCCESS; }