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 <smokewood@qq.com>
This commit is contained in:
parent
a00aaab2ba
commit
e244c196c4
|
@ -11,7 +11,7 @@
|
||||||
#include <rthw.h>
|
#include <rthw.h>
|
||||||
#include <rtthread.h>
|
#include <rtthread.h>
|
||||||
|
|
||||||
#include "rt_interrupt.h"
|
#include "interrupt.h"
|
||||||
#include "riscv.h"
|
#include "riscv.h"
|
||||||
#include "plic.h"
|
#include "plic.h"
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#include <rtdbg.h>
|
#include <rtdbg.h>
|
||||||
|
|
||||||
#include "plic.h"
|
#include "plic.h"
|
||||||
#include "rt_interrupt.h"
|
#include "interrupt.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "encoding.h"
|
#include "encoding.h"
|
||||||
#include "ioremap.h"
|
#include "ioremap.h"
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#ifndef __RISCV64_PLIC_H__
|
#ifndef __RISCV64_PLIC_H__
|
||||||
#define __RISCV64_PLIC_H__
|
#define __RISCV64_PLIC_H__
|
||||||
|
|
||||||
#include <rt_interrupt.h>
|
#include <interrupt.h>
|
||||||
|
|
||||||
#ifndef C906_PLIC_PHY_ADDR
|
#ifndef C906_PLIC_PHY_ADDR
|
||||||
#define C906_PLIC_PHY_ADDR (0x10000000)
|
#define C906_PLIC_PHY_ADDR (0x10000000)
|
||||||
|
|
|
@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*
|
*
|
||||||
* Change Logs:
|
* Change Logs:
|
||||||
* Date Author Notes
|
* Date Author Notes
|
||||||
* 2021-01-30 lizhirui first version
|
* 2021-01-30 lizhirui first version
|
||||||
|
* 2024-08-28 RT-Thread Fit into rv64ilp32 ABI
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __RISCV_H__
|
#ifndef __RISCV_H__
|
||||||
|
@ -13,13 +14,15 @@
|
||||||
|
|
||||||
#include <encoding.h>
|
#include <encoding.h>
|
||||||
|
|
||||||
#define __SIZE(bit) (1UL << (bit))
|
/* using unsigned long long for the case of rv64ilp32 */
|
||||||
#define __MASK(bit) (__SIZE(bit) - 1UL)
|
#define __SIZE(bit) (1ULL << (bit))
|
||||||
|
#define __MASK(bit) (__SIZE(bit) - 1ULL)
|
||||||
|
|
||||||
#define __UMASK(bit) (~(__MASK(bit)))
|
#define __UMASK(bit) (~(__MASK(bit)))
|
||||||
#define __MASKVALUE(value,maskvalue) ((value) & (maskvalue))
|
#define __MASKVALUE(value,maskvalue) ((value) & (maskvalue))
|
||||||
#define __UMASKVALUE(value,maskvalue) ((value) & (~(maskvalue)))
|
#define __UMASKVALUE(value,maskvalue) ((value) & (~(maskvalue)))
|
||||||
#define __CHECKUPBOUND(value,bit_count) (!(((rt_size_t)value) & (~__MASK(bit_count))))
|
#define __CHECKUPBOUND(value,bit_count) (!(((rt_ubase_t)value) & (~__MASK(bit_count))))
|
||||||
#define __CHECKALIGN(value,start_bit) (!(((rt_size_t)value) & (__MASK(start_bit))))
|
#define __CHECKALIGN(value,start_bit) (!(((rt_ubase_t)value) & (__MASK(start_bit))))
|
||||||
|
|
||||||
#define __PARTBIT(value,start_bit,length) (((value) >> (start_bit)) & __MASK(length))
|
#define __PARTBIT(value,start_bit,length) (((value) >> (start_bit)) & __MASK(length))
|
||||||
|
|
||||||
|
|
|
@ -10,100 +10,106 @@
|
||||||
#ifndef __RISCV_IO_H__
|
#ifndef __RISCV_IO_H__
|
||||||
#define __RISCV_IO_H__
|
#define __RISCV_IO_H__
|
||||||
|
|
||||||
static inline void __raw_writeb(rt_uint8_t val, volatile void *addr)
|
static inline uint32_t __raw_hartid(void)
|
||||||
{
|
{
|
||||||
asm volatile("sb %0, 0(%1)" : : "r"(val), "r"(addr));
|
extern int boot_hartid;
|
||||||
}
|
return boot_hartid;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void __raw_writew(rt_uint16_t val, volatile void *addr)
|
static inline void __raw_writeb(rt_uint8_t val, volatile void *addr)
|
||||||
{
|
{
|
||||||
asm volatile("sh %0, 0(%1)" : : "r"(val), "r"(addr));
|
asm volatile("sb %0, 0(%1)" : : "r"(val), "r"(addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void __raw_writel(rt_uint32_t val, volatile void *addr)
|
static inline void __raw_writew(rt_uint16_t val, volatile void *addr)
|
||||||
{
|
{
|
||||||
asm volatile("sw %0, 0(%1)" : : "r"(val), "r"(addr));
|
asm volatile("sh %0, 0(%1)" : : "r"(val), "r"(addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if __riscv_xlen != 32
|
static inline void __raw_writel(rt_uint32_t val, volatile void *addr)
|
||||||
static inline void __raw_writeq(rt_uint64_t val, volatile void *addr)
|
{
|
||||||
{
|
asm volatile("sw %0, 0(%1)" : : "r"(val), "r"(addr));
|
||||||
asm volatile("sd %0, 0(%1)" : : "r"(val), "r"(addr));
|
}
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline rt_uint8_t __raw_readb(const volatile void *addr)
|
#if __riscv_xlen != 32
|
||||||
{
|
static inline void __raw_writeq(rt_uint64_t val, volatile void *addr)
|
||||||
rt_uint8_t val;
|
{
|
||||||
|
asm volatile("sd %0, 0(%1)" : : "r"(val), "r"(addr));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
asm volatile("lb %0, 0(%1)" : "=r"(val) : "r"(addr));
|
static inline rt_uint8_t __raw_readb(const volatile void *addr)
|
||||||
return val;
|
{
|
||||||
}
|
rt_uint8_t val;
|
||||||
|
|
||||||
static inline rt_uint16_t __raw_readw(const volatile void *addr)
|
asm volatile("lb %0, 0(%1)" : "=r"(val) : "r"(addr));
|
||||||
{
|
return val;
|
||||||
rt_uint16_t val;
|
}
|
||||||
|
|
||||||
asm volatile("lh %0, 0(%1)" : "=r"(val) : "r"(addr));
|
static inline rt_uint16_t __raw_readw(const volatile void *addr)
|
||||||
return val;
|
{
|
||||||
}
|
rt_uint16_t val;
|
||||||
|
|
||||||
static inline rt_uint32_t __raw_readl(const volatile void *addr)
|
asm volatile("lh %0, 0(%1)" : "=r"(val) : "r"(addr));
|
||||||
{
|
return val;
|
||||||
rt_uint32_t val;
|
}
|
||||||
|
|
||||||
asm volatile("lw %0, 0(%1)" : "=r"(val) : "r"(addr));
|
static inline rt_uint32_t __raw_readl(const volatile void *addr)
|
||||||
return val;
|
{
|
||||||
}
|
rt_uint32_t val;
|
||||||
|
|
||||||
#if __riscv_xlen != 32
|
asm volatile("lw %0, 0(%1)" : "=r"(val) : "r"(addr));
|
||||||
static inline rt_uint64_t __raw_readq(const volatile void *addr)
|
return val;
|
||||||
{
|
}
|
||||||
rt_uint64_t val;
|
|
||||||
|
|
||||||
asm volatile("ld %0, 0(%1)" : "=r"(val) : "r"(addr));
|
#if __riscv_xlen != 32
|
||||||
return val;
|
static inline rt_uint64_t __raw_readq(const volatile void *addr)
|
||||||
}
|
{
|
||||||
#endif
|
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)
|
/* clang-format off */
|
||||||
#define __io_rar() do {} while (0)
|
|
||||||
#define __io_rbw() do {} while (0)
|
|
||||||
#define __io_raw() do {} while (0)
|
|
||||||
|
|
||||||
#define readb_relaxed(c) ({ rt_uint8_t __v; __io_rbr(); __v = __raw_readb(c); __io_rar(); __v; })
|
#define __io_rbr() do {} while (0)
|
||||||
#define readw_relaxed(c) ({ rt_uint16_t __v; __io_rbr(); __v = __raw_readw(c); __io_rar(); __v; })
|
#define __io_rar() do {} while (0)
|
||||||
#define readl_relaxed(c) ({ rt_uint32_t __v; __io_rbr(); __v = __raw_readl(c); __io_rar(); __v; })
|
#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 readb_relaxed(c) ({ rt_uint8_t __v; __io_rbr(); __v = __raw_readb(c); __io_rar(); __v; })
|
||||||
#define writew_relaxed(v,c) ({ __io_rbw(); __raw_writew((v),(c)); __io_raw(); })
|
#define readw_relaxed(c) ({ rt_uint16_t __v; __io_rbr(); __v = __raw_readw(c); __io_rar(); __v; })
|
||||||
#define writel_relaxed(v,c) ({ __io_rbw(); __raw_writel((v),(c)); __io_raw(); })
|
#define readl_relaxed(c) ({ rt_uint32_t __v; __io_rbr(); __v = __raw_readl(c); __io_rar(); __v; })
|
||||||
|
|
||||||
#if __riscv_xlen != 32
|
#define writeb_relaxed(v,c) ({ __io_rbw(); __raw_writeb((v),(c)); __io_raw(); })
|
||||||
#define readq_relaxed(c) ({ rt_uint64_t __v; __io_rbr(); __v = __raw_readq(c); __io_rar(); __v; })
|
#define writew_relaxed(v,c) ({ __io_rbw(); __raw_writew((v),(c)); __io_raw(); })
|
||||||
#define writeq_relaxed(v,c) ({ __io_rbw(); __raw_writeq((v),(c)); __io_raw(); })
|
#define writel_relaxed(v,c) ({ __io_rbw(); __raw_writel((v),(c)); __io_raw(); })
|
||||||
#endif
|
|
||||||
|
|
||||||
#define __io_br() do {} while (0)
|
#if __riscv_xlen != 32
|
||||||
#define __io_ar() __asm__ __volatile__ ("fence i,r" : : : "memory");
|
#define readq_relaxed(c) ({ rt_uint64_t __v; __io_rbr(); __v = __raw_readq(c); __io_rar(); __v; })
|
||||||
#define __io_bw() __asm__ __volatile__ ("fence w,o" : : : "memory");
|
#define writeq_relaxed(v,c) ({ __io_rbw(); __raw_writeq((v),(c)); __io_raw(); })
|
||||||
#define __io_aw() do {} while (0)
|
#endif
|
||||||
|
|
||||||
#define readb(c) ({ rt_uint8_t __v; __io_br(); __v = __raw_readb(c); __io_ar(); __v; })
|
#define __io_br() do {} while (0)
|
||||||
#define readw(c) ({ rt_uint16_t __v; __io_br(); __v = __raw_readw(c); __io_ar(); __v; })
|
#define __io_ar() __asm__ __volatile__ ("fence i,r" : : : "memory");
|
||||||
#define readl(c) ({ rt_uint32_t __v; __io_br(); __v = __raw_readl(c); __io_ar(); __v; })
|
#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 readb(c) ({ rt_uint8_t __v; __io_br(); __v = __raw_readb(c); __io_ar(); __v; })
|
||||||
#define writew(v,c) ({ __io_bw(); __raw_writew((v),(c)); __io_aw(); })
|
#define readw(c) ({ rt_uint16_t __v; __io_br(); __v = __raw_readw(c); __io_ar(); __v; })
|
||||||
#define writel(v,c) ({ __io_bw(); __raw_writel((v),(c)); __io_aw(); })
|
#define readl(c) ({ rt_uint32_t __v; __io_br(); __v = __raw_readl(c); __io_ar(); __v; })
|
||||||
|
|
||||||
#if __riscv_xlen != 32
|
#define writeb(v,c) ({ __io_bw(); __raw_writeb((v),(c)); __io_aw(); })
|
||||||
#define readq(c) ({ rt_uint64_t __v; __io_br(); __v = __raw_readq(c); __io_ar(); __v; })
|
#define writew(v,c) ({ __io_bw(); __raw_writew((v),(c)); __io_aw(); })
|
||||||
#define writeq(v,c) ({ __io_bw(); __raw_writeq((v),(c)); __io_aw(); })
|
#define writel(v,c) ({ __io_bw(); __raw_writel((v),(c)); __io_aw(); })
|
||||||
#endif
|
|
||||||
|
#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
|
#endif
|
||||||
|
|
|
@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*
|
*
|
||||||
* Change Logs:
|
* Change Logs:
|
||||||
* Date Author Notes
|
* Date Author Notes
|
||||||
* 2021/1/30 lizirui first version
|
* 2022-12-08 RT-Thread first version
|
||||||
* 2021/10/20 JasonHu move to trap.c
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <rthw.h>
|
#include <rthw.h>
|
||||||
#include <rtthread.h>
|
#include <rtthread.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
#include "board.h"
|
|
||||||
#include "tick.h"
|
|
||||||
|
|
||||||
#include <mm_fault.h>
|
#include <mm_fault.h>
|
||||||
#include "mmu.h"
|
#include <mmu.h>
|
||||||
#include "encoding.h"
|
#include <encoding.h>
|
||||||
#include "stack.h"
|
#include <stack.h>
|
||||||
#include "sbi.h"
|
#include <sbi.h>
|
||||||
#include "riscv.h"
|
#include <riscv.h>
|
||||||
#include "rt_interrupt.h"
|
#include <interrupt.h>
|
||||||
#include "plic.h"
|
#include <plic.h>
|
||||||
|
#include <tick.h>
|
||||||
|
|
||||||
#ifdef RT_USING_SMART
|
#ifdef RT_USING_SMART
|
||||||
#include <lwp_arch.h>
|
#include <lwp_arch.h>
|
||||||
void rt_hw_backtrace(rt_uint32_t *ffp, rt_ubase_t sepc);
|
|
||||||
#else
|
|
||||||
#define rt_hw_backtrace(...) (0)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DBG_TAG "libcpu.trap"
|
#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("--------------Dump Registers-----------------\n");
|
||||||
|
|
||||||
rt_kprintf("Function 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("\tgp(x3) = 0x%p\ttp(x4) = 0x%p\n", regs->gp, regs->tp);
|
||||||
rt_kprintf("Temporary Registers:\n");
|
rt_kprintf("Temporary Registers:\n");
|
||||||
rt_kprintf("\tt0(x5) = 0x%p\tt1(x6) = 0x%p\n", regs->t0, regs->t1);
|
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("\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("\ta6(x16) = 0x%p\ta7(x17) = 0x%p\n", regs->a6, regs->a7);
|
||||||
rt_kprintf("sstatus = 0x%p\n", regs->sstatus);
|
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_SIE)
|
||||||
rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SPIE) ? "Last Time Supervisor Interrupt Enabled" : "Last Time Supervisor Interrupt Disabled");
|
? "Supervisor Interrupt Enabled"
|
||||||
rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SPP) ? "Last Privilege is Supervisor Mode" : "Last Privilege is User Mode");
|
: "Supervisor Interrupt Disabled");
|
||||||
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 & SSTATUS_SPIE)
|
||||||
rt_kprintf("\t%s\n", (regs->sstatus & (1 << 19)) ? "Permit to Read Executable-only Page" : "Not Permit to Read Executable-only Page");
|
? "Last Time Supervisor Interrupt Enabled"
|
||||||
rt_size_t satp_v = read_csr(satp);
|
: "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("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 Page Table(Physical) = 0x%p\n",
|
||||||
rt_kprintf("\tCurrent ASID = 0x%p\n", __MASKVALUE(satp_v >> 44, __MASK(16)) << PAGE_OFFSET_BIT);
|
__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";
|
const char *mode_str = "Unknown Address Translation/Protection Mode";
|
||||||
|
|
||||||
switch (__MASKVALUE(satp_v >> 60, __MASK(4)))
|
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");
|
rt_kprintf("-----------------Dump OK---------------------\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *Exception_Name[] =
|
static const char *Exception_Name[] = {"Instruction Address Misaligned",
|
||||||
{
|
"Instruction Access Fault",
|
||||||
"Instruction Address Misaligned",
|
"Illegal Instruction",
|
||||||
"Instruction Access Fault",
|
"Breakpoint",
|
||||||
"Illegal Instruction",
|
"Load Address Misaligned",
|
||||||
"Breakpoint",
|
"Load Access Fault",
|
||||||
"Load Address Misaligned",
|
"Store/AMO Address Misaligned",
|
||||||
"Load Access Fault",
|
"Store/AMO Access Fault",
|
||||||
"Store/AMO Address Misaligned",
|
"Environment call from U-mode",
|
||||||
"Store/AMO Access Fault",
|
"Environment call from S-mode",
|
||||||
"Environment call from U-mode",
|
"Reserved-10",
|
||||||
"Environment call from S-mode",
|
"Reserved-11",
|
||||||
"Reserved-10",
|
"Instruction Page Fault",
|
||||||
"Reserved-11",
|
"Load Page Fault",
|
||||||
"Instruction Page Fault",
|
"Reserved-14",
|
||||||
"Load Page Fault",
|
"Store/AMO Page Fault"};
|
||||||
"Reserved-14",
|
|
||||||
"Store/AMO Page Fault"};
|
|
||||||
|
|
||||||
static const char *Interrupt_Name[] =
|
static const char *Interrupt_Name[] = {
|
||||||
{
|
"User Software Interrupt",
|
||||||
"User Software Interrupt",
|
"Supervisor Software Interrupt",
|
||||||
"Supervisor Software Interrupt",
|
"Reversed-2",
|
||||||
"Reversed-2",
|
"Reversed-3",
|
||||||
"Reversed-3",
|
"User Timer Interrupt",
|
||||||
"User Timer Interrupt",
|
"Supervisor Timer Interrupt",
|
||||||
"Supervisor Timer Interrupt",
|
"Reversed-6",
|
||||||
"Reversed-6",
|
"Reversed-7",
|
||||||
"Reversed-7",
|
"User External Interrupt",
|
||||||
"User External Interrupt",
|
"Supervisor External Interrupt",
|
||||||
"Supervisor External Interrupt",
|
"Reserved-10",
|
||||||
"Reserved-10",
|
"Reserved-11",
|
||||||
"Reserved-11",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef RT_USING_SMP
|
#ifndef RT_USING_SMP
|
||||||
static volatile int nested = 0;
|
static volatile int nested = 0;
|
||||||
#define ENTER_TRAP \
|
#define ENTER_TRAP nested += 1
|
||||||
nested += 1
|
#define EXIT_TRAP nested -= 1
|
||||||
#define EXIT_TRAP \
|
|
||||||
nested -= 1
|
|
||||||
#define CHECK_NESTED_PANIC(cause, tval, epc, eframe) \
|
#define CHECK_NESTED_PANIC(cause, tval, epc, eframe) \
|
||||||
if (nested != 1) \
|
if (nested != 1) handle_nested_trap_panic(cause, tval, epc, eframe)
|
||||||
handle_nested_trap_panic(cause, tval, epc, eframe)
|
|
||||||
#endif /* RT_USING_SMP */
|
#endif /* RT_USING_SMP */
|
||||||
|
|
||||||
static const char *get_exception_msg(int id)
|
static const char *get_exception_msg(int id)
|
||||||
|
@ -153,9 +153,11 @@ static const char *get_exception_msg(int id)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef RT_USING_SMART
|
#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;
|
struct rt_lwp *lwp;
|
||||||
|
|
||||||
/* user page fault */
|
/* 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:
|
case EP_LOAD_PAGE_FAULT:
|
||||||
fault_op = MM_FAULT_OP_READ;
|
fault_op = MM_FAULT_OP_READ;
|
||||||
fault_type = MM_FAULT_TYPE_PAGE_FAULT;
|
fault_type = MM_FAULT_TYPE_GENERIC_MMU;
|
||||||
break;
|
break;
|
||||||
case EP_LOAD_ACCESS_FAULT:
|
case EP_LOAD_ACCESS_FAULT:
|
||||||
fault_op = MM_FAULT_OP_READ;
|
fault_op = MM_FAULT_OP_READ;
|
||||||
fault_type = MM_FAULT_TYPE_GENERIC;
|
fault_type = MM_FAULT_TYPE_BUS_ERROR;
|
||||||
break;
|
break;
|
||||||
case EP_LOAD_ADDRESS_MISALIGNED:
|
case EP_LOAD_ADDRESS_MISALIGNED:
|
||||||
fault_op = MM_FAULT_OP_READ;
|
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;
|
break;
|
||||||
case EP_STORE_PAGE_FAULT:
|
case EP_STORE_PAGE_FAULT:
|
||||||
fault_op = MM_FAULT_OP_WRITE;
|
fault_op = MM_FAULT_OP_WRITE;
|
||||||
fault_type = MM_FAULT_TYPE_PAGE_FAULT;
|
fault_type = MM_FAULT_TYPE_GENERIC_MMU;
|
||||||
break;
|
break;
|
||||||
case EP_STORE_ACCESS_FAULT:
|
case EP_STORE_ACCESS_FAULT:
|
||||||
fault_op = MM_FAULT_OP_WRITE;
|
fault_op = MM_FAULT_OP_WRITE;
|
||||||
fault_type = MM_FAULT_TYPE_GENERIC;
|
fault_type = MM_FAULT_TYPE_BUS_ERROR;
|
||||||
break;
|
break;
|
||||||
case EP_STORE_ADDRESS_MISALIGNED:
|
case EP_STORE_ADDRESS_MISALIGNED:
|
||||||
fault_op = MM_FAULT_OP_WRITE;
|
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;
|
break;
|
||||||
case EP_INSTRUCTION_PAGE_FAULT:
|
case EP_INSTRUCTION_PAGE_FAULT:
|
||||||
fault_op = MM_FAULT_OP_EXECUTE;
|
fault_op = MM_FAULT_OP_EXECUTE;
|
||||||
fault_type = MM_FAULT_TYPE_PAGE_FAULT;
|
fault_type = MM_FAULT_TYPE_GENERIC_MMU;
|
||||||
break;
|
break;
|
||||||
case EP_INSTRUCTION_ACCESS_FAULT:
|
case EP_INSTRUCTION_ACCESS_FAULT:
|
||||||
fault_op = MM_FAULT_OP_EXECUTE;
|
fault_op = MM_FAULT_OP_EXECUTE;
|
||||||
fault_type = MM_FAULT_TYPE_GENERIC;
|
fault_type = MM_FAULT_TYPE_BUS_ERROR;
|
||||||
break;
|
break;
|
||||||
case EP_INSTRUCTION_ADDRESS_MISALIGNED:
|
case EP_INSTRUCTION_ADDRESS_MISALIGNED:
|
||||||
fault_op = MM_FAULT_OP_EXECUTE;
|
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,
|
.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))
|
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;
|
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("[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);
|
LOG_E("scause:0x%p,stval:0x%p,sepc:0x%p\n", scause, stval, sepc);
|
||||||
dump_regs(sp);
|
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;
|
EXIT_TRAP;
|
||||||
sys_exit_group(-1);
|
sys_exit_group(-1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_VECTOR
|
#ifdef ARCH_RISCV_VECTOR
|
||||||
static void vector_enable(struct rt_hw_stack_frame *sp)
|
static void vector_enable(struct rt_hw_stack_frame *sp)
|
||||||
{
|
{
|
||||||
sp->sstatus |= SSTATUS_VS_INITIAL;
|
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
|
* 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
|
// first 7 bits is opcode
|
||||||
int opcode = stval & 0x7f;
|
int opcode = stval & 0x7f;
|
||||||
|
@ -254,12 +260,12 @@ static int illegal_inst_recoverable(rt_ubase_t stval, struct rt_hw_stack_frame *
|
||||||
|
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
{
|
{
|
||||||
case 0x57: // V
|
case 0x57: // V
|
||||||
case 0x27: // scalar FLOAT
|
case 0x27: // scalar FLOAT
|
||||||
case 0x07:
|
case 0x07:
|
||||||
case 0x73: // CSR
|
case 0x73: // CSR
|
||||||
flag = 1;
|
flag = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flag)
|
if (flag)
|
||||||
|
@ -271,11 +277,9 @@ static int illegal_inst_recoverable(rt_ubase_t stval, struct rt_hw_stack_frame *
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void handle_nested_trap_panic(
|
static void handle_nested_trap_panic(rt_ubase_t cause, rt_ubase_t tval,
|
||||||
rt_size_t cause,
|
rt_ubase_t epc,
|
||||||
rt_size_t tval,
|
struct rt_hw_stack_frame *eframe)
|
||||||
rt_size_t epc,
|
|
||||||
struct rt_hw_stack_frame *eframe)
|
|
||||||
{
|
{
|
||||||
LOG_E("\n-------- [SEVER ERROR] --------");
|
LOG_E("\n-------- [SEVER ERROR] --------");
|
||||||
LOG_E("Nested trap detected");
|
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 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 */
|
/* 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;
|
const char *msg;
|
||||||
|
|
||||||
/* supervisor external interrupt */
|
/* 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();
|
rt_interrupt_enter();
|
||||||
plic_handle_irq();
|
plic_handle_irq();
|
||||||
rt_interrupt_leave();
|
rt_interrupt_leave();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
else if ((SCAUSE_INTERRUPT | SCAUSE_S_TIMER_INTR) == scause)
|
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();
|
rt_interrupt_enter();
|
||||||
tick_isr();
|
tick_isr();
|
||||||
rt_interrupt_leave();
|
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
|
else
|
||||||
{
|
{
|
||||||
#ifdef RT_USING_SMART
|
if (SCAUSE_INTERRUPT & scause)
|
||||||
if (!(sp->sstatus & 0x100) || (PAGE_FAULT && IN_USER_SPACE))
|
|
||||||
{
|
{
|
||||||
handle_user(scause, stval, sepc, sp);
|
if (id < sizeof(Interrupt_Name) / sizeof(const char *))
|
||||||
// if handle_user() return here, jump to u mode then
|
{
|
||||||
return ;
|
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
|
#endif
|
||||||
|
|
||||||
// handle kernel exception:
|
// 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", 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)
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
_exit:
|
||||||
rt_kprintf("scause:0x%p,stval:0x%p,sepc:0x%p\n", scause, stval, sepc);
|
EXIT_TRAP;
|
||||||
dump_regs(sp);
|
return;
|
||||||
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)
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,13 +40,13 @@ static inline uint32_t readl(const volatile void *addr)
|
||||||
static inline void write_reg(
|
static inline void write_reg(
|
||||||
uint32_t val, volatile void *addr, unsigned offset)
|
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(
|
static inline uint32_t read_reg(
|
||||||
const volatile void *addr, unsigned offset)
|
const volatile void *addr, unsigned offset)
|
||||||
{
|
{
|
||||||
return readl(addr + offset);
|
return readl((void *)((rt_size_t)addr + offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // ARCH_IO_H
|
#endif // ARCH_IO_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__ */
|
|
@ -14,6 +14,7 @@
|
||||||
#include "plic.h"
|
#include "plic.h"
|
||||||
#include <riscv_io.h>
|
#include <riscv_io.h>
|
||||||
#include "encoding.h"
|
#include "encoding.h"
|
||||||
|
#include <interrupt.h>
|
||||||
|
|
||||||
#include <riscv.h>
|
#include <riscv.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -139,3 +140,17 @@ void plic_init()
|
||||||
// in a single core system, only current context was set
|
// in a single core system, only current context was set
|
||||||
_set_sie(__raw_hartid());
|
_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);
|
||||||
|
}
|
||||||
|
|
|
@ -72,5 +72,6 @@ void plic_complete(int irq);
|
||||||
void plic_set_thresh(rt_uint32_t val);
|
void plic_set_thresh(rt_uint32_t val);
|
||||||
void plic_set_ie(rt_uint32_t word_index,rt_uint32_t val);
|
void plic_set_ie(rt_uint32_t word_index,rt_uint32_t val);
|
||||||
void plic_init();
|
void plic_init();
|
||||||
|
void plic_handle_irq(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#ifndef __RISCV_IO_H__
|
#ifndef __RISCV_IO_H__
|
||||||
#define __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;
|
extern int boot_hartid;
|
||||||
return 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)
|
static inline void __raw_writeb(rt_uint8_t val, volatile void *addr)
|
||||||
{
|
{
|
||||||
asm volatile("sb %0, 0(%1)"
|
asm volatile("sb %0, 0(%1)" : : "r"(val), "r"(addr));
|
||||||
:
|
|
||||||
: "r"(val), "r"(addr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void __raw_writew(rt_uint16_t val, volatile void *addr)
|
static inline void __raw_writew(rt_uint16_t val, volatile void *addr)
|
||||||
{
|
{
|
||||||
asm volatile("sh %0, 0(%1)"
|
asm volatile("sh %0, 0(%1)" : : "r"(val), "r"(addr));
|
||||||
:
|
|
||||||
: "r"(val), "r"(addr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void __raw_writel(rt_uint32_t val, volatile void *addr)
|
static inline void __raw_writel(rt_uint32_t val, volatile void *addr)
|
||||||
{
|
{
|
||||||
asm volatile("sw %0, 0(%1)"
|
asm volatile("sw %0, 0(%1)" : : "r"(val), "r"(addr));
|
||||||
:
|
|
||||||
: "r"(val), "r"(addr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if __riscv_xlen != 32
|
#if __riscv_xlen != 32
|
||||||
static inline void __raw_writeq(rt_uint64_t val, volatile void *addr)
|
static inline void __raw_writeq(rt_uint64_t val, volatile void *addr)
|
||||||
{
|
{
|
||||||
asm volatile("sd %0, 0(%1)"
|
asm volatile("sd %0, 0(%1)" : : "r"(val), "r"(addr));
|
||||||
:
|
|
||||||
: "r"(val), "r"(addr));
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -50,9 +42,7 @@ static inline rt_uint8_t __raw_readb(const volatile void *addr)
|
||||||
{
|
{
|
||||||
rt_uint8_t val;
|
rt_uint8_t val;
|
||||||
|
|
||||||
asm volatile("lb %0, 0(%1)"
|
asm volatile("lb %0, 0(%1)" : "=r"(val) : "r"(addr));
|
||||||
: "=r"(val)
|
|
||||||
: "r"(addr));
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,9 +50,7 @@ static inline rt_uint16_t __raw_readw(const volatile void *addr)
|
||||||
{
|
{
|
||||||
rt_uint16_t val;
|
rt_uint16_t val;
|
||||||
|
|
||||||
asm volatile("lh %0, 0(%1)"
|
asm volatile("lh %0, 0(%1)" : "=r"(val) : "r"(addr));
|
||||||
: "=r"(val)
|
|
||||||
: "r"(addr));
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,9 +58,7 @@ static inline rt_uint32_t __raw_readl(const volatile void *addr)
|
||||||
{
|
{
|
||||||
rt_uint32_t val;
|
rt_uint32_t val;
|
||||||
|
|
||||||
asm volatile("lw %0, 0(%1)"
|
asm volatile("lw %0, 0(%1)" : "=r"(val) : "r"(addr));
|
||||||
: "=r"(val)
|
|
||||||
: "r"(addr));
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,9 +67,7 @@ static inline rt_uint64_t __raw_readq(const volatile void *addr)
|
||||||
{
|
{
|
||||||
rt_uint64_t val;
|
rt_uint64_t val;
|
||||||
|
|
||||||
asm volatile("ld %0, 0(%1)"
|
asm volatile("ld %0, 0(%1)" : "=r"(val) : "r"(addr));
|
||||||
: "=r"(val)
|
|
||||||
: "r"(addr));
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -7,24 +7,23 @@
|
||||||
* Date Author Notes
|
* Date Author Notes
|
||||||
* 2022-12-08 RT-Thread first version
|
* 2022-12-08 RT-Thread first version
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <rthw.h>
|
#include <rthw.h>
|
||||||
#include <rtthread.h>
|
#include <rtthread.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <mm_fault.h>
|
#include <mm_fault.h>
|
||||||
#include "mmu.h"
|
#include <mmu.h>
|
||||||
#include "encoding.h"
|
#include <encoding.h>
|
||||||
#include "stack.h"
|
#include <stack.h>
|
||||||
#include "sbi.h"
|
#include <sbi.h>
|
||||||
#include "riscv.h"
|
#include <riscv.h>
|
||||||
#include "interrupt.h"
|
#include <interrupt.h>
|
||||||
#include "plic.h"
|
#include <plic.h>
|
||||||
#include "tick.h"
|
#include <tick.h>
|
||||||
|
|
||||||
#ifdef RT_USING_SMART
|
#ifdef RT_USING_SMART
|
||||||
#include <lwp_arch.h>
|
#include <lwp_arch.h>
|
||||||
#else
|
|
||||||
#define rt_hw_backtrace(...) (0)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DBG_TAG "libcpu.trap"
|
#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("--------------Dump Registers-----------------\n");
|
||||||
|
|
||||||
rt_kprintf("Function 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("\tgp(x3) = 0x%p\ttp(x4) = 0x%p\n", regs->gp, regs->tp);
|
||||||
rt_kprintf("Temporary Registers:\n");
|
rt_kprintf("Temporary Registers:\n");
|
||||||
rt_kprintf("\tt0(x5) = 0x%p\tt1(x6) = 0x%p\n", regs->t0, regs->t1);
|
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("\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("\ta6(x16) = 0x%p\ta7(x17) = 0x%p\n", regs->a6, regs->a7);
|
||||||
rt_kprintf("sstatus = 0x%p\n", regs->sstatus);
|
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_SIE)
|
||||||
rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SPIE) ? "Last Time Supervisor Interrupt Enabled" : "Last Time Supervisor Interrupt Disabled");
|
? "Supervisor Interrupt Enabled"
|
||||||
rt_kprintf("\t%s\n", (regs->sstatus & SSTATUS_SPP) ? "Last Privilege is Supervisor Mode" : "Last Privilege is User Mode");
|
: "Supervisor Interrupt Disabled");
|
||||||
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 & SSTATUS_SPIE)
|
||||||
rt_kprintf("\t%s\n", (regs->sstatus & (1 << 19)) ? "Permit to Read Executable-only Page" : "Not Permit to Read Executable-only Page");
|
? "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_ubase_t satp_v = read_csr(satp);
|
||||||
rt_kprintf("satp = 0x%p\n", satp_v);
|
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 Page Table(Physical) = 0x%p\n",
|
||||||
rt_kprintf("\tCurrent ASID = 0x%p\n", __MASKVALUE(satp_v >> 44, __MASK(16)) << PAGE_OFFSET_BIT);
|
__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";
|
const char *mode_str = "Unknown Address Translation/Protection Mode";
|
||||||
|
|
||||||
switch (__MASKVALUE(satp_v >> 60, __MASK(4)))
|
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");
|
rt_kprintf("-----------------Dump OK---------------------\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *Exception_Name[] =
|
static const char *Exception_Name[] = {"Instruction Address Misaligned",
|
||||||
{
|
"Instruction Access Fault",
|
||||||
"Instruction Address Misaligned",
|
"Illegal Instruction",
|
||||||
"Instruction Access Fault",
|
"Breakpoint",
|
||||||
"Illegal Instruction",
|
"Load Address Misaligned",
|
||||||
"Breakpoint",
|
"Load Access Fault",
|
||||||
"Load Address Misaligned",
|
"Store/AMO Address Misaligned",
|
||||||
"Load Access Fault",
|
"Store/AMO Access Fault",
|
||||||
"Store/AMO Address Misaligned",
|
"Environment call from U-mode",
|
||||||
"Store/AMO Access Fault",
|
"Environment call from S-mode",
|
||||||
"Environment call from U-mode",
|
"Reserved-10",
|
||||||
"Environment call from S-mode",
|
"Reserved-11",
|
||||||
"Reserved-10",
|
"Instruction Page Fault",
|
||||||
"Reserved-11",
|
"Load Page Fault",
|
||||||
"Instruction Page Fault",
|
"Reserved-14",
|
||||||
"Load Page Fault",
|
"Store/AMO Page Fault"};
|
||||||
"Reserved-14",
|
|
||||||
"Store/AMO Page Fault"};
|
|
||||||
|
|
||||||
static const char *Interrupt_Name[] =
|
static const char *Interrupt_Name[] = {
|
||||||
{
|
"User Software Interrupt",
|
||||||
"User Software Interrupt",
|
"Supervisor Software Interrupt",
|
||||||
"Supervisor Software Interrupt",
|
"Reversed-2",
|
||||||
"Reversed-2",
|
"Reversed-3",
|
||||||
"Reversed-3",
|
"User Timer Interrupt",
|
||||||
"User Timer Interrupt",
|
"Supervisor Timer Interrupt",
|
||||||
"Supervisor Timer Interrupt",
|
"Reversed-6",
|
||||||
"Reversed-6",
|
"Reversed-7",
|
||||||
"Reversed-7",
|
"User External Interrupt",
|
||||||
"User External Interrupt",
|
"Supervisor External Interrupt",
|
||||||
"Supervisor External Interrupt",
|
"Reserved-10",
|
||||||
"Reserved-10",
|
"Reserved-11",
|
||||||
"Reserved-11",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct rt_irq_desc irq_desc[];
|
|
||||||
|
|
||||||
#ifndef RT_USING_SMP
|
#ifndef RT_USING_SMP
|
||||||
static volatile int nested = 0;
|
static volatile int nested = 0;
|
||||||
#define ENTER_TRAP \
|
#define ENTER_TRAP nested += 1
|
||||||
nested += 1
|
#define EXIT_TRAP nested -= 1
|
||||||
#define EXIT_TRAP \
|
|
||||||
nested -= 1
|
|
||||||
#define CHECK_NESTED_PANIC(cause, tval, epc, eframe) \
|
#define CHECK_NESTED_PANIC(cause, tval, epc, eframe) \
|
||||||
if (nested != 1) \
|
if (nested != 1) handle_nested_trap_panic(cause, tval, epc, eframe)
|
||||||
handle_nested_trap_panic(cause, tval, epc, eframe)
|
|
||||||
#endif /* RT_USING_SMP */
|
#endif /* RT_USING_SMP */
|
||||||
|
|
||||||
static const char *get_exception_msg(int id)
|
static const char *get_exception_msg(int id)
|
||||||
|
@ -150,7 +154,8 @@ static const char *get_exception_msg(int id)
|
||||||
|
|
||||||
#ifdef RT_USING_SMART
|
#ifdef RT_USING_SMART
|
||||||
#include "lwp.h"
|
#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));
|
rt_ubase_t id = __MASKVALUE(scause, __MASK(63UL));
|
||||||
struct rt_lwp *lwp;
|
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,
|
.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))
|
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;
|
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("[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);
|
LOG_E("scause:0x%p,stval:0x%p,sepc:0x%p\n", scause, stval, sepc);
|
||||||
dump_regs(sp);
|
dump_regs(sp);
|
||||||
|
|
||||||
rt_thread_t cur_thr = rt_thread_self();
|
rt_thread_t cur_thr = rt_thread_self();
|
||||||
struct rt_hw_backtrace_frame frame = {
|
struct rt_hw_backtrace_frame frame = {.fp = sp->s0_fp, .pc = sepc};
|
||||||
.fp = sp->s0_fp,
|
|
||||||
.pc = sepc
|
|
||||||
};
|
|
||||||
rt_kprintf("fp = %p\n", frame.fp);
|
rt_kprintf("fp = %p\n", frame.fp);
|
||||||
lwp_backtrace_frame(cur_thr, &frame);
|
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
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_VECTOR
|
#ifdef ARCH_RISCV_VECTOR
|
||||||
static void vector_enable(struct rt_hw_stack_frame *sp)
|
static void vector_enable(struct rt_hw_stack_frame *sp)
|
||||||
{
|
{
|
||||||
sp->sstatus |= SSTATUS_VS_INITIAL;
|
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
|
* 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
|
// first 7 bits is opcode
|
||||||
int opcode = stval & 0x7f;
|
int opcode = stval & 0x7f;
|
||||||
|
@ -257,12 +260,12 @@ static int illegal_inst_recoverable(rt_ubase_t stval, struct rt_hw_stack_frame *
|
||||||
|
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
{
|
{
|
||||||
case 0x57: // V
|
case 0x57: // V
|
||||||
case 0x27: // scalar FLOAT
|
case 0x27: // scalar FLOAT
|
||||||
case 0x07:
|
case 0x07:
|
||||||
case 0x73: // CSR
|
case 0x73: // CSR
|
||||||
flag = 1;
|
flag = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flag)
|
if (flag)
|
||||||
|
@ -274,11 +277,9 @@ static int illegal_inst_recoverable(rt_ubase_t stval, struct rt_hw_stack_frame *
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void handle_nested_trap_panic(
|
static void handle_nested_trap_panic(rt_ubase_t cause, rt_ubase_t tval,
|
||||||
rt_ubase_t cause,
|
rt_ubase_t epc,
|
||||||
rt_ubase_t tval,
|
struct rt_hw_stack_frame *eframe)
|
||||||
rt_ubase_t epc,
|
|
||||||
struct rt_hw_stack_frame *eframe)
|
|
||||||
{
|
{
|
||||||
LOG_E("\n-------- [SEVER ERROR] --------");
|
LOG_E("\n-------- [SEVER ERROR] --------");
|
||||||
LOG_E("Nested trap detected");
|
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 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 */
|
/* 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;
|
ENTER_TRAP;
|
||||||
rt_ubase_t id = __MASKVALUE(scause, __MASK(63UL));
|
rt_ubase_t id = __MASKVALUE(scause, __MASK(63UL));
|
||||||
const char *msg;
|
const char *msg;
|
||||||
|
|
||||||
/* supervisor external interrupt */
|
/* 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();
|
rt_interrupt_enter();
|
||||||
tick_isr();
|
tick_isr();
|
||||||
rt_interrupt_leave();
|
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
|
else
|
||||||
{
|
{
|
||||||
// trap cannot nested when handling another trap / interrupt
|
if (SCAUSE_INTERRUPT & scause)
|
||||||
CHECK_NESTED_PANIC(scause, stval, sepc, sp);
|
|
||||||
rt_ubase_t id = __MASKVALUE(scause, __MASK(63UL));
|
|
||||||
const char *msg;
|
|
||||||
|
|
||||||
if (scause >> 63)
|
|
||||||
{
|
{
|
||||||
if (id < sizeof(Interrupt_Name) / sizeof(const char *))
|
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";
|
msg = "Unknown Interrupt";
|
||||||
}
|
}
|
||||||
|
|
||||||
rt_kprintf("Unhandled Interrupt %ld:%s\n", id, msg);
|
LOG_E("Unhandled Interrupt %ld:%s\n", id, msg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_VECTOR
|
#ifdef ARCH_RISCV_VECTOR
|
||||||
if (scause == 0x2)
|
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;
|
goto _exit;
|
||||||
}
|
}
|
||||||
#endif /* ENABLE_VECTOR */
|
#endif /* ARCH_RISCV_VECTOR */
|
||||||
#ifdef RT_USING_SMART
|
#ifdef RT_USING_SMART
|
||||||
if (!(sp->sstatus & 0x100) || (PAGE_FAULT && IN_USER_SPACE))
|
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
|
#endif
|
||||||
|
|
||||||
// handle kernel exception:
|
// 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);
|
rt_kprintf("scause:0x%p,stval:0x%p,sepc:0x%p\n", scause, stval, sepc);
|
||||||
dump_regs(sp);
|
dump_regs(sp);
|
||||||
|
|
||||||
|
rt_thread_t cur_thr = rt_thread_self();
|
||||||
rt_kprintf("--------------Thread list--------------\n");
|
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");
|
rt_kprintf("--------------Backtrace--------------\n");
|
||||||
struct rt_hw_backtrace_frame frame = {
|
struct rt_hw_backtrace_frame frame = {.fp = sp->s0_fp, .pc = sepc};
|
||||||
.fp = sp->s0_fp,
|
|
||||||
.pc = sepc
|
|
||||||
};
|
|
||||||
rt_kprintf("fp = %p", frame.fp);
|
|
||||||
rt_backtrace_frame(rt_thread_self(), &frame);
|
|
||||||
|
|
||||||
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:
|
||||||
EXIT_TRAP;
|
EXIT_TRAP;
|
||||||
return ;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue