From e244c196c4f1f5a867891df303476947a7769876 Mon Sep 17 00:00:00 2001 From: Shell Date: Mon, 2 Sep 2024 18:02:15 +0800 Subject: [PATCH] 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 --- libcpu/risc-v/t-head/c906/interrupt.c | 2 +- .../c906/{rt_interrupt.h => interrupt.h} | 0 libcpu/risc-v/t-head/c906/plic.c | 2 +- libcpu/risc-v/t-head/c906/plic.h | 2 +- libcpu/risc-v/t-head/c906/riscv.h | 13 +- libcpu/risc-v/t-head/c906/riscv_io.h | 154 +++++----- libcpu/risc-v/t-head/c906/trap.c | 290 ++++++++++-------- libcpu/risc-v/virt64/io.h | 4 +- libcpu/risc-v/virt64/opcode.h | 40 +++ libcpu/risc-v/virt64/plic.c | 15 + libcpu/risc-v/virt64/plic.h | 1 + libcpu/risc-v/virt64/riscv_io.h | 34 +- libcpu/risc-v/virt64/trap.c | 232 +++++++------- 13 files changed, 442 insertions(+), 347 deletions(-) rename libcpu/risc-v/t-head/c906/{rt_interrupt.h => interrupt.h} (100%) create mode 100644 libcpu/risc-v/virt64/opcode.h 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 #include -#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 similarity index 100% rename from libcpu/risc-v/t-head/c906/rt_interrupt.h rename to 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 #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 +#include #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 -#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 #include #include - -#include "board.h" -#include "tick.h" - #include -#include "mmu.h" -#include "encoding.h" -#include "stack.h" -#include "sbi.h" -#include "riscv.h" -#include "rt_interrupt.h" -#include "plic.h" +#include +#include +#include +#include +#include +#include +#include +#include #ifdef RT_USING_SMART #include -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) - { - 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 { -#ifdef RT_USING_SMART - if (!(sp->sstatus & 0x100) || (PAGE_FAULT && IN_USER_SPACE)) + if (SCAUSE_INTERRUPT & scause) { - handle_user(scause, stval, sepc, sp); - // if handle_user() return here, jump to u mode then - return ; + 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 + { +#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)); + // handle kernel exception: + 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", 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)) + { + lwp_backtrace_frame(cur_thr, &frame); + } + else +#endif + { + rt_backtrace_frame(cur_thr, &frame); + } + + 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 #include "encoding.h" +#include #include #include @@ -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 #include #include #include -#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 +#include +#include +#include +#include +#include +#include +#include #ifdef RT_USING_SMART #include -#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(); + plic_handle_irq(); + rt_interrupt_leave(); + } + else if ((SCAUSE_INTERRUPT | SCAUSE_S_TIMER_INTR) == scause) + { + /* supervisor timer */ rt_interrupt_enter(); tick_isr(); rt_interrupt_leave(); } - else if (scause == (uint64_t)(0x8000000000000009)) - { - rt_interrupt_enter(); - int plic_irq = plic_claim(); - plic_complete(plic_irq); - irq_desc[plic_irq].handler(plic_irq, irq_desc[plic_irq].param); - 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}; - RT_ASSERT(0); +#ifdef RT_USING_SMART + if (!(sp->sstatus & 0x100)) + { + lwp_backtrace_frame(cur_thr, &frame); + } + else +#endif + { + rt_backtrace_frame(cur_thr, &frame); + } + + while (1) + ; } _exit: EXIT_TRAP; - return ; + return; }