summaryrefslogtreecommitdiff
path: root/libcpu
diff options
context:
space:
mode:
authorShell <[email protected]>2024-09-02 18:02:15 +0800
committerMeco Man <[email protected]>2024-09-11 18:06:51 -0400
commite244c196c4f1f5a867891df303476947a7769876 (patch)
tree1716b9d3472d1a3cd6904ee0b8c67a9f432a7b87 /libcpu
parenta00aaab2bac3b44baa55f5f25fe08b2d10c27c9b (diff)
feat: libcpu/risc-v: unify interrupt & IO on rv64
This patch aims to unify the two currently separated RISC-V 64-bit architecture ports, 'virt64' and 'c906', into a single generic 'common64' port. The changes include renaming files and updating includes to use a unified 'interrupt.h' header, as well as making adjustments to IO and trap handling to be more consistent between the two architectures. Changes: - Renamed 'rt_interrupt.h' to 'interrupt.h' and updated includes accordingly. - Unified IO register access functions in 'riscv_io.h'. - Added 'opcode.h' for portable assembly support. - Updated 'plic.c' and 'plic.h' to handle interrupts in a unified manner. - Modified 'trap.c' to handle exceptions and interrupts consistently for 'rv64'. Signed-off-by: Shell <[email protected]>
Diffstat (limited to 'libcpu')
-rw-r--r--libcpu/risc-v/t-head/c906/interrupt.c2
-rw-r--r--libcpu/risc-v/t-head/c906/interrupt.h (renamed from libcpu/risc-v/t-head/c906/rt_interrupt.h)0
-rw-r--r--libcpu/risc-v/t-head/c906/plic.c2
-rw-r--r--libcpu/risc-v/t-head/c906/plic.h2
-rw-r--r--libcpu/risc-v/t-head/c906/riscv.h13
-rw-r--r--libcpu/risc-v/t-head/c906/riscv_io.h154
-rw-r--r--libcpu/risc-v/t-head/c906/trap.c280
-rw-r--r--libcpu/risc-v/virt64/io.h4
-rw-r--r--libcpu/risc-v/virt64/opcode.h40
-rw-r--r--libcpu/risc-v/virt64/plic.c15
-rw-r--r--libcpu/risc-v/virt64/plic.h1
-rw-r--r--libcpu/risc-v/virt64/riscv_io.h34
-rw-r--r--libcpu/risc-v/virt64/trap.c226
13 files changed, 434 insertions, 339 deletions
diff --git a/libcpu/risc-v/t-head/c906/interrupt.c b/libcpu/risc-v/t-head/c906/interrupt.c
index 1cabe67587..9e4cf2f157 100644
--- a/libcpu/risc-v/t-head/c906/interrupt.c
+++ b/libcpu/risc-v/t-head/c906/interrupt.c
@@ -11,7 +11,7 @@
#include <rthw.h>
#include <rtthread.h>
-#include "rt_interrupt.h"
+#include "interrupt.h"
#include "riscv.h"
#include "plic.h"
diff --git a/libcpu/risc-v/t-head/c906/rt_interrupt.h b/libcpu/risc-v/t-head/c906/interrupt.h
index bdc98972b2..bdc98972b2 100644
--- a/libcpu/risc-v/t-head/c906/rt_interrupt.h
+++ b/libcpu/risc-v/t-head/c906/interrupt.h
diff --git a/libcpu/risc-v/t-head/c906/plic.c b/libcpu/risc-v/t-head/c906/plic.c
index 07f1333fa8..829ee9e4fd 100644
--- a/libcpu/risc-v/t-head/c906/plic.c
+++ b/libcpu/risc-v/t-head/c906/plic.c
@@ -15,7 +15,7 @@
#include <rtdbg.h>
#include "plic.h"
-#include "rt_interrupt.h"
+#include "interrupt.h"
#include "io.h"
#include "encoding.h"
#include "ioremap.h"
diff --git a/libcpu/risc-v/t-head/c906/plic.h b/libcpu/risc-v/t-head/c906/plic.h
index fab0f0fe5c..93235279e2 100644
--- a/libcpu/risc-v/t-head/c906/plic.h
+++ b/libcpu/risc-v/t-head/c906/plic.h
@@ -12,7 +12,7 @@
#ifndef __RISCV64_PLIC_H__
#define __RISCV64_PLIC_H__
-#include <rt_interrupt.h>
+#include <interrupt.h>
#ifndef C906_PLIC_PHY_ADDR
#define C906_PLIC_PHY_ADDR (0x10000000)
diff --git a/libcpu/risc-v/t-head/c906/riscv.h b/libcpu/risc-v/t-head/c906/riscv.h
index d0c0cc4b38..4adaaf1034 100644
--- a/libcpu/risc-v/t-head/c906/riscv.h
+++ b/libcpu/risc-v/t-head/c906/riscv.h
@@ -1,11 +1,12 @@
/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
+ * Copyright (c) 2006-2024, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-01-30 lizhirui first version
+ * 2024-08-28 RT-Thread Fit into rv64ilp32 ABI
*/
#ifndef __RISCV_H__
@@ -13,13 +14,15 @@
#include <encoding.h>
-#define __SIZE(bit) (1UL << (bit))
-#define __MASK(bit) (__SIZE(bit) - 1UL)
+/* using unsigned long long for the case of rv64ilp32 */
+#define __SIZE(bit) (1ULL << (bit))
+#define __MASK(bit) (__SIZE(bit) - 1ULL)
+
#define __UMASK(bit) (~(__MASK(bit)))
#define __MASKVALUE(value,maskvalue) ((value) & (maskvalue))
#define __UMASKVALUE(value,maskvalue) ((value) & (~(maskvalue)))
-#define __CHECKUPBOUND(value,bit_count) (!(((rt_size_t)value) & (~__MASK(bit_count))))
-#define __CHECKALIGN(value,start_bit) (!(((rt_size_t)value) & (__MASK(start_bit))))
+#define __CHECKUPBOUND(value,bit_count) (!(((rt_ubase_t)value) & (~__MASK(bit_count))))
+#define __CHECKALIGN(value,start_bit) (!(((rt_ubase_t)value) & (__MASK(start_bit))))
#define __PARTBIT(value,start_bit,length) (((value) >> (start_bit)) & __MASK(length))
diff --git a/libcpu/risc-v/t-head/c906/riscv_io.h b/libcpu/risc-v/t-head/c906/riscv_io.h
index cde0495b29..f5582fbbf8 100644
--- a/libcpu/risc-v/t-head/c906/riscv_io.h
+++ b/libcpu/risc-v/t-head/c906/riscv_io.h
@@ -10,100 +10,106 @@
#ifndef __RISCV_IO_H__
#define __RISCV_IO_H__
- static inline void __raw_writeb(rt_uint8_t val, volatile void *addr)
- {
- asm volatile("sb %0, 0(%1)" : : "r"(val), "r"(addr));
- }
+static inline uint32_t __raw_hartid(void)
+{
+ extern int boot_hartid;
+ return boot_hartid;
+}
- static inline void __raw_writew(rt_uint16_t val, volatile void *addr)
- {
- asm volatile("sh %0, 0(%1)" : : "r"(val), "r"(addr));
- }
+static inline void __raw_writeb(rt_uint8_t val, volatile void *addr)
+{
+ asm volatile("sb %0, 0(%1)" : : "r"(val), "r"(addr));
+}
- static inline void __raw_writel(rt_uint32_t val, volatile void *addr)
- {
- asm volatile("sw %0, 0(%1)" : : "r"(val), "r"(addr));
- }
+static inline void __raw_writew(rt_uint16_t val, volatile void *addr)
+{
+ asm volatile("sh %0, 0(%1)" : : "r"(val), "r"(addr));
+}
- #if __riscv_xlen != 32
- static inline void __raw_writeq(rt_uint64_t val, volatile void *addr)
- {
- asm volatile("sd %0, 0(%1)" : : "r"(val), "r"(addr));
- }
- #endif
+static inline void __raw_writel(rt_uint32_t val, volatile void *addr)
+{
+ asm volatile("sw %0, 0(%1)" : : "r"(val), "r"(addr));
+}
- static inline rt_uint8_t __raw_readb(const volatile void *addr)
- {
- rt_uint8_t val;
+#if __riscv_xlen != 32
+static inline void __raw_writeq(rt_uint64_t val, volatile void *addr)
+{
+ asm volatile("sd %0, 0(%1)" : : "r"(val), "r"(addr));
+}
+#endif
- asm volatile("lb %0, 0(%1)" : "=r"(val) : "r"(addr));
- return val;
- }
+static inline rt_uint8_t __raw_readb(const volatile void *addr)
+{
+ rt_uint8_t val;
- static inline rt_uint16_t __raw_readw(const volatile void *addr)
- {
- rt_uint16_t val;
+ asm volatile("lb %0, 0(%1)" : "=r"(val) : "r"(addr));
+ return val;
+}
- asm volatile("lh %0, 0(%1)" : "=r"(val) : "r"(addr));
- return val;
- }
+static inline rt_uint16_t __raw_readw(const volatile void *addr)
+{
+ rt_uint16_t val;
- static inline rt_uint32_t __raw_readl(const volatile void *addr)
- {
- rt_uint32_t val;
+ asm volatile("lh %0, 0(%1)" : "=r"(val) : "r"(addr));
+ return val;
+}
- asm volatile("lw %0, 0(%1)" : "=r"(val) : "r"(addr));
- return val;
- }
+static inline rt_uint32_t __raw_readl(const volatile void *addr)
+{
+ rt_uint32_t val;
- #if __riscv_xlen != 32
- static inline rt_uint64_t __raw_readq(const volatile void *addr)
- {
- rt_uint64_t val;
+ asm volatile("lw %0, 0(%1)" : "=r"(val) : "r"(addr));
+ return val;
+}
- asm volatile("ld %0, 0(%1)" : "=r"(val) : "r"(addr));
- return val;
- }
- #endif
+#if __riscv_xlen != 32
+static inline rt_uint64_t __raw_readq(const volatile void *addr)
+{
+ rt_uint64_t val;
- /* FIXME: These are now the same as asm-generic */
+ asm volatile("ld %0, 0(%1)" : "=r"(val) : "r"(addr));
+ return val;
+}
+#endif
- /* clang-format off */
+/* FIXME: These are now the same as asm-generic */
- #define __io_rbr() do {} while (0)
- #define __io_rar() do {} while (0)
- #define __io_rbw() do {} while (0)
- #define __io_raw() do {} while (0)
+/* clang-format off */
- #define readb_relaxed(c) ({ rt_uint8_t __v; __io_rbr(); __v = __raw_readb(c); __io_rar(); __v; })
- #define readw_relaxed(c) ({ rt_uint16_t __v; __io_rbr(); __v = __raw_readw(c); __io_rar(); __v; })
- #define readl_relaxed(c) ({ rt_uint32_t __v; __io_rbr(); __v = __raw_readl(c); __io_rar(); __v; })
+#define __io_rbr() do {} while (0)
+#define __io_rar() do {} while (0)
+#define __io_rbw() do {} while (0)
+#define __io_raw() do {} while (0)
- #define writeb_relaxed(v,c) ({ __io_rbw(); __raw_writeb((v),(c)); __io_raw(); })
- #define writew_relaxed(v,c) ({ __io_rbw(); __raw_writew((v),(c)); __io_raw(); })
- #define writel_relaxed(v,c) ({ __io_rbw(); __raw_writel((v),(c)); __io_raw(); })
+#define readb_relaxed(c) ({ rt_uint8_t __v; __io_rbr(); __v = __raw_readb(c); __io_rar(); __v; })
+#define readw_relaxed(c) ({ rt_uint16_t __v; __io_rbr(); __v = __raw_readw(c); __io_rar(); __v; })
+#define readl_relaxed(c) ({ rt_uint32_t __v; __io_rbr(); __v = __raw_readl(c); __io_rar(); __v; })
- #if __riscv_xlen != 32
- #define readq_relaxed(c) ({ rt_uint64_t __v; __io_rbr(); __v = __raw_readq(c); __io_rar(); __v; })
- #define writeq_relaxed(v,c) ({ __io_rbw(); __raw_writeq((v),(c)); __io_raw(); })
- #endif
+#define writeb_relaxed(v,c) ({ __io_rbw(); __raw_writeb((v),(c)); __io_raw(); })
+#define writew_relaxed(v,c) ({ __io_rbw(); __raw_writew((v),(c)); __io_raw(); })
+#define writel_relaxed(v,c) ({ __io_rbw(); __raw_writel((v),(c)); __io_raw(); })
- #define __io_br() do {} while (0)
- #define __io_ar() __asm__ __volatile__ ("fence i,r" : : : "memory");
- #define __io_bw() __asm__ __volatile__ ("fence w,o" : : : "memory");
- #define __io_aw() do {} while (0)
+#if __riscv_xlen != 32
+#define readq_relaxed(c) ({ rt_uint64_t __v; __io_rbr(); __v = __raw_readq(c); __io_rar(); __v; })
+#define writeq_relaxed(v,c) ({ __io_rbw(); __raw_writeq((v),(c)); __io_raw(); })
+#endif
- #define readb(c) ({ rt_uint8_t __v; __io_br(); __v = __raw_readb(c); __io_ar(); __v; })
- #define readw(c) ({ rt_uint16_t __v; __io_br(); __v = __raw_readw(c); __io_ar(); __v; })
- #define readl(c) ({ rt_uint32_t __v; __io_br(); __v = __raw_readl(c); __io_ar(); __v; })
+#define __io_br() do {} while (0)
+#define __io_ar() __asm__ __volatile__ ("fence i,r" : : : "memory");
+#define __io_bw() __asm__ __volatile__ ("fence w,o" : : : "memory");
+#define __io_aw() do {} while (0)
- #define writeb(v,c) ({ __io_bw(); __raw_writeb((v),(c)); __io_aw(); })
- #define writew(v,c) ({ __io_bw(); __raw_writew((v),(c)); __io_aw(); })
- #define writel(v,c) ({ __io_bw(); __raw_writel((v),(c)); __io_aw(); })
+#define readb(c) ({ rt_uint8_t __v; __io_br(); __v = __raw_readb(c); __io_ar(); __v; })
+#define readw(c) ({ rt_uint16_t __v; __io_br(); __v = __raw_readw(c); __io_ar(); __v; })
+#define readl(c) ({ rt_uint32_t __v; __io_br(); __v = __raw_readl(c); __io_ar(); __v; })
- #if __riscv_xlen != 32
- #define readq(c) ({ rt_uint64_t __v; __io_br(); __v = __raw_readq(c); __io_ar(); __v; })
- #define writeq(v,c) ({ __io_bw(); __raw_writeq((v),(c)); __io_aw(); })
- #endif
+#define writeb(v,c) ({ __io_bw(); __raw_writeb((v),(c)); __io_aw(); })
+#define writew(v,c) ({ __io_bw(); __raw_writew((v),(c)); __io_aw(); })
+#define writel(v,c) ({ __io_bw(); __raw_writel((v),(c)); __io_aw(); })
+
+#if __riscv_xlen != 32
+#define readq(c) ({ rt_uint64_t __v; __io_br(); __v = __raw_readq(c); __io_ar(); __v; })
+#define writeq(v,c) ({ __io_bw(); __raw_writeq((v),(c)); __io_aw(); })
+#endif
#endif
diff --git a/libcpu/risc-v/t-head/c906/trap.c b/libcpu/risc-v/t-head/c906/trap.c
index c4ba4bf333..abd4bed6bc 100644
--- a/libcpu/risc-v/t-head/c906/trap.c
+++ b/libcpu/risc-v/t-head/c906/trap.c
@@ -1,36 +1,29 @@
/*
- * Copyright (c) 2006-2021, RT-Thread Development Team
+ * Copyright (c) 2006-2024, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
- * 2021/1/30 lizirui first version
- * 2021/10/20 JasonHu move to trap.c
+ * 2022-12-08 RT-Thread first version
*/
#include <rthw.h>
#include <rtthread.h>
#include <stdint.h>
-
-#include "board.h"
-#include "tick.h"
-
#include <mm_fault.h>
-#include "mmu.h"
-#include "encoding.h"
-#include "stack.h"
-#include "sbi.h"
-#include "riscv.h"
-#include "rt_interrupt.h"
-#include "plic.h"
+#include <mmu.h>
+#include <encoding.h>
+#include <stack.h>
+#include <sbi.h>
+#include <riscv.h>
+#include <interrupt.h>
+#include <plic.h>
+#include <tick.h>
#ifdef RT_USING_SMART
#include <lwp_arch.h>
-void rt_hw_backtrace(rt_uint32_t *ffp, rt_ubase_t sepc);
-#else
-#define rt_hw_backtrace(...) (0)
#endif
#define DBG_TAG "libcpu.trap"
@@ -42,7 +35,8 @@ void dump_regs(struct rt_hw_stack_frame *regs)
rt_kprintf("--------------Dump Registers-----------------\n");
rt_kprintf("Function Registers:\n");
- rt_kprintf("\tra(x1) = 0x%p\tuser_sp = 0x%p\n", regs->ra, regs->user_sp_exc_stack);
+ rt_kprintf("\tra(x1) = 0x%p\tuser_sp = 0x%p\n", regs->ra,
+ regs->user_sp_exc_stack);
rt_kprintf("\tgp(x3) = 0x%p\ttp(x4) = 0x%p\n", regs->gp, regs->tp);
rt_kprintf("Temporary Registers:\n");
rt_kprintf("\tt0(x5) = 0x%p\tt1(x6) = 0x%p\n", regs->t0, regs->t1);
@@ -62,15 +56,27 @@ void dump_regs(struct rt_hw_stack_frame *regs)
rt_kprintf("\ta4(x14) = 0x%p\ta5(x15) = 0x%p\n", regs->a4, regs->a5);
rt_kprintf("\ta6(x16) = 0x%p\ta7(x17) = 0x%p\n", regs->a6, regs->a7);
rt_kprintf("sstatus = 0x%p\n", regs->sstatus);
- rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SIE) ? "Supervisor Interrupt Enabled" : "Supervisor Interrupt Disabled");
- rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SPIE) ? "Last Time Supervisor Interrupt Enabled" : "Last Time Supervisor Interrupt Disabled");
- rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SPP) ? "Last Privilege is Supervisor Mode" : "Last Privilege is User Mode");
- rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SUM) ? "Permit to Access User Page" : "Not Permit to Access User Page");
- rt_kprintf("\t%s\n", (regs->sstatus & (1 << 19)) ? "Permit to Read Executable-only Page" : "Not Permit to Read Executable-only Page");
- rt_size_t satp_v = read_csr(satp);
+ rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SIE)
+ ? "Supervisor Interrupt Enabled"
+ : "Supervisor Interrupt Disabled");
+ rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SPIE)
+ ? "Last Time Supervisor Interrupt Enabled"
+ : "Last Time Supervisor Interrupt Disabled");
+ rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SPP)
+ ? "Last Privilege is Supervisor Mode"
+ : "Last Privilege is User Mode");
+ rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SUM)
+ ? "Permit to Access User Page"
+ : "Not Permit to Access User Page");
+ rt_kprintf("\t%s\n", (regs->sstatus & (1 << 19))
+ ? "Permit to Read Executable-only Page"
+ : "Not Permit to Read Executable-only Page");
+ rt_ubase_t satp_v = read_csr(satp);
rt_kprintf("satp = 0x%p\n", satp_v);
- rt_kprintf("\tCurrent Page Table(Physical) = 0x%p\n", __MASKVALUE(satp_v, __MASK(44)) << PAGE_OFFSET_BIT);
- rt_kprintf("\tCurrent ASID = 0x%p\n", __MASKVALUE(satp_v >> 44, __MASK(16)) << PAGE_OFFSET_BIT);
+ rt_kprintf("\tCurrent Page Table(Physical) = 0x%p\n",
+ __MASKVALUE(satp_v, __MASK(44)) << PAGE_OFFSET_BIT);
+ rt_kprintf("\tCurrent ASID = 0x%p\n", __MASKVALUE(satp_v >> 44, __MASK(16))
+ << PAGE_OFFSET_BIT);
const char *mode_str = "Unknown Address Translation/Protection Mode";
switch (__MASKVALUE(satp_v >> 60, __MASK(4)))
@@ -92,50 +98,44 @@ void dump_regs(struct rt_hw_stack_frame *regs)
rt_kprintf("-----------------Dump OK---------------------\n");
}
-static const char *Exception_Name[] =
- {
- "Instruction Address Misaligned",
- "Instruction Access Fault",
- "Illegal Instruction",
- "Breakpoint",
- "Load Address Misaligned",
- "Load Access Fault",
- "Store/AMO Address Misaligned",
- "Store/AMO Access Fault",
- "Environment call from U-mode",
- "Environment call from S-mode",
- "Reserved-10",
- "Reserved-11",
- "Instruction Page Fault",
- "Load Page Fault",
- "Reserved-14",
- "Store/AMO Page Fault"};
+static const char *Exception_Name[] = {"Instruction Address Misaligned",
+ "Instruction Access Fault",
+ "Illegal Instruction",
+ "Breakpoint",
+ "Load Address Misaligned",
+ "Load Access Fault",
+ "Store/AMO Address Misaligned",
+ "Store/AMO Access Fault",
+ "Environment call from U-mode",
+ "Environment call from S-mode",
+ "Reserved-10",
+ "Reserved-11",
+ "Instruction Page Fault",
+ "Load Page Fault",
+ "Reserved-14",
+ "Store/AMO Page Fault"};
-static const char *Interrupt_Name[] =
- {
- "User Software Interrupt",
- "Supervisor Software Interrupt",
- "Reversed-2",
- "Reversed-3",
- "User Timer Interrupt",
- "Supervisor Timer Interrupt",
- "Reversed-6",
- "Reversed-7",
- "User External Interrupt",
- "Supervisor External Interrupt",
- "Reserved-10",
- "Reserved-11",
+static const char *Interrupt_Name[] = {
+ "User Software Interrupt",
+ "Supervisor Software Interrupt",
+ "Reversed-2",
+ "Reversed-3",
+ "User Timer Interrupt",
+ "Supervisor Timer Interrupt",
+ "Reversed-6",
+ "Reversed-7",
+ "User External Interrupt",
+ "Supervisor External Interrupt",
+ "Reserved-10",
+ "Reserved-11",
};
#ifndef RT_USING_SMP
static volatile int nested = 0;
-#define ENTER_TRAP \
- nested += 1
-#define EXIT_TRAP \
- nested -= 1
+#define ENTER_TRAP nested += 1
+#define EXIT_TRAP nested -= 1
#define CHECK_NESTED_PANIC(cause, tval, epc, eframe) \
- if (nested != 1) \
- handle_nested_trap_panic(cause, tval, epc, eframe)
+ if (nested != 1) handle_nested_trap_panic(cause, tval, epc, eframe)
#endif /* RT_USING_SMP */
static const char *get_exception_msg(int id)
@@ -153,9 +153,11 @@ static const char *get_exception_msg(int id)
}
#ifdef RT_USING_SMART
-void handle_user(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw_stack_frame *sp)
+#include "lwp.h"
+void handle_user(rt_ubase_t scause, rt_ubase_t stval, rt_ubase_t sepc,
+ struct rt_hw_stack_frame *sp)
{
- rt_size_t id = __MASKVALUE(scause, __MASK(63UL));
+ rt_ubase_t id = __MASKVALUE(scause, __MASK(63UL));
struct rt_lwp *lwp;
/* user page fault */
@@ -165,11 +167,11 @@ void handle_user(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw
{
case EP_LOAD_PAGE_FAULT:
fault_op = MM_FAULT_OP_READ;
- fault_type = MM_FAULT_TYPE_PAGE_FAULT;
+ fault_type = MM_FAULT_TYPE_GENERIC_MMU;
break;
case EP_LOAD_ACCESS_FAULT:
fault_op = MM_FAULT_OP_READ;
- fault_type = MM_FAULT_TYPE_GENERIC;
+ fault_type = MM_FAULT_TYPE_BUS_ERROR;
break;
case EP_LOAD_ADDRESS_MISALIGNED:
fault_op = MM_FAULT_OP_READ;
@@ -177,11 +179,11 @@ void handle_user(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw
break;
case EP_STORE_PAGE_FAULT:
fault_op = MM_FAULT_OP_WRITE;
- fault_type = MM_FAULT_TYPE_PAGE_FAULT;
+ fault_type = MM_FAULT_TYPE_GENERIC_MMU;
break;
case EP_STORE_ACCESS_FAULT:
fault_op = MM_FAULT_OP_WRITE;
- fault_type = MM_FAULT_TYPE_GENERIC;
+ fault_type = MM_FAULT_TYPE_BUS_ERROR;
break;
case EP_STORE_ADDRESS_MISALIGNED:
fault_op = MM_FAULT_OP_WRITE;
@@ -189,11 +191,11 @@ void handle_user(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw
break;
case EP_INSTRUCTION_PAGE_FAULT:
fault_op = MM_FAULT_OP_EXECUTE;
- fault_type = MM_FAULT_TYPE_PAGE_FAULT;
+ fault_type = MM_FAULT_TYPE_GENERIC_MMU;
break;
case EP_INSTRUCTION_ACCESS_FAULT:
fault_op = MM_FAULT_OP_EXECUTE;
- fault_type = MM_FAULT_TYPE_GENERIC;
+ fault_type = MM_FAULT_TYPE_BUS_ERROR;
break;
case EP_INSTRUCTION_ADDRESS_MISALIGNED:
fault_op = MM_FAULT_OP_EXECUTE;
@@ -213,28 +215,31 @@ void handle_user(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw
.fault_vaddr = (void *)stval,
};
- __asm__ volatile ("csrrsi %0, sstatus, 2":"=r"(saved_stat));
+ __asm__ volatile("csrrsi %0, sstatus, 2" : "=r"(saved_stat));
if (lwp && rt_aspace_fault_try_fix(lwp->aspace, &msg))
{
- __asm__ volatile ("csrw sstatus, %0"::"r"(saved_stat));
+ __asm__ volatile("csrw sstatus, %0" ::"r"(saved_stat));
return;
}
- __asm__ volatile ("csrw sstatus, %0"::"r"(saved_stat));
+ __asm__ volatile("csrw sstatus, %0" ::"r"(saved_stat));
}
LOG_E("[FATAL ERROR] Exception %ld:%s\n", id, get_exception_msg(id));
LOG_E("scause:0x%p,stval:0x%p,sepc:0x%p\n", scause, stval, sepc);
dump_regs(sp);
- rt_hw_backtrace((uint32_t *)sp->s0_fp, sepc);
+ rt_thread_t cur_thr = rt_thread_self();
+ struct rt_hw_backtrace_frame frame = {.fp = sp->s0_fp, .pc = sepc};
+ rt_kprintf("fp = %p\n", frame.fp);
+ lwp_backtrace_frame(cur_thr, &frame);
- LOG_E("User Fault, killing thread: %s", rt_thread_self()->parent.name);
+ LOG_E("User Fault, killing thread: %s", cur_thr->parent.name);
EXIT_TRAP;
sys_exit_group(-1);
}
#endif
-#ifdef ENABLE_VECTOR
+#ifdef ARCH_RISCV_VECTOR
static void vector_enable(struct rt_hw_stack_frame *sp)
{
sp->sstatus |= SSTATUS_VS_INITIAL;
@@ -243,7 +248,8 @@ static void vector_enable(struct rt_hw_stack_frame *sp)
/**
* detect V/D support, and do not distinguish V/D instruction
*/
-static int illegal_inst_recoverable(rt_ubase_t stval, struct rt_hw_stack_frame *sp)
+static int illegal_inst_recoverable(rt_ubase_t stval,
+ struct rt_hw_stack_frame *sp)
{
// first 7 bits is opcode
int opcode = stval & 0x7f;
@@ -254,12 +260,12 @@ static int illegal_inst_recoverable(rt_ubase_t stval, struct rt_hw_stack_frame *
switch (opcode)
{
- case 0x57: // V
- case 0x27: // scalar FLOAT
- case 0x07:
- case 0x73: // CSR
- flag = 1;
- break;
+ case 0x57: // V
+ case 0x27: // scalar FLOAT
+ case 0x07:
+ case 0x73: // CSR
+ flag = 1;
+ break;
}
if (flag)
@@ -271,11 +277,9 @@ static int illegal_inst_recoverable(rt_ubase_t stval, struct rt_hw_stack_frame *
}
#endif
-static void handle_nested_trap_panic(
- rt_size_t cause,
- rt_size_t tval,
- rt_size_t epc,
- struct rt_hw_stack_frame *eframe)
+static void handle_nested_trap_panic(rt_ubase_t cause, rt_ubase_t tval,
+ rt_ubase_t epc,
+ struct rt_hw_stack_frame *eframe)
{
LOG_E("\n-------- [SEVER ERROR] --------");
LOG_E("Nested trap detected");
@@ -285,21 +289,23 @@ static void handle_nested_trap_panic(
}
#define IN_USER_SPACE (stval >= USER_VADDR_START && stval < USER_VADDR_TOP)
-#define PAGE_FAULT (id == EP_LOAD_PAGE_FAULT || id == EP_STORE_PAGE_FAULT)
+#define PAGE_FAULT (id == EP_LOAD_PAGE_FAULT || id == EP_STORE_PAGE_FAULT)
/* Trap entry */
-void handle_trap(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw_stack_frame *sp)
+void handle_trap(rt_ubase_t scause, rt_ubase_t stval, rt_ubase_t sepc,
+ struct rt_hw_stack_frame *sp)
{
- rt_size_t id = __MASKVALUE(scause,__MASK(63UL));
+ ENTER_TRAP;
+ rt_ubase_t id = __MASKVALUE(scause, __MASK(63UL));
const char *msg;
/* supervisor external interrupt */
- if ((SCAUSE_INTERRUPT & scause) && SCAUSE_S_EXTERNAL_INTR == (scause & 0xff))
+ if ((SCAUSE_INTERRUPT & scause) &&
+ SCAUSE_S_EXTERNAL_INTR == (scause & 0xff))
{
rt_interrupt_enter();
plic_handle_irq();
rt_interrupt_leave();
- return;
}
else if ((SCAUSE_INTERRUPT | SCAUSE_S_TIMER_INTR) == scause)
{
@@ -307,44 +313,74 @@ void handle_trap(rt_size_t scause, rt_size_t stval, rt_size_t sepc, struct rt_hw
rt_interrupt_enter();
tick_isr();
rt_interrupt_leave();
- return;
}
- else if (SCAUSE_INTERRUPT & scause)
+ else
{
- if(id < sizeof(Interrupt_Name) / sizeof(const char *))
+ if (SCAUSE_INTERRUPT & scause)
{
- msg = Interrupt_Name[id];
+ if (id < sizeof(Interrupt_Name) / sizeof(const char *))
+ {
+ msg = Interrupt_Name[id];
+ }
+ else
+ {
+ msg = "Unknown Interrupt";
+ }
+
+ LOG_E("Unhandled Interrupt %ld:%s\n", id, msg);
}
else
{
- msg = "Unknown Interrupt";
+#ifdef ARCH_RISCV_VECTOR
+ if (scause == 0x2)
+ {
+ if (!(sp->sstatus & SSTATUS_VS) &&
+ illegal_inst_recoverable(stval, sp))
+ goto _exit;
+ }
+#endif /* ARCH_RISCV_VECTOR */
+#ifdef RT_USING_SMART
+ if (!(sp->sstatus & 0x100) || (PAGE_FAULT && IN_USER_SPACE))
+ {
+ handle_user(scause, stval, sepc, sp);
+ // if handle_user() return here, jump to u mode then
+ goto _exit;
+ }
+#endif
+
+ // handle kernel exception:
+ rt_kprintf("Unhandled Exception %ld:%s\n", id,
+ get_exception_msg(id));
}
- LOG_E("Unhandled Interrupt %ld:%s\n",id,msg);
- }
- else
- {
+
+ // trap cannot nested when handling another trap / interrupt
+ CHECK_NESTED_PANIC(scause, stval, sepc, sp);
+
+ rt_kprintf("scause:0x%p,stval:0x%p,sepc:0x%p\n", scause, stval, sepc);
+ dump_regs(sp);
+
+ rt_thread_t cur_thr = rt_thread_self();
+ rt_kprintf("--------------Thread list--------------\n");
+ rt_kprintf("current thread: %s\n", cur_thr->parent.name);
+
+ rt_kprintf("--------------Backtrace--------------\n");
+ struct rt_hw_backtrace_frame frame = {.fp = sp->s0_fp, .pc = sepc};
+
#ifdef RT_USING_SMART
- if (!(sp->sstatus & 0x100) || (PAGE_FAULT && IN_USER_SPACE))
+ if (!(sp->sstatus & 0x100))
{
- handle_user(scause, stval, sepc, sp);
- // if handle_user() return here, jump to u mode then
- return ;
+ lwp_backtrace_frame(cur_thr, &frame);
}
+ else
#endif
+ {
+ rt_backtrace_frame(cur_thr, &frame);
+ }
- // handle kernel exception:
- rt_kprintf("Unhandled Exception %ld:%s\n", id, get_exception_msg(id));
+ while (1)
+ ;
}
-
- rt_kprintf("scause:0x%p,stval:0x%p,sepc:0x%p\n", scause, stval, sepc);
- dump_regs(sp);
- rt_kprintf("--------------Thread list--------------\n");
- rt_kprintf("current thread: %s\n", rt_thread_self()->parent.name);
-
- extern struct rt_thread *rt_current_thread;
- rt_kprintf("--------------Backtrace--------------\n");
- rt_hw_backtrace((uint32_t *)sp->s0_fp, sepc);
-
- while (1)
- ;
+_exit:
+ EXIT_TRAP;
+ return;
}
diff --git a/libcpu/risc-v/virt64/io.h b/libcpu/risc-v/virt64/io.h
index 1285d5955b..97dca5af97 100644
--- a/libcpu/risc-v/virt64/io.h
+++ b/libcpu/risc-v/virt64/io.h
@@ -40,13 +40,13 @@ static inline uint32_t readl(const volatile void *addr)
static inline void write_reg(
uint32_t val, volatile void *addr, unsigned offset)
{
- writel(val, addr + offset);
+ writel(val, (void *)((rt_size_t)addr + offset));
}
static inline uint32_t read_reg(
const volatile void *addr, unsigned offset)
{
- return readl(addr + offset);
+ return readl((void *)((rt_size_t)addr + offset));
}
#endif // ARCH_IO_H
diff --git a/libcpu/risc-v/virt64/opcode.h b/libcpu/risc-v/virt64/opcode.h
new file mode 100644
index 0000000000..14a6a73649
--- /dev/null
+++ b/libcpu/risc-v/virt64/opcode.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2022-11-09 Shell Add portable asm support
+ */
+#ifndef __OPCODE_H__
+#define __OPCODE_H__
+
+/**
+ * @brief binary opcode pseudo operations
+ * Used to bypass toolchain restriction on extension ISA
+ *
+ */
+
+/**
+ * @brief RISC-V instruction formats
+ */
+
+/**
+ * R type: .insn r opcode6, func3, func7, rd, rs1, rs2
+ *
+ * +-------+-----+-----+-------+----+---------+
+ * | func7 | rs2 | rs1 | func3 | rd | opcode6 |
+ * +-------+-----+-----+-------+----+---------+
+ * 31 25 20 15 12 7 0
+ */
+#define __OPC_INSN_FORMAT_R(opcode, func3, func7, rd, rs1, rs2) \
+ ".insn r "RT_STRINGIFY(opcode)","RT_STRINGIFY(func3)","RT_STRINGIFY(func7)","RT_STRINGIFY(rd)","RT_STRINGIFY(rs1)","RT_STRINGIFY(rs2)
+
+#ifdef _TOOLCHAIN_SUPP_ZIFENCEI_ISA_
+#define OPC_FENCE_I "fence.i"
+#else /* !_TOOLCHAIN_SUPP_ZIFENCEI_ISA_ */
+#define OPC_FENCE_I ".long 0x0000100F"
+#endif /* _TOOLCHAIN_SUPP_ZIFENCEI_ISA_ */
+
+#endif /* __OPCODE_H__ */ \ No newline at end of file
diff --git a/libcpu/risc-v/virt64/plic.c b/libcpu/risc-v/virt64/plic.c
index bd87df0e62..f222146f34 100644
--- a/libcpu/risc-v/virt64/plic.c
+++ b/libcpu/risc-v/virt64/plic.c
@@ -14,6 +14,7 @@
#include "plic.h"
#include <riscv_io.h>
#include "encoding.h"
+#include <interrupt.h>
#include <riscv.h>
#include <string.h>
@@ -139,3 +140,17 @@ void plic_init()
// in a single core system, only current context was set
_set_sie(__raw_hartid());
}
+
+extern struct rt_irq_desc irq_desc[MAX_HANDLERS];
+/*
+ * Handling an interrupt is a two-step process: first you claim the interrupt
+ * by reading the claim register, then you complete the interrupt by writing
+ * that source ID back to the same claim register. This automatically enables
+ * and disables the interrupt, so there's nothing else to do.
+ */
+void plic_handle_irq(void)
+{
+ int plic_irq = plic_claim();
+ plic_complete(plic_irq);
+ irq_desc[plic_irq].handler(plic_irq, irq_desc[plic_irq].param);
+}
diff --git a/libcpu/risc-v/virt64/plic.h b/libcpu/risc-v/virt64/plic.h
index d24c2e5a53..314210c66b 100644
--- a/libcpu/risc-v/virt64/plic.h
+++ b/libcpu/risc-v/virt64/plic.h
@@ -72,5 +72,6 @@ void plic_complete(int irq);
void plic_set_thresh(rt_uint32_t val);
void plic_set_ie(rt_uint32_t word_index,rt_uint32_t val);
void plic_init();
+void plic_handle_irq(void);
#endif
diff --git a/libcpu/risc-v/virt64/riscv_io.h b/libcpu/risc-v/virt64/riscv_io.h
index b92e24e4c9..f5582fbbf8 100644
--- a/libcpu/risc-v/virt64/riscv_io.h
+++ b/libcpu/risc-v/virt64/riscv_io.h
@@ -10,7 +10,7 @@
#ifndef __RISCV_IO_H__
#define __RISCV_IO_H__
-static inline uint32_t __raw_hartid(void)
+static inline uint32_t __raw_hartid(void)
{
extern int boot_hartid;
return boot_hartid;
@@ -18,31 +18,23 @@ static inline uint32_t __raw_hartid(void)
static inline void __raw_writeb(rt_uint8_t val, volatile void *addr)
{
- asm volatile("sb %0, 0(%1)"
- :
- : "r"(val), "r"(addr));
+ asm volatile("sb %0, 0(%1)" : : "r"(val), "r"(addr));
}
static inline void __raw_writew(rt_uint16_t val, volatile void *addr)
{
- asm volatile("sh %0, 0(%1)"
- :
- : "r"(val), "r"(addr));
+ asm volatile("sh %0, 0(%1)" : : "r"(val), "r"(addr));
}
static inline void __raw_writel(rt_uint32_t val, volatile void *addr)
{
- asm volatile("sw %0, 0(%1)"
- :
- : "r"(val), "r"(addr));
+ asm volatile("sw %0, 0(%1)" : : "r"(val), "r"(addr));
}
#if __riscv_xlen != 32
static inline void __raw_writeq(rt_uint64_t val, volatile void *addr)
{
- asm volatile("sd %0, 0(%1)"
- :
- : "r"(val), "r"(addr));
+ asm volatile("sd %0, 0(%1)" : : "r"(val), "r"(addr));
}
#endif
@@ -50,9 +42,7 @@ static inline rt_uint8_t __raw_readb(const volatile void *addr)
{
rt_uint8_t val;
- asm volatile("lb %0, 0(%1)"
- : "=r"(val)
- : "r"(addr));
+ asm volatile("lb %0, 0(%1)" : "=r"(val) : "r"(addr));
return val;
}
@@ -60,9 +50,7 @@ static inline rt_uint16_t __raw_readw(const volatile void *addr)
{
rt_uint16_t val;
- asm volatile("lh %0, 0(%1)"
- : "=r"(val)
- : "r"(addr));
+ asm volatile("lh %0, 0(%1)" : "=r"(val) : "r"(addr));
return val;
}
@@ -70,9 +58,7 @@ static inline rt_uint32_t __raw_readl(const volatile void *addr)
{
rt_uint32_t val;
- asm volatile("lw %0, 0(%1)"
- : "=r"(val)
- : "r"(addr));
+ asm volatile("lw %0, 0(%1)" : "=r"(val) : "r"(addr));
return val;
}
@@ -81,9 +67,7 @@ static inline rt_uint64_t __raw_readq(const volatile void *addr)
{
rt_uint64_t val;
- asm volatile("ld %0, 0(%1)"
- : "=r"(val)
- : "r"(addr));
+ asm volatile("ld %0, 0(%1)" : "=r"(val) : "r"(addr));
return val;
}
#endif
diff --git a/libcpu/risc-v/virt64/trap.c b/libcpu/risc-v/virt64/trap.c
index 3b0f86fe0e..abd4bed6bc 100644
--- a/libcpu/risc-v/virt64/trap.c
+++ b/libcpu/risc-v/virt64/trap.c
@@ -7,24 +7,23 @@
* Date Author Notes
* 2022-12-08 RT-Thread first version
*/
+
#include <rthw.h>
#include <rtthread.h>
#include <stdint.h>
#include <mm_fault.h>
-#include "mmu.h"
-#include "encoding.h"
-#include "stack.h"
-#include "sbi.h"
-#include "riscv.h"
-#include "interrupt.h"
-#include "plic.h"
-#include "tick.h"
+#include <mmu.h>
+#include <encoding.h>
+#include <stack.h>
+#include <sbi.h>
+#include <riscv.h>
+#include <interrupt.h>
+#include <plic.h>
+#include <tick.h>
#ifdef RT_USING_SMART
#include <lwp_arch.h>
-#else
-#define rt_hw_backtrace(...) (0)
#endif
#define DBG_TAG "libcpu.trap"
@@ -36,7 +35,8 @@ void dump_regs(struct rt_hw_stack_frame *regs)
rt_kprintf("--------------Dump Registers-----------------\n");
rt_kprintf("Function Registers:\n");
- rt_kprintf("\tra(x1) = 0x%p\tuser_sp = 0x%p\n", regs->ra, regs->user_sp_exc_stack);
+ rt_kprintf("\tra(x1) = 0x%p\tuser_sp = 0x%p\n", regs->ra,
+ regs->user_sp_exc_stack);
rt_kprintf("\tgp(x3) = 0x%p\ttp(x4) = 0x%p\n", regs->gp, regs->tp);
rt_kprintf("Temporary Registers:\n");
rt_kprintf("\tt0(x5) = 0x%p\tt1(x6) = 0x%p\n", regs->t0, regs->t1);
@@ -56,15 +56,27 @@ void dump_regs(struct rt_hw_stack_frame *regs)
rt_kprintf("\ta4(x14) = 0x%p\ta5(x15) = 0x%p\n", regs->a4, regs->a5);
rt_kprintf("\ta6(x16) = 0x%p\ta7(x17) = 0x%p\n", regs->a6, regs->a7);
rt_kprintf("sstatus = 0x%p\n", regs->sstatus);
- rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SIE) ? "Supervisor Interrupt Enabled" : "Supervisor Interrupt Disabled");
- rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SPIE) ? "Last Time Supervisor Interrupt Enabled" : "Last Time Supervisor Interrupt Disabled");
- rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SPP) ? "Last Privilege is Supervisor Mode" : "Last Privilege is User Mode");
- rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SUM) ? "Permit to Access User Page" : "Not Permit to Access User Page");
- rt_kprintf("\t%s\n", (regs->sstatus & (1 << 19)) ? "Permit to Read Executable-only Page" : "Not Permit to Read Executable-only Page");
+ rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SIE)
+ ? "Supervisor Interrupt Enabled"
+ : "Supervisor Interrupt Disabled");
+ rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SPIE)
+ ? "Last Time Supervisor Interrupt Enabled"
+ : "Last Time Supervisor Interrupt Disabled");
+ rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SPP)
+ ? "Last Privilege is Supervisor Mode"
+ : "Last Privilege is User Mode");
+ rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SUM)
+ ? "Permit to Access User Page"
+ : "Not Permit to Access User Page");
+ rt_kprintf("\t%s\n", (regs->sstatus & (1 << 19))
+ ? "Permit to Read Executable-only Page"
+ : "Not Permit to Read Executable-only Page");
rt_ubase_t satp_v = read_csr(satp);
rt_kprintf("satp = 0x%p\n", satp_v);
- rt_kprintf("\tCurrent Page Table(Physical) = 0x%p\n", __MASKVALUE(satp_v, __MASK(44)) << PAGE_OFFSET_BIT);
- rt_kprintf("\tCurrent ASID = 0x%p\n", __MASKVALUE(satp_v >> 44, __MASK(16)) << PAGE_OFFSET_BIT);
+ rt_kprintf("\tCurrent Page Table(Physical) = 0x%p\n",
+ __MASKVALUE(satp_v, __MASK(44)) << PAGE_OFFSET_BIT);
+ rt_kprintf("\tCurrent ASID = 0x%p\n", __MASKVALUE(satp_v >> 44, __MASK(16))
+ << PAGE_OFFSET_BIT);
const char *mode_str = "Unknown Address Translation/Protection Mode";
switch (__MASKVALUE(satp_v >> 60, __MASK(4)))
@@ -86,52 +98,44 @@ void dump_regs(struct rt_hw_stack_frame *regs)
rt_kprintf("-----------------Dump OK---------------------\n");
}
-static const char *Exception_Name[] =
- {
- "Instruction Address Misaligned",
- "Instruction Access Fault",
- "Illegal Instruction",
- "Breakpoint",
- "Load Address Misaligned",
- "Load Access Fault",
- "Store/AMO Address Misaligned",
- "Store/AMO Access Fault",
- "Environment call from U-mode",
- "Environment call from S-mode",
- "Reserved-10",
- "Reserved-11",
- "Instruction Page Fault",
- "Load Page Fault",
- "Reserved-14",
- "Store/AMO Page Fault"};
+static const char *Exception_Name[] = {"Instruction Address Misaligned",
+ "Instruction Access Fault",
+ "Illegal Instruction",
+ "Breakpoint",
+ "Load Address Misaligned",
+ "Load Access Fault",
+ "Store/AMO Address Misaligned",
+ "Store/AMO Access Fault",
+ "Environment call from U-mode",
+ "Environment call from S-mode",
+ "Reserved-10",
+ "Reserved-11",
+ "Instruction Page Fault",
+ "Load Page Fault",
+ "Reserved-14",
+ "Store/AMO Page Fault"};
-static const char *Interrupt_Name[] =
- {
- "User Software Interrupt",
- "Supervisor Software Interrupt",
- "Reversed-2",
- "Reversed-3",
- "User Timer Interrupt",
- "Supervisor Timer Interrupt",
- "Reversed-6",
- "Reversed-7",
- "User External Interrupt",
- "Supervisor External Interrupt",
- "Reserved-10",
- "Reserved-11",
+static const char *Interrupt_Name[] = {
+ "User Software Interrupt",
+ "Supervisor Software Interrupt",
+ "Reversed-2",
+ "Reversed-3",
+ "User Timer Interrupt",
+ "Supervisor Timer Interrupt",
+ "Reversed-6",
+ "Reversed-7",
+ "User External Interrupt",
+ "Supervisor External Interrupt",
+ "Reserved-10",
+ "Reserved-11",
};
-extern struct rt_irq_desc irq_desc[];
-
#ifndef RT_USING_SMP
static volatile int nested = 0;
-#define ENTER_TRAP \
- nested += 1
-#define EXIT_TRAP \
- nested -= 1
+#define ENTER_TRAP nested += 1
+#define EXIT_TRAP nested -= 1
#define CHECK_NESTED_PANIC(cause, tval, epc, eframe) \
- if (nested != 1) \
- handle_nested_trap_panic(cause, tval, epc, eframe)
+ if (nested != 1) handle_nested_trap_panic(cause, tval, epc, eframe)
#endif /* RT_USING_SMP */
static const char *get_exception_msg(int id)
@@ -150,7 +154,8 @@ static const char *get_exception_msg(int id)
#ifdef RT_USING_SMART
#include "lwp.h"
-void handle_user(rt_ubase_t scause, rt_ubase_t stval, rt_ubase_t sepc, struct rt_hw_stack_frame *sp)
+void handle_user(rt_ubase_t scause, rt_ubase_t stval, rt_ubase_t sepc,
+ struct rt_hw_stack_frame *sp)
{
rt_ubase_t id = __MASKVALUE(scause, __MASK(63UL));
struct rt_lwp *lwp;
@@ -210,23 +215,20 @@ void handle_user(rt_ubase_t scause, rt_ubase_t stval, rt_ubase_t sepc, struct rt
.fault_vaddr = (void *)stval,
};
- __asm__ volatile ("csrrsi %0, sstatus, 2":"=r"(saved_stat));
+ __asm__ volatile("csrrsi %0, sstatus, 2" : "=r"(saved_stat));
if (lwp && rt_aspace_fault_try_fix(lwp->aspace, &msg))
{
- __asm__ volatile ("csrw sstatus, %0"::"r"(saved_stat));
+ __asm__ volatile("csrw sstatus, %0" ::"r"(saved_stat));
return;
}
- __asm__ volatile ("csrw sstatus, %0"::"r"(saved_stat));
+ __asm__ volatile("csrw sstatus, %0" ::"r"(saved_stat));
}
LOG_E("[FATAL ERROR] Exception %ld:%s\n", id, get_exception_msg(id));
LOG_E("scause:0x%p,stval:0x%p,sepc:0x%p\n", scause, stval, sepc);
dump_regs(sp);
rt_thread_t cur_thr = rt_thread_self();
- struct rt_hw_backtrace_frame frame = {
- .fp = sp->s0_fp,
- .pc = sepc
- };
+ struct rt_hw_backtrace_frame frame = {.fp = sp->s0_fp, .pc = sepc};
rt_kprintf("fp = %p\n", frame.fp);
lwp_backtrace_frame(cur_thr, &frame);
@@ -237,7 +239,7 @@ void handle_user(rt_ubase_t scause, rt_ubase_t stval, rt_ubase_t sepc, struct rt
}
#endif
-#ifdef ENABLE_VECTOR
+#ifdef ARCH_RISCV_VECTOR
static void vector_enable(struct rt_hw_stack_frame *sp)
{
sp->sstatus |= SSTATUS_VS_INITIAL;
@@ -246,7 +248,8 @@ static void vector_enable(struct rt_hw_stack_frame *sp)
/**
* detect V/D support, and do not distinguish V/D instruction
*/
-static int illegal_inst_recoverable(rt_ubase_t stval, struct rt_hw_stack_frame *sp)
+static int illegal_inst_recoverable(rt_ubase_t stval,
+ struct rt_hw_stack_frame *sp)
{
// first 7 bits is opcode
int opcode = stval & 0x7f;
@@ -257,12 +260,12 @@ static int illegal_inst_recoverable(rt_ubase_t stval, struct rt_hw_stack_frame *
switch (opcode)
{
- case 0x57: // V
- case 0x27: // scalar FLOAT
- case 0x07:
- case 0x73: // CSR
- flag = 1;
- break;
+ case 0x57: // V
+ case 0x27: // scalar FLOAT
+ case 0x07:
+ case 0x73: // CSR
+ flag = 1;
+ break;
}
if (flag)
@@ -274,11 +277,9 @@ static int illegal_inst_recoverable(rt_ubase_t stval, struct rt_hw_stack_frame *
}
#endif
-static void handle_nested_trap_panic(
- rt_ubase_t cause,
- rt_ubase_t tval,
- rt_ubase_t epc,
- struct rt_hw_stack_frame *eframe)
+static void handle_nested_trap_panic(rt_ubase_t cause, rt_ubase_t tval,
+ rt_ubase_t epc,
+ struct rt_hw_stack_frame *eframe)
{
LOG_E("\n-------- [SEVER ERROR] --------");
LOG_E("Nested trap detected");
@@ -288,38 +289,34 @@ static void handle_nested_trap_panic(
}
#define IN_USER_SPACE (stval >= USER_VADDR_START && stval < USER_VADDR_TOP)
-#define PAGE_FAULT (id == EP_LOAD_PAGE_FAULT || id == EP_STORE_PAGE_FAULT)
+#define PAGE_FAULT (id == EP_LOAD_PAGE_FAULT || id == EP_STORE_PAGE_FAULT)
/* Trap entry */
-void handle_trap(rt_ubase_t scause, rt_ubase_t stval, rt_ubase_t sepc, struct rt_hw_stack_frame *sp)
+void handle_trap(rt_ubase_t scause, rt_ubase_t stval, rt_ubase_t sepc,
+ struct rt_hw_stack_frame *sp)
{
ENTER_TRAP;
rt_ubase_t id = __MASKVALUE(scause, __MASK(63UL));
const char *msg;
/* supervisor external interrupt */
- if (scause == (uint64_t)(0x8000000000000005))
+ if ((SCAUSE_INTERRUPT & scause) &&
+ SCAUSE_S_EXTERNAL_INTR == (scause & 0xff))
{
rt_interrupt_enter();
- tick_isr();
+ plic_handle_irq();
rt_interrupt_leave();
}
- else if (scause == (uint64_t)(0x8000000000000009))
+ else if ((SCAUSE_INTERRUPT | SCAUSE_S_TIMER_INTR) == scause)
{
+ /* supervisor timer */
rt_interrupt_enter();
- int plic_irq = plic_claim();
- plic_complete(plic_irq);
- irq_desc[plic_irq].handler(plic_irq, irq_desc[plic_irq].param);
+ tick_isr();
rt_interrupt_leave();
}
else
{
- // trap cannot nested when handling another trap / interrupt
- CHECK_NESTED_PANIC(scause, stval, sepc, sp);
- rt_ubase_t id = __MASKVALUE(scause, __MASK(63UL));
- const char *msg;
-
- if (scause >> 63)
+ if (SCAUSE_INTERRUPT & scause)
{
if (id < sizeof(Interrupt_Name) / sizeof(const char *))
{
@@ -330,17 +327,18 @@ void handle_trap(rt_ubase_t scause, rt_ubase_t stval, rt_ubase_t sepc, struct rt
msg = "Unknown Interrupt";
}
- rt_kprintf("Unhandled Interrupt %ld:%s\n", id, msg);
+ LOG_E("Unhandled Interrupt %ld:%s\n", id, msg);
}
else
{
-#ifdef ENABLE_VECTOR
+#ifdef ARCH_RISCV_VECTOR
if (scause == 0x2)
{
- if (!(sp->sstatus & SSTATUS_VS) && illegal_inst_recoverable(stval, sp))
+ if (!(sp->sstatus & SSTATUS_VS) &&
+ illegal_inst_recoverable(stval, sp))
goto _exit;
}
-#endif /* ENABLE_VECTOR */
+#endif /* ARCH_RISCV_VECTOR */
#ifdef RT_USING_SMART
if (!(sp->sstatus & 0x100) || (PAGE_FAULT && IN_USER_SPACE))
{
@@ -351,26 +349,38 @@ void handle_trap(rt_ubase_t scause, rt_ubase_t stval, rt_ubase_t sepc, struct rt
#endif
// handle kernel exception:
- rt_kprintf("Unhandled Exception %ld:%s\n", id, get_exception_msg(id));
+ rt_kprintf("Unhandled Exception %ld:%s\n", id,
+ get_exception_msg(id));
}
+ // trap cannot nested when handling another trap / interrupt
+ CHECK_NESTED_PANIC(scause, stval, sepc, sp);
+
rt_kprintf("scause:0x%p,stval:0x%p,sepc:0x%p\n", scause, stval, sepc);
dump_regs(sp);
+
+ rt_thread_t cur_thr = rt_thread_self();
rt_kprintf("--------------Thread list--------------\n");
- rt_kprintf("current thread: %s\n", rt_thread_self()->parent.name);
+ rt_kprintf("current thread: %s\n", cur_thr->parent.name);
- extern struct rt_thread *rt_current_thread;
rt_kprintf("--------------Backtrace--------------\n");
- struct rt_hw_backtrace_frame frame = {
- .fp = sp->s0_fp,
- .pc = sepc
- };
- rt_kprintf("fp = %p", frame.fp);
- rt_backtrace_frame(rt_thread_self(), &frame);
+ struct rt_hw_backtrace_frame frame = {.fp = sp->s0_fp, .pc = sepc};
+
+#ifdef RT_USING_SMART
+ if (!(sp->sstatus & 0x100))
+ {
+ lwp_backtrace_frame(cur_thr, &frame);
+ }
+ else
+#endif
+ {
+ rt_backtrace_frame(cur_thr, &frame);
+ }
- RT_ASSERT(0);
+ while (1)
+ ;
}
_exit:
EXIT_TRAP;
- return ;
+ return;
}