This patch adds kconfig option RISCV_SMODE to run U-Boot in
S-mode. When this opition is enabled we use s<xyz> CSRs instead
of m<xyz> CSRs.

It is important to note that there is no equivalent S-mode CSR
for misa and mhartid CSRs so we expect M-mode runtime firmware
(BBL or equivalent) to emulate misa and mhartid CSR read.

In-future, we will have more patches to avoid accessing misa and
mhartid CSRs from S-mode.

Signed-off-by: Anup Patel <a...@brainfault.org>
Reviewed-by: Bin Meng <bmeng...@gmail.com>
Tested-by: Bin Meng <bmeng...@gmail.com>
Reviewed-by: Lukas Auer <lukas.a...@aisec.fraunhofer.de>
---
 arch/riscv/Kconfig                |  5 +++++
 arch/riscv/cpu/start.S            | 33 ++++++++++++++++++++++++++++
 arch/riscv/include/asm/encoding.h |  2 ++
 arch/riscv/lib/interrupts.c       | 36 +++++++++++++++++++++++--------
 4 files changed, 67 insertions(+), 9 deletions(-)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 3e0af55e71..732a357a99 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -55,6 +55,11 @@ config RISCV_ISA_C
 config RISCV_ISA_A
        def_bool y
 
+config RISCV_SMODE
+       bool "Run in S-Mode"
+       help
+         Enable this option to build U-Boot for RISC-V S-Mode
+
 config 32BIT
        bool
 
diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S
index 5af189b338..e4276e8e19 100644
--- a/arch/riscv/cpu/start.S
+++ b/arch/riscv/cpu/start.S
@@ -39,10 +39,18 @@ _start:
        mv      s1, a1
 
        la      t0, trap_entry
+#ifdef CONFIG_RISCV_SMODE
+       csrw    stvec, t0
+#else
        csrw    mtvec, t0
+#endif
 
        /* mask all interrupts */
+#ifdef CONFIG_RISCV_SMODE
+       csrw    sie, zero
+#else
        csrw    mie, zero
+#endif
 
        /* Enable cache */
        jal     icache_enable
@@ -164,7 +172,11 @@ fix_rela_dyn:
 */
        la      t0, trap_entry
        add     t0, t0, t6
+#ifdef CONFIG_RISCV_SMODE
+       csrw    stvec, t0
+#else
        csrw    mtvec, t0
+#endif
 
 clear_bss:
        la      t0, __bss_start         /* t0 <- rel __bss_start in FLASH */
@@ -236,17 +248,34 @@ trap_entry:
        SREG    x29, 29*REGBYTES(sp)
        SREG    x30, 30*REGBYTES(sp)
        SREG    x31, 31*REGBYTES(sp)
+#ifdef CONFIG_RISCV_SMODE
+       csrr    a0, scause
+       csrr    a1, sepc
+#else
        csrr    a0, mcause
        csrr    a1, mepc
+#endif
        mv      a2, sp
        jal     handle_trap
+#ifdef CONFIG_RISCV_SMODE
+       csrw    sepc, a0
+#else
        csrw    mepc, a0
+#endif
 
+#ifdef CONFIG_RISCV_SMODE
+/*
+ * Remain in S-mode after sret
+ */
+       li      t0, SSTATUS_SPP
+       csrs    sstatus, t0
+#else
 /*
  * Remain in M-mode after mret
  */
        li      t0, MSTATUS_MPP
        csrs    mstatus, t0
+#endif
        LREG    x1, 1*REGBYTES(sp)
        LREG    x2, 2*REGBYTES(sp)
        LREG    x3, 3*REGBYTES(sp)
@@ -279,4 +308,8 @@ trap_entry:
        LREG    x30, 30*REGBYTES(sp)
        LREG    x31, 31*REGBYTES(sp)
        addi    sp, sp, 32*REGBYTES
+#ifdef CONFIG_RISCV_SMODE
+       sret
+#else
        mret
+#endif
diff --git a/arch/riscv/include/asm/encoding.h 
b/arch/riscv/include/asm/encoding.h
index 9ea50ce640..153f5af2ff 100644
--- a/arch/riscv/include/asm/encoding.h
+++ b/arch/riscv/include/asm/encoding.h
@@ -143,6 +143,8 @@
 # define MCAUSE_CAUSE MCAUSE32_CAUSE
 #endif
 
+#define SCAUSE_INT MCAUSE_INT
+
 #define RISCV_PGSHIFT 12
 #define RISCV_PGSIZE BIT(RISCV_PGSHIFT)
 
diff --git a/arch/riscv/lib/interrupts.c b/arch/riscv/lib/interrupts.c
index 903a1c4cd5..8793f233d0 100644
--- a/arch/riscv/lib/interrupts.c
+++ b/arch/riscv/lib/interrupts.c
@@ -34,17 +34,35 @@ int disable_interrupts(void)
        return 0;
 }
 
-ulong handle_trap(ulong mcause, ulong epc, struct pt_regs *regs)
+ulong handle_trap(ulong cause, ulong epc, struct pt_regs *regs)
 {
-       ulong is_int;
+       ulong is_irq, irq;
 
-       is_int = (mcause & MCAUSE_INT);
-       if ((is_int) && ((mcause & MCAUSE_CAUSE)  == IRQ_M_EXT))
-               external_interrupt(0);  /* handle_m_ext_interrupt */
-       else if ((is_int) && ((mcause & MCAUSE_CAUSE)  == IRQ_M_TIMER))
-               timer_interrupt(0);     /* handle_m_timer_interrupt */
-       else
-               _exit_trap(mcause, epc, regs);
+#ifdef CONFIG_RISCV_SMODE
+       is_irq = (cause & SCAUSE_INT);
+       irq = (cause & ~SCAUSE_INT);
+#else
+       is_irq = (cause & MCAUSE_INT);
+       irq = (cause & ~MCAUSE_INT);
+#endif
+
+       if (is_irq) {
+               switch (irq) {
+               case IRQ_M_EXT:
+               case IRQ_S_EXT:
+                       external_interrupt(0);  /* handle external interrupt */
+                       break;
+               case IRQ_M_TIMER:
+               case IRQ_S_TIMER:
+                       timer_interrupt(0);     /* handle timer interrupt */
+                       break;
+               default:
+                       _exit_trap(cause, epc, regs);
+                       break;
+               };
+       } else {
+               _exit_trap(cause, epc, regs);
+       }
 
        return epc;
 }
-- 
2.17.1

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to