This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 6558f40f80d arm64/gic: add TrustZone dual-security GICv3 support
6558f40f80d is described below
commit 6558f40f80d9dfe357ada7b15d9fa446407826f3
Author: Parthiban Nallathambi <[email protected]>
AuthorDate: Fri Nov 6 16:12:07 2026 +0530
arm64/gic: add TrustZone dual-security GICv3 support
Introduce IGROUPR_SGI_SECURE_VAL bitmask to classify SGIs: SGI0-7
as Group 1 Non-Secure (G1NS), SGI8-15 as Group 1 Secure (G1S).
Replace the HIPRI-only IGROUPR_SGI_VAL conditional with this
unified scheme.
Secure world (CONFIG_ARCH_TRUSTZONE_SECURE) changes in arm64_gicv3.c:
- cpuif_init: configure SGI/PPI groups via IGROUPR and IGROUPMODR
using IGROUPR_SGI_SECURE_VAL.
- dist_init: default all SPIs to G1NS (IGROUPR=1, IGROUPMODR=0)
so normal world receives them; secure SPIs are promoted
individually via up_secure_irq().
- dist_init: enable GICD_CTLR with ARE_S, G1S and G1NS forwarding.
- arm64_gic_send_sgi: use ICC_ASGI1R for G1NS SGIs and ICC_SGI1R
for G1S SGIs based on IGROUPR_SGI_SECURE_VAL.
- up_secure_irq: also set IGROUPMODR so secure IRQs are delivered
as Group 1 Secure (IRQ) rather than FIQ (Group 0).
Non-secure world (CONFIG_ARCH_TRUSTZONE_NONSECURE) changes:
- Add ree_send_secure_sgi() helper that issues SMC
(NUTTXSPD_SEND_SECURE_SGI) asking EL3 to forward a secure SGI.
- up_trigger_irq: detect secure SGIs via IGROUPR_SGI_SECURE_VAL
and route them through the SMC path.
Minor cleanups: normalize #ifdef to #if defined() for HIPRI guards.
Signed-off-by: hujun5 <[email protected]>
---
arch/arm64/src/common/arm64_gicv3.c | 83 ++++++++++++++++++++++++++++++-------
1 file changed, 68 insertions(+), 15 deletions(-)
diff --git a/arch/arm64/src/common/arm64_gicv3.c
b/arch/arm64/src/common/arm64_gicv3.c
index 51da1eb862c..afab8302504 100644
--- a/arch/arm64/src/common/arm64_gicv3.c
+++ b/arch/arm64/src/common/arm64_gicv3.c
@@ -33,6 +33,7 @@
#include <arch/barriers.h>
#include <arch/irq.h>
#include <arch/chip/chip.h>
+#include <arch/syscall.h>
#include <sched/sched.h>
#include "arm64_arch.h"
@@ -64,14 +65,14 @@
#define IGROUPR_VAL 0xFFFFFFFFU
-#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
-
-/* Config SGI8 ~ SGI15 as group0, to signal fiq */
+/* SGI group assignment bitmask:
+ * IGROUPR_SGI_SECURE_VAL bit=1 -> G1NS (non-secure)
+ * IGROUPR_SGI_SECURE_VAL bit=0 -> G1S (secure)
+ * Default: SGI0-7 are G1NS (0xFF), SGI8-15 are G1S.
+ */
-# define IGROUPR_SGI_VAL 0xFFFF00FFU
-#else
-# define IGROUPR_SGI_VAL 0xFFFFFFFFU
-#endif
+#define IGROUPR_SGI_VAL 0xFFFFFFFFU
+#define IGROUPR_SGI_SECURE_VAL 0x000000FFU
#define PENDING_GRP1NS_INTID 1021
#define SPURIOUS_INT 1023
@@ -270,7 +271,7 @@ unsigned int arm64_gic_get_active_irq(void)
return intid;
}
-#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
+#if defined(CONFIG_ARCH_HIPRI_INTERRUPT)
unsigned int arm64_gic_get_active_fiq(void)
{
int intid;
@@ -312,7 +313,7 @@ void aarm64_gic_eoi_irq(unsigned int intid)
UP_ISB();
}
-#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
+#if defined(CONFIG_ARCH_HIPRI_INTERRUPT)
void arm64_gic_eoi_fiq(unsigned int intid)
{
/* Interrupt request deassertion from peripheral to GIC happens
@@ -363,7 +364,23 @@ static int arm64_gic_send_sgi(unsigned int sgi_id,
uint64_t target_aff,
if (regval & BIT(sgi_id))
{
+#if defined(CONFIG_ARCH_TRUSTZONE_SECURE)
+ /* In Secure state, ICC_SGI1R generates G1S (Secure Group 1).
+ * To send G1NS from Secure, use ICC_ASGI1R instead.
+ * Check IGROUPR_SGI_SECURE_VAL: bit=1 means G1NS for that SGI.
+ */
+
+ if (IGROUPR_SGI_SECURE_VAL & BIT(sgi_id))
+ {
+ write_sysreg(sgi_val, ICC_ASGI1R); /* G1NS from Secure */
+ }
+ else
+ {
+ write_sysreg(sgi_val, ICC_SGI1R); /* G1S */
+ }
+#else
write_sysreg(sgi_val, ICC_SGI1R); /* Group 1 */
+#endif
}
else
{
@@ -459,8 +476,22 @@ static void gicv3_cpuif_init(void)
* EL1S or EL1NS respectively. All interrupts will be delivered as irq.
*/
+#ifdef CONFIG_ARCH_TRUSTZONE_SECURE
+ /* Secure state SGI/PPI group configuration:
+ * IGROUPR_SGI_SECURE_VAL bit=1 -> G1NS (non-secure)
+ * IGROUPR_SGI_SECURE_VAL bit=0 -> G1S (secure, IRQ in S-EL1)
+ * Default: SGI0-7 G1NS, SGI8-15 G1S, all PPIs G1S.
+ *
+ * Per-interrupt overrides (e.g. PPI14 for NS timer) are handled
+ * separately via up_secure_irq() after init.
+ */
+
+ putreg32(IGROUPR_SGI_SECURE_VAL, IGROUPR(base, 0));
+ putreg32(~IGROUPR_SGI_SECURE_VAL, IGROUPMODR(base, 0));
+#else
putreg32(IGROUPR_SGI_VAL, IGROUPR(base, 0));
putreg32(0, IGROUPMODR(base, 0));
+#endif
/* Clear any active IRQs in the CPU interface */
@@ -655,18 +686,25 @@ static void gicv3_dist_init(void)
putreg32(regval, GICD_CTLR);
+#elif defined(CONFIG_ARCH_TRUSTZONE_SECURE)
+ /* Secure state: enable ARE_S, Secure Group 1.
+ * Also enable non-secure group1 forwarding so that
+ * non-secure interrupts can be routed to normal world.
+ */
+
+ regval = BIT(GICD_CTRL_ARE_S) | BIT(GICD_CTLR_ENABLE_G1S) |
+ BIT(GICD_CTRL_ARE_NS) | BIT(GICD_CTLR_ENABLE_G1NS);
#else
/* Enable distributor with ARE */
regval = BIT(GICD_CTRL_ARE_NS) | BIT(GICD_CTLR_ENABLE_G1NS);
-#ifdef CONFIG_ARCH_HIPRI_INTERRUPT
+# ifdef CONFIG_ARCH_HIPRI_INTERRUPT
regval |= BIT(GICD_CTLR_ENABLE_G0);
+# endif
#endif
putreg32(regval, GICD_CTLR);
-#endif
-
#ifdef CONFIG_SMP
/* Attach SGI interrupt handlers. This attaches the handler to all CPUs. */
@@ -699,18 +737,33 @@ void up_secure_irq(int irq, bool secure)
uint32_t mask = BIT(irq & (GIC_NUM_INTR_PER_REG - 1));
uint32_t idx = irq / GIC_NUM_INTR_PER_REG;
unsigned long base = GET_DIST_BASE(irq);
- unsigned int val = getreg32(IGROUPR(base, idx));
+ unsigned int val;
+
+ val = getreg32(IGROUPR(base, idx));
if (secure)
{
- val &= (~mask); /* group 0 fiq */
+ val &= ~mask; /* IGROUPR=0 */
}
else
{
- val |= mask; /* group 1 irq */
+ val |= mask; /* IGROUPR=1 */
}
putreg32(val, IGROUPR(base, idx));
+
+#if defined(CONFIG_ARCH_TRUSTZONE_SECURE)
+ /* In dual security state, IGROUPMODR selects between:
+ * secure: IGROUPR=0, IGROUPMODR=1 -> Group 1 Secure (IRQ)
+ * non-secure: IGROUPR=1, IGROUPMODR=1 -> Group 1 Non-secure
+ * Keep IGROUPMODR=1 for both cases so secure interrupts are
+ * delivered as IRQ (Group 1 Secure) rather than FIQ (Group 0).
+ */
+
+ val = getreg32(IGROUPMODR(base, idx));
+ val |= mask;
+ putreg32(val, IGROUPMODR(base, idx));
+#endif
}
#endif