This is an automated email from the ASF dual-hosted git repository.

acassis 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 4e196729e76 arch/risc-v: Add CLIC interrupt threshold support
4e196729e76 is described below

commit 4e196729e766a7fb45c2d534def81b8551cb5fe5
Author: Huang Qi <[email protected]>
AuthorDate: Wed Jun 11 10:38:59 2025 +0800

    arch/risc-v: Add CLIC interrupt threshold support
    
    and documentation it
    
    Signed-off-by: Huang Qi <[email protected]>
---
 Documentation/platforms/risc-v/common/index.rst | 151 ++++++++++++++++++++++++
 arch/risc-v/Kconfig                             |   9 ++
 arch/risc-v/include/irq.h                       |  93 ++++++++++++++-
 arch/risc-v/include/mode.h                      |   2 +
 arch/risc-v/src/common/riscv_exception_common.S |  10 ++
 5 files changed, 261 insertions(+), 4 deletions(-)

diff --git a/Documentation/platforms/risc-v/common/index.rst 
b/Documentation/platforms/risc-v/common/index.rst
new file mode 100644
index 00000000000..76d3e749422
--- /dev/null
+++ b/Documentation/platforms/risc-v/common/index.rst
@@ -0,0 +1,151 @@
+===========================================================================
+RISC-V Specific Features
+===========================================================================
+
+RISC-V CLIC Interrupt Threshold Configuration
+==============================================
+
+Overview
+--------
+
+The RISC-V Core-Level Interrupt Controller (CLIC) provides more flexible 
interrupt
+control compared to the legacy CLINT. One key feature is the interrupt 
threshold
+mechanism (INTTHRESH), which allows fine-grained control over which interrupts
+are processed based on their priority levels.
+
+CLIC Interrupt Threshold Basics
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The CLIC interrupt threshold works by:
+
+1. **Threshold Register**: Each privilege mode has its own interrupt threshold 
register:
+   - Machine mode: ``CSR_MINTTHRESH`` (0x347)
+   - Supervisor mode: ``CSR_SINTTHRESH`` (0x147)
+
+2. **Interrupt Filtering**: Only interrupts with priority levels above the 
current
+   threshold are delivered to the processor.
+
+3. **Context Preservation**: The threshold value must be saved and restored 
during
+   context switches to maintain proper interrupt priority handling.
+
+Configuration in Custom Chip Layer
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Kconfig Configuration
+"""""""""""""""""""""
+
+To enable CLIC interrupt threshold support in your custom chip, add the 
following
+to your chip's Kconfig file:
+
+.. code-block:: kconfig
+
+   config ARCH_CHIP_MYCUSTOM_CHIP
+       bool "My Custom RISC-V Chip"
+       select ARCH_RV32  # or ARCH_RV64
+       select ARCH_RV_HAVE_CLIC
+       ---help---
+         My custom RISC-V chip with CLIC support
+
+Required Definitions
+""""""""""""""""""""
+
+In your chip-specific header file (e.g., 
``arch/risc-v/include/mycustom/irq.h``):
+
+.. code-block:: c
+
+   /* Define maximum interrupt threshold value for your CLIC implementation */
+   #define RISCV_MAX_INTTHRESH    255  /* Adjust based on your CLIC design */
+
+   /* Optional: Define interrupt priority levels */
+   #define CLIC_PRIO_CRITICAL          200
+   #define CLIC_PRIO_HIGH              150
+   #define CLIC_PRIO_NORMAL            100
+   #define CLIC_PRIO_LOW               50
+
+.. note::
+   If ``RISCV_MAX_INTTHRESH`` is not defined by the chip, NuttX will use a 
default
+   value of ``0xff`` (255). This default should work for most CLIC 
implementations
+   that support 8-bit interrupt threshold values. Chips with different 
threshold
+   widths should define their own maximum value accordingly.
+
+Implementation Details
+^^^^^^^^^^^^^^^^^^^^^^
+
+Interrupt Save/Restore Mechanism
+"""""""""""""""""""""""""""""""""
+
+When ``ARCH_RV_HAVE_CLIC`` is enabled, NuttX automatically uses the
+interrupt threshold register instead of the standard status register for
+interrupt control. The CLIC implementation uses the ``SWAP_CSR()`` macro
+for atomic read-modify-write operations on the threshold register:
+
+.. code-block:: c
+
+   /* Standard RISC-V interrupt disable (without CLIC) */
+   noinstrument_function static inline_function irqstate_t up_irq_save(void)
+   {
+     irqstate_t flags;
+
+     /* Read mstatus & clear machine interrupt enable (MIE) in mstatus */
+
+     __asm__ __volatile__
+       (
+         "csrrc %0, " __XSTR(CSR_STATUS) ", %1\n"
+         : "=r" (flags)
+         : "r"(STATUS_IE)
+         : "memory"
+       );
+
+     return flags;
+   }
+
+   /* CLIC interrupt threshold disable (with ARCH_RV_HAVE_CLIC) */
+   noinstrument_function static inline_function irqstate_t up_irq_save(void)
+   {
+     /* Read current interrupt threshold and set to maximum to mask all */
+
+     return SWAP_CSR(CSR_INTTHRESH, RISCV_MAX_INTTHRESH);
+   }
+
+Context Switch Handling
+"""""""""""""""""""""""
+
+The interrupt context register (``REG_INT_CTX``) stores different values
+depending on CLIC configuration:
+
+.. code-block:: c
+
+   /*
+    * Without CLIC (standard RISC-V): REG_INT_CTX stores CSR_MSTATUS or 
CSR_SSTATUS
+    * With CLIC (ARCH_RV_HAVE_CLIC): REG_INT_CTX stores CSR_MINTTHRESH or 
CSR_SINTTHRESH
+    *
+    * The interrupt context is automatically determined by the 
CONFIG_ARCH_RV_HAVE_CLIC
+    * configuration, eliminating the need for a separate threshold enable 
option.
+    */
+
+CLIC Driver Implementation
+""""""""""""""""""""""""""
+
+To implement the CLIC driver with interrupt threshold support, you may need to 
configure
+CLIC properly to handle priority management and threshold levels in your chip's
+driver code.
+
+Integration Checklist
+^^^^^^^^^^^^^^^^^^^^^^
+
+When integrating CLIC interrupt threshold support:
+
+☐ Enable ``ARCH_RV_HAVE_CLIC`` in Kconfig
+☐ Define ``RISCV_MAX_INTTHRESH`` for your chip (optional - defaults to 
0xff/255)
+☐ Implement CLIC driver with priority management
+☐ Verify interrupt threshold save/restore in context switches
+☐ Test interrupt priority levels and threshold functionality
+☐ Add debug support for troubleshooting
+
+References
+^^^^^^^^^^
+
+* RISC-V CLIC Specification
+* NuttX RISC-V Architecture Documentation
+* ``arch/risc-v/include/irq.h`` - Core interrupt handling definitions
+* ``arch/risc-v/src/common/riscv_exception_common.S`` - Assembly interrupt 
handling
diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig
index 8ca23643063..3e4eec577da 100644
--- a/arch/risc-v/Kconfig
+++ b/arch/risc-v/Kconfig
@@ -776,6 +776,15 @@ config ARCH_RV_HAVE_APLIC
                Controller (APLIC) to provide flexible interrupt control. This 
device
                is not backward compatible with PLIC.
 
+config ARCH_RV_HAVE_CLIC
+       bool
+       default n
+       ---help---
+               RISC-V defines Core-Level Interrupt Controller (CLIC) to provide
+               flexible interrupt control. When enabled, CLIC uses interrupt
+               threshold (MINTTHRESH/SINTTHRESH) CSRs for interrupt control
+               instead of the standard IE bit in STATUS register.
+
 config ARCH_RV_EXT_AIA
        bool "Enable RISC-V SxAIA support"
        default n
diff --git a/arch/risc-v/include/irq.h b/arch/risc-v/include/irq.h
index 77ef18eca07..9bf32c58b57 100644
--- a/arch/risc-v/include/irq.h
+++ b/arch/risc-v/include/irq.h
@@ -130,6 +130,14 @@
 
 #define RISCV_IRQ_MASK            (~RISCV_IRQ_BIT)
 
+#ifndef RISCV_MAX_INTTHRESH
+/* The maximum interrupt threshold value. This is the maximum value that
+ * can be set in the MINTTHRESH or SINTTHRESH CSR registers to mask all
+ * interrupts.
+ */
+#  define RISCV_MAX_INTTHRESH     (0xff)
+#endif
+
 /* Configuration ************************************************************/
 
 /* Processor PC */
@@ -197,14 +205,47 @@
 #define REG_X30_NDX         30
 #define REG_X31_NDX         31
 
-/* Interrupt Context register */
+/* Interrupt Context register
+ * This register stores interrupt-related state that needs to be preserved
+ * across context switches and interrupt handling.
+ *
+ * If ARCH_RV_HAVE_CLIC is enabled:
+ *   - Both machine mode and supervisor mode use CLIC to mask interrupts
+ *   - Contains the value of CSR_MINTTHRESH (Machine Interrupt Threshold)
+ *     in machine mode or CSR_SINTTHRESH (Supervisor Interrupt Threshold)
+ *     in supervisor mode
+ *   - CLIC (Core Local Interrupt Controller) extension allows setting a
+ *     threshold level below which interrupts are masked
+ *   - This threshold value must be saved/restored to maintain proper
+ *     interrupt priority handling across context switches
+ *
+ * Otherwise (standard RISC-V interrupt handling):
+ *   - Contains the value of CSR_MSTATUS (Machine Status Register) in
+ *     machine mode or CSR_SSTATUS (Supervisor Status Register) in
+ *     supervisor mode
+ *   - Preserves critical status bits including:
+ *     * MIE/SIE (Machine/Supervisor Interrupt Enable)
+ *     * MPIE/SPIE (Machine/Supervisor Previous Interrupt Enable)
+ *     * MPP/SPP (Machine/Supervisor Previous Privilege)
+ *     * FS (Floating Point Status) - floating-point unit state
+ *   - Essential for proper interrupt state restoration when returning
+ *     from exceptions or switching between tasks
+ *
+ * This context preservation ensures that interrupt handling behavior
+ * remains consistent across task switches and nested interrupt scenarios.
+ */
 
-#define REG_INT_CTX_NDX     32
+#ifdef CONFIG_ARCH_RV_HAVE_CLIC
+#  define REG_INT_THRESH_NDX  32
+#  define REG_INT_CTX_NDX     33
+#else
+#  define REG_INT_CTX_NDX     32
+#endif
 
 #ifdef CONFIG_ARCH_RISCV_INTXCPT_EXTREGS
-#  define INT_XCPT_REGS     (33 + CONFIG_ARCH_RISCV_INTXCPT_EXTREGS)
+#  define INT_XCPT_REGS     (REG_INT_CTX_NDX + 1 + 
CONFIG_ARCH_RISCV_INTXCPT_EXTREGS)
 #else
-#  define INT_XCPT_REGS     33
+#  define INT_XCPT_REGS     (REG_INT_CTX_NDX + 1)
 #endif
 
 #ifdef CONFIG_ARCH_RV32
@@ -346,6 +387,9 @@
 #  define REG_X29           (INT_REG_SIZE*REG_X29_NDX)
 #  define REG_X30           (INT_REG_SIZE*REG_X30_NDX)
 #  define REG_X31           (INT_REG_SIZE*REG_X31_NDX)
+#  ifdef CONFIG_ARCH_RV_HAVE_CLIC
+#    define REG_INT_THRESH  (INT_REG_SIZE*REG_INT_THRESH_NDX)
+#  endif
 #  define REG_INT_CTX       (INT_REG_SIZE*REG_INT_CTX_NDX)
 
 #ifdef CONFIG_ARCH_FPU
@@ -425,6 +469,9 @@
 #  define REG_X29           REG_X29_NDX
 #  define REG_X30           REG_X30_NDX
 #  define REG_X31           REG_X31_NDX
+#  ifdef CONFIG_ARCH_RV_HAVE_CLIC
+#    define REG_INT_THRESH  REG_INT_THRESH_NDX
+#  endif
 #  define REG_INT_CTX       REG_INT_CTX_NDX
 
 #ifdef CONFIG_ARCH_FPU
@@ -755,6 +802,42 @@ int up_this_cpu(void);
  * Inline Functions
  ****************************************************************************/
 
+#ifdef CONFIG_ARCH_RV_HAVE_CLIC
+
+/****************************************************************************
+ * Name: up_irq_save
+ *
+ * Description:
+ *   Disable interrupts by setting interrupt threshold to maximum and return
+ *   the previous threshold value
+ *
+ ****************************************************************************/
+
+noinstrument_function static inline_function irqstate_t up_irq_save(void)
+{
+  /* Read current interrupt threshold and set to maximum to mask all */
+
+  return SWAP_CSR(CSR_INTTHRESH, RISCV_MAX_INTTHRESH);
+}
+
+/****************************************************************************
+ * Name: up_irq_restore
+ *
+ * Description:
+ *   Restore the value of the interrupt threshold register
+ *
+ ****************************************************************************/
+
+noinstrument_function static inline_function
+void up_irq_restore(irqstate_t flags)
+{
+  /* Restore the interrupt threshold value */
+
+  WRITE_CSR(CSR_INTTHRESH, flags);
+}
+
+#else
+
 /****************************************************************************
  * Name: up_irq_save
  *
@@ -804,6 +887,8 @@ void up_irq_restore(irqstate_t flags)
     );
 }
 
+#endif /* CONFIG_ARCH_RV_HAVE_CLIC */
+
 /****************************************************************************
  * Name: up_set_interrupt_context
  *
diff --git a/arch/risc-v/include/mode.h b/arch/risc-v/include/mode.h
index c39523d4f24..2c81c008b65 100644
--- a/arch/risc-v/include/mode.h
+++ b/arch/risc-v/include/mode.h
@@ -53,6 +53,7 @@
 #  define CSR_IPH           CSR_SIPH
 #  define CSR_TOPEI         CSR_STOPEI       /* Top external interrupt 
register */
 #  define CSR_TOPI          CSR_STOPI        /* Top interrupt register */
+#  define CSR_INTTHRESH     CSR_SINTTHRESH   /* Interrupt threshold register */
 
 /* In status register */
 
@@ -102,6 +103,7 @@
 #  define CSR_IPH           CSR_MIPH
 #  define CSR_TOPEI         CSR_MTOPEI       /* Top external interrupt 
register */
 #  define CSR_TOPI          CSR_MTOPI        /* Top interrupt register */
+#  define CSR_INTTHRESH     CSR_MINTTHRESH   /* Interrupt threshold register */
 
 /* In status register */
 
diff --git a/arch/risc-v/src/common/riscv_exception_common.S 
b/arch/risc-v/src/common/riscv_exception_common.S
index 11570b3d69f..a98774ec2ae 100644
--- a/arch/risc-v/src/common/riscv_exception_common.S
+++ b/arch/risc-v/src/common/riscv_exception_common.S
@@ -147,6 +147,9 @@ exception_common:
   csrr       s0, CSR_STATUS       /* s0=status */
   csrr       s1, CSR_EPC          /* s1=exception PC */
   csrr       s2, CSR_CAUSE        /* s2=cause */
+#ifdef CONFIG_ARCH_RV_HAVE_CLIC
+  csrr       s4, CSR_INTTHRESH    /* s4=interrupt threshold */
+#endif
 
 #ifdef CONFIG_ARCH_KERNEL_STACK
   csrr       s3, CSR_SCRATCH
@@ -158,6 +161,9 @@ exception_common:
   REGSTORE   s0, REG_INT_CTX(sp)
   REGSTORE   s1, REG_EPC(sp)
   REGSTORE   s3, REG_SP(sp)
+#ifdef CONFIG_ARCH_RV_HAVE_CLIC
+  REGSTORE   s4, REG_INT_THRESH(sp)
+#endif
 
 #ifdef CONFIG_LIB_SYSCALL
   csrr       tp, CSR_SCRATCH      /* Load kernel TP */
@@ -281,6 +287,10 @@ return_from_exception:
 
   REGLOAD    s0, REG_INT_CTX(sp)  /* restore status */
   csrw       CSR_STATUS, s0
+#ifdef CONFIG_ARCH_RV_HAVE_CLIC
+  REGLOAD    s0, REG_INT_THRESH(sp) /* restore interrupt threshold */
+  csrw       CSR_INTTHRESH, s0
+#endif
 
 #ifdef CONFIG_LIB_SYSCALL
   /* Store tcb to scratch register */

Reply via email to