Skip to content

Commit

Permalink
core: interrupts: add gic_spi_release_to_ns API to reset the properties
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Jens Wiklander <[email protected]>
  • Loading branch information
Runyang Chen committed Aug 6, 2024
1 parent ac5bf9b commit 4276430
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 0 deletions.
32 changes: 32 additions & 0 deletions core/drivers/gic.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <kernel/dt_driver.h>
#include <kernel/interrupt.h>
#include <kernel/misc.h>
#include <kernel/mutex.h>
#include <kernel/panic.h>
#include <libfdt.h>
#include <mm/core_memprot.h>
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
9 changes: 9 additions & 0 deletions core/include/drivers/gic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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*/

0 comments on commit 4276430

Please sign in to comment.