From 427643021561f5fa90bbfbd3b08752b62e983b91 Mon Sep 17 00:00:00 2001 From: Runyang Chen Date: Fri, 21 Jun 2024 09:23:10 +0800 Subject: [PATCH] core: interrupts: add gic_spi_release_to_ns API to reset the properties of an interrupt This patch introduces gic_spi_release_to_ns API to release an interrupt to Non secure settings. This functionality is essential for scenarios where a specific interrupt needs to be dynamically set to either Group 1 Secure (G1S) or Group 1 Non-Secure (G1NS) at different times. Signed-off-by: Runyang Chen Reviewed-by: Jens Wiklander --- core/drivers/gic.c | 32 ++++++++++++++++++++++++++++++++ core/include/drivers/gic.h | 9 +++++++++ 2 files changed, 41 insertions(+) diff --git a/core/drivers/gic.c b/core/drivers/gic.c index a1d9766cb5b..762c727e21f 100644 --- a/core/drivers/gic.c +++ b/core/drivers/gic.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -138,6 +139,7 @@ struct gic_data { static bool gic_primary_done __nex_bss; static struct gic_data gic_data __nex_bss; +static struct mutex gic_mutex = MUTEX_INITIALIZER; static void gic_op_add(struct itr_chip *chip, size_t it, uint32_t type, uint32_t prio); @@ -858,6 +860,36 @@ void gic_dump_state(void) } } +int gic_spi_release_to_ns(size_t it) +{ + struct gic_data *gd = &gic_data; + size_t idx = it / NUM_INTS_PER_REG; + uint32_t mask = BIT32(it % NUM_INTS_PER_REG); + + if (it < gd->max_it && it >= GIC_SPI_BASE) + return TEE_ERROR_OVERFLOW; + /* Make sure it's already disabled */ + if (!gic_it_is_enabled(gd, it)) + return TEE_ERROR_BAD_STATE; + /* Assert it's secure to start with */ + if (!gic_it_get_group(gd, it)) + return TEE_ERROR_SECURITY; + + gic_it_set_cpu_mask(gd, it, 0); + gic_it_set_prio(gd, it, GIC_SPI_PRI_NS_EL1); + + mutex_lock(&gic_mutex); + /* Clear pending status */ + io_write32(gd->gicd_base + GICD_ICPENDR(idx), mask); + /* Assign it to NS Group1 */ + io_setbits32(gd->gicd_base + GICD_IGROUPR(idx), mask); +#if defined(CFG_ARM_GICV3) + io_clrbits32(gd->gicd_base + GICD_IGROUPMODR(idx), mask); +#endif + mutex_unlock(&gic_mutex); + return TEE_SUCCESS; +} + static void __maybe_unused gic_native_itr_handler(void) { struct gic_data *gd = &gic_data; diff --git a/core/include/drivers/gic.h b/core/include/drivers/gic.h index 498e3c8a78a..15aadb663b8 100644 --- a/core/include/drivers/gic.h +++ b/core/include/drivers/gic.h @@ -31,6 +31,8 @@ #define GIC_SGI_SEC_BASE 8 /* Max ID for secure SGIs */ #define GIC_SGI_SEC_MAX 15 +/* Default IRQ priority for SPIs in Non-Sec EL1 */ +#define GIC_SPI_PRI_NS_EL1 0x50 /* * The two gic_init() and gic_init_v3() functions initializes the struct @@ -56,4 +58,11 @@ void gic_init_per_cpu(void); /* Print GIC state to console */ void gic_dump_state(void); + +/* + * Reassign one of the SPIs to normal world and set its priority to + * GIC_SPI_PRI_NS_EL1. Ensure that the interrupt is disabled when this + * function is called. + */ +int gic_spi_release_to_ns(size_t it); #endif /*__DRIVERS_GIC_H*/