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 */