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
 

Reply via email to