mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-09-22 19:11:44 +08:00
riscv: Rework exception handling
Remove _CPU_ISR_install_raw_handler() and _CPU_ISR_install_vector() functions. Applications can install an exception handler via the fatal error handler to handle synchronous exceptions. Handle interrupt exceptions via _RISCV_Interrupt_dispatch() which must be provided by the BSP. Update #3433.
This commit is contained in:
@@ -142,7 +142,9 @@ typedef enum {
|
||||
/* RISC-V fatal codes */
|
||||
RISCV_FATAL_NO_TIMEBASE_FREQUENCY_IN_DEVICE_TREE = BSP_FATAL_CODE_BLOCK(13),
|
||||
RISCV_FATAL_NO_NS16550_REG_IN_DEVICE_TREE,
|
||||
RISCV_FATAL_NO_NS16550_CLOCK_FREQUENCY_IN_DEVICE_TREE
|
||||
RISCV_FATAL_NO_NS16550_CLOCK_FREQUENCY_IN_DEVICE_TREE,
|
||||
RISCV_FATAL_UNEXPECTED_INTERRUPT_EXCEPTION,
|
||||
RISCV_FATAL_CLOCK_IRQ_INSTALL
|
||||
} bsp_fatal_code;
|
||||
|
||||
RTEMS_NO_RETURN static inline void
|
||||
|
||||
@@ -63,10 +63,6 @@ LINKER_SYMBOL(bsp_vector_table_begin)
|
||||
LINKER_SYMBOL(bsp_vector_table_end)
|
||||
LINKER_SYMBOL(bsp_vector_table_size)
|
||||
|
||||
LINKER_SYMBOL(bsp_start_vector_table_begin)
|
||||
LINKER_SYMBOL(bsp_start_vector_table_end)
|
||||
LINKER_SYMBOL(bsp_start_vector_table_size)
|
||||
|
||||
LINKER_SYMBOL(bsp_translation_table_base)
|
||||
LINKER_SYMBOL(bsp_translation_table_end)
|
||||
|
||||
|
||||
@@ -29,8 +29,6 @@
|
||||
#include <rtems/btimer.h>
|
||||
#include <rtems/score/riscv-utility.h>
|
||||
|
||||
extern char bsp_start_vector_table_begin[];
|
||||
|
||||
bool benchmark_timer_find_average_overhead;
|
||||
|
||||
static void benchmark_timer1_interrupt_handler(void)
|
||||
|
||||
@@ -72,11 +72,20 @@ static void riscv_clock_at_tick(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void riscv_clock_handler_install(proc_ptr new_isr)
|
||||
static void riscv_clock_handler_install(void)
|
||||
{
|
||||
_CPU_ISR_install_vector(RISCV_MACHINE_TIMER_INTERRUPT,
|
||||
new_isr,
|
||||
NULL);
|
||||
rtems_status_code sc;
|
||||
|
||||
sc = rtems_interrupt_handler_install(
|
||||
RISCV_INTERRUPT_VECTOR_TIMER,
|
||||
"Clock",
|
||||
RTEMS_INTERRUPT_UNIQUE,
|
||||
(rtems_interrupt_handler) Clock_isr,
|
||||
NULL
|
||||
);
|
||||
if (sc != RTEMS_SUCCESSFUL) {
|
||||
bsp_fatal(RISCV_FATAL_CLOCK_IRQ_INSTALL);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t riscv_clock_get_timecount(struct timecounter *tc)
|
||||
@@ -136,6 +145,6 @@ uint32_t _CPU_Counter_frequency( void )
|
||||
#define Clock_driver_support_initialize_hardware() riscv_clock_initialize()
|
||||
|
||||
#define Clock_driver_support_install_isr(isr) \
|
||||
riscv_clock_handler_install(isr)
|
||||
riscv_clock_handler_install()
|
||||
|
||||
#include "../../../shared/dev/clock/clockimpl.h"
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018 embedded brains GmbH
|
||||
*
|
||||
* Copyright (c) 2015 University of York.
|
||||
* Hesham Almatary <hesham@alumni.york.ac.uk>
|
||||
@@ -38,12 +39,20 @@
|
||||
|
||||
#ifndef ASM
|
||||
|
||||
#include <rtems.h>
|
||||
#include <bsp.h>
|
||||
#include <rtems/irq.h>
|
||||
#include <rtems/irq-extension.h>
|
||||
|
||||
#define BSP_INTERRUPT_VECTOR_MIN 0x0
|
||||
#define BSP_INTERRUPT_VECTOR_MAX 0x24
|
||||
#define RISCV_INTERRUPT_VECTOR_SOFTWARE 0
|
||||
|
||||
#define RISCV_INTERRUPT_VECTOR_TIMER 1
|
||||
|
||||
#define RISCV_INTERRUPT_VECTOR_EXTERNAL(x) ((x) + 2)
|
||||
|
||||
#define BSP_INTERRUPT_VECTOR_MIN 0
|
||||
|
||||
#define BSP_INTERRUPT_VECTOR_MAX RISCV_INTERRUPT_VECTOR_EXTERNAL(RISCV_MAXIMUM_EXTERNAL_INTERRUPTS - 1)
|
||||
|
||||
#endif /* ASM */
|
||||
|
||||
#endif /* LIBBSP_GENERIC_RISCV_IRQ_H */
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* RISCV CPU Dependent Source
|
||||
* Copyright (c) 2018 embedded brains GmbH
|
||||
*
|
||||
* Copyright (c) 2015 University of York.
|
||||
* Hesham Almatary <hesham@alumni.york.ac.uk>
|
||||
@@ -35,11 +35,33 @@
|
||||
*/
|
||||
|
||||
#include <bsp/irq.h>
|
||||
#include <bsp/fatal.h>
|
||||
#include <bsp/irq-generic.h>
|
||||
|
||||
rtems_status_code bsp_interrupt_facility_initialize()
|
||||
#include <rtems/score/percpu.h>
|
||||
|
||||
void _RISCV_Interrupt_dispatch(uintptr_t mcause, Per_CPU_Control *cpu_self)
|
||||
{
|
||||
return RTEMS_NOT_IMPLEMENTED;
|
||||
/*
|
||||
* Get rid of the most significant bit which indicates if the exception was
|
||||
* caused by an interrupt or not.
|
||||
*/
|
||||
mcause <<= 1;
|
||||
|
||||
if (mcause == (RISCV_INTERRUPT_TIMER_MACHINE << 1)) {
|
||||
bsp_interrupt_handler_dispatch(RISCV_INTERRUPT_VECTOR_TIMER);
|
||||
} else if (mcause == (RISCV_INTERRUPT_EXTERNAL_MACHINE << 1)) {
|
||||
/* TODO: Handle PLIC interrupt */
|
||||
} else if (mcause == (RISCV_INTERRUPT_SOFTWARE_MACHINE << 1)) {
|
||||
bsp_interrupt_handler_dispatch(RISCV_INTERRUPT_VECTOR_SOFTWARE);
|
||||
} else {
|
||||
bsp_fatal(RISCV_FATAL_UNEXPECTED_INTERRUPT_EXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
rtems_status_code bsp_interrupt_facility_initialize(void)
|
||||
{
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
void bsp_interrupt_vector_enable(rtems_vector_number vector)
|
||||
|
||||
+5
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Hesham Almatary <heshamelmatary@gmail.com>
|
||||
* Copyright (c) 2018 embedded brains GmbH
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -23,17 +23,10 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include <bsp/bootcard.h>
|
||||
#include <bsp/irq-generic.h>
|
||||
|
||||
#include <rtems/score/cpu.h>
|
||||
#include <rtems/fatal.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void _RISCV_Exception_default(uint32_t vector, CPU_Exception_frame *frame);
|
||||
|
||||
void _RISCV_Exception_default(uint32_t vector, CPU_Exception_frame *frame)
|
||||
void bsp_start(void)
|
||||
{
|
||||
rtems_fatal( RTEMS_FATAL_SOURCE_EXCEPTION, (rtems_fatal_code) frame );
|
||||
bsp_interrupt_initialize();
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 embedded brains GmbH
|
||||
|
||||
* Copyright (c) 2015 University of York.
|
||||
* Hesham Almatary <hesham@alumni.york.ac.uk>
|
||||
*
|
||||
@@ -33,13 +35,6 @@
|
||||
#include <bsp/linker-symbols.h>
|
||||
#include <bspopts.h>
|
||||
|
||||
EXTERN(bsp_section_bss_begin)
|
||||
EXTERN(bsp_section_bss_end)
|
||||
EXTERN(ISR_Handler)
|
||||
EXTERN(bsp_section_stack_begin)
|
||||
|
||||
PUBLIC(bsp_start_vector_table_begin)
|
||||
PUBLIC(bsp_start_vector_table_end)
|
||||
PUBLIC(_start)
|
||||
|
||||
.section .bsp_start_text, "wax", @progbits
|
||||
@@ -70,7 +65,7 @@ SYM(_start):
|
||||
call bsp_fdt_copy
|
||||
#endif
|
||||
|
||||
LADDR t0, ISR_Handler
|
||||
LADDR t0, _RISCV_Exception_handler
|
||||
csrw mtvec, t0
|
||||
|
||||
/* Clear .bss */
|
||||
@@ -107,29 +102,3 @@ SYM(_start):
|
||||
.Lsecondary_processor_go:
|
||||
.word 0xdeadbeef
|
||||
#endif
|
||||
|
||||
#if __riscv_xlen == 32
|
||||
#define ADDR .word
|
||||
#elif __riscv_xlen == 64
|
||||
#define ADDR .quad
|
||||
#endif
|
||||
|
||||
.align 4
|
||||
bsp_start_vector_table_begin:
|
||||
ADDR _RISCV_Exception_default /* User int */
|
||||
ADDR _RISCV_Exception_default /* Supervisor int */
|
||||
ADDR _RISCV_Exception_default /* Reserved */
|
||||
ADDR _RISCV_Exception_default /* Machine int */
|
||||
ADDR _RISCV_Exception_default /* User timer int */
|
||||
ADDR _RISCV_Exception_default /* Supervisor Timer int */
|
||||
ADDR _RISCV_Exception_default /* Reserved */
|
||||
ADDR _RISCV_Exception_default /* Machine Timer int */
|
||||
ADDR _RISCV_Exception_default /* User external int */
|
||||
ADDR _RISCV_Exception_default /* Supervisor external int */
|
||||
ADDR _RISCV_Exception_default /* Reserved */
|
||||
ADDR _RISCV_Exception_default /* Machine external int */
|
||||
ADDR _RISCV_Exception_default
|
||||
ADDR _RISCV_Exception_default
|
||||
ADDR _RISCV_Exception_default
|
||||
ADDR _RISCV_Exception_default
|
||||
bsp_start_vector_table_end:
|
||||
|
||||
@@ -33,7 +33,7 @@ project_lib_LIBRARIES = librtemsbsp.a
|
||||
|
||||
# Startup
|
||||
librtemsbsp_a_SOURCES = ../../../../../../bsps/shared/start/bspreset-empty.c
|
||||
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/bspstart-empty.c
|
||||
librtemsbsp_a_SOURCES += ../../../../../../bsps/riscv/riscv/start/bspstart.c
|
||||
librtemsbsp_a_SOURCES += ../../../../../../bsps/riscv/riscv/start/bsp_fatal_halt.c
|
||||
|
||||
# Shared
|
||||
|
||||
@@ -30,6 +30,9 @@ RTEMS_BSPOPTS_HELP([BSP_FDT_BLOB_COPY_TO_READ_ONLY_LOAD_AREA],[copy the FDT blob
|
||||
RTEMS_BSPOPTS_SET([BSP_CONSOLE_BAUD],[*],[115200])
|
||||
RTEMS_BSPOPTS_HELP([BSP_CONSOLE_BAUD],[default baud for console driver devices (default 115200)])
|
||||
|
||||
RTEMS_BSPOPTS_SET([RISCV_MAXIMUM_EXTERNAL_INTERRUPTS],[*],[64])
|
||||
RTEMS_BSPOPTS_HELP([RISCV_MAXIMUM_EXTERNAL_INTERRUPTS],[maximum number of external interrupts supported by the BSP (default 64)])
|
||||
|
||||
RTEMS_BSPOPTS_SET([RISCV_ENABLE_HTIF_SUPPORT],[*],[1])
|
||||
RTEMS_BSPOPTS_HELP([RISCV_ENABLE_HTIF_SUPPORT],[enables the HTIF support if defined to a non-zero value, otherwise it is disabled (enabled by default)])
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ noinst_LIBRARIES = libscorecpu.a
|
||||
libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
libscorecpu_a_SOURCES = cpu.c
|
||||
libscorecpu_a_SOURCES += riscv-exception-handler.S
|
||||
libscorecpu_a_SOURCES += riscv-exception-default.c
|
||||
libscorecpu_a_SOURCES += riscv-exception-frame-print.c
|
||||
libscorecpu_a_SOURCES += riscv-context-switch.S
|
||||
libscorecpu_a_SOURCES += riscv-context-initialize.c
|
||||
|
||||
@@ -173,12 +173,6 @@ RTEMS_STATIC_ASSERT(
|
||||
riscv_interrupt_frame_size
|
||||
);
|
||||
|
||||
/* bsp_start_vector_table_begin is the start address of the vector table
|
||||
* containing addresses to ISR Handlers. It's defined at the BSP linkcmds
|
||||
* and may differ from one BSP to another.
|
||||
*/
|
||||
extern char bsp_start_vector_table_begin[];
|
||||
|
||||
void _init(void);
|
||||
|
||||
void _fini(void);
|
||||
@@ -208,46 +202,6 @@ uint32_t _CPU_ISR_Get_level( void )
|
||||
return 1;
|
||||
}
|
||||
|
||||
void _CPU_ISR_install_raw_handler(
|
||||
uint32_t vector,
|
||||
proc_ptr new_handler,
|
||||
proc_ptr *old_handler
|
||||
)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
void _CPU_ISR_install_vector(
|
||||
unsigned long vector,
|
||||
proc_ptr new_handler,
|
||||
proc_ptr *old_handler
|
||||
)
|
||||
{
|
||||
proc_ptr *table =
|
||||
(proc_ptr *) bsp_start_vector_table_begin;
|
||||
proc_ptr current_handler;
|
||||
|
||||
ISR_Level level;
|
||||
|
||||
_ISR_Local_disable( level );
|
||||
|
||||
current_handler = table [vector];
|
||||
|
||||
/* The current handler is now the old one */
|
||||
if (old_handler != NULL) {
|
||||
*old_handler = (proc_ptr) current_handler;
|
||||
}
|
||||
|
||||
/* Write only if necessary to avoid writes to a maybe read-only
|
||||
* memory */
|
||||
if (current_handler != new_handler) {
|
||||
table [vector] = new_handler;
|
||||
}
|
||||
|
||||
_ISR_Local_enable( level );
|
||||
|
||||
}
|
||||
|
||||
void *_CPU_Thread_Idle_body( uintptr_t ignored )
|
||||
{
|
||||
do {
|
||||
|
||||
@@ -360,36 +360,6 @@ void _CPU_Initialize(
|
||||
void
|
||||
);
|
||||
|
||||
/*
|
||||
* _CPU_ISR_install_raw_handler
|
||||
*
|
||||
* This routine installs a "raw" interrupt handler directly into the
|
||||
* processor's vector table.
|
||||
*
|
||||
*/
|
||||
|
||||
void _CPU_ISR_install_raw_handler(
|
||||
uint32_t vector,
|
||||
proc_ptr new_handler,
|
||||
proc_ptr *old_handler
|
||||
);
|
||||
|
||||
/*
|
||||
* _CPU_ISR_install_vector
|
||||
*
|
||||
* This routine installs an interrupt vector.
|
||||
*
|
||||
* NO_CPU Specific Information:
|
||||
*
|
||||
* XXX document implementation including references if appropriate
|
||||
*/
|
||||
|
||||
void _CPU_ISR_install_vector(
|
||||
unsigned long vector,
|
||||
proc_ptr new_handler,
|
||||
proc_ptr *old_handler
|
||||
);
|
||||
|
||||
/*
|
||||
* _CPU_Thread_Idle_body
|
||||
*
|
||||
|
||||
@@ -289,6 +289,13 @@ typedef struct {
|
||||
} CPU_Per_CPU_control;
|
||||
#endif
|
||||
|
||||
struct Per_CPU_Control;
|
||||
|
||||
void _RISCV_Interrupt_dispatch(
|
||||
uintptr_t mcause,
|
||||
struct Per_CPU_Control *cpu_self
|
||||
);
|
||||
|
||||
static inline uint32_t _RISCV_Read_FCSR( void )
|
||||
{
|
||||
uint32_t fcsr;
|
||||
|
||||
@@ -41,15 +41,13 @@
|
||||
#include <rtems/asm.h>
|
||||
#include <rtems/score/percpu.h>
|
||||
|
||||
EXTERN(bsp_start_vector_table_begin)
|
||||
EXTERN(_Thread_Dispatch)
|
||||
PUBLIC(ISR_Handler)
|
||||
PUBLIC(_RISCV_Exception_handler)
|
||||
|
||||
.section .text, "ax", @progbits
|
||||
.align 2
|
||||
|
||||
TYPE_FUNC(ISR_Handler)
|
||||
SYM(ISR_Handler):
|
||||
TYPE_FUNC(_RISCV_Exception_handler)
|
||||
SYM(_RISCV_Exception_handler):
|
||||
addi sp, sp, -CPU_INTERRUPT_FRAME_SIZE
|
||||
|
||||
/* Save */
|
||||
@@ -104,8 +102,8 @@ SYM(ISR_Handler):
|
||||
FSREG fa7, RISCV_INTERRUPT_FRAME_FA7(sp)
|
||||
#endif
|
||||
|
||||
/* FIXME Only handle interrupts for now (MSB = 1) */
|
||||
andi a0, a0, 0xf
|
||||
/* Check if this is a synchronous or interrupt exception */
|
||||
bgez a0, .Lsynchronous_exception
|
||||
|
||||
/* Increment interrupt nest and thread dispatch disable level */
|
||||
lw t0, PER_CPU_ISR_NEST_LEVEL(s0)
|
||||
@@ -117,32 +115,17 @@ SYM(ISR_Handler):
|
||||
|
||||
CLEAR_RESERVATIONS s0
|
||||
|
||||
/* Keep sp (Exception frame address) in s1 */
|
||||
/*
|
||||
* Remember current stack pointer in non-volatile register s1. Switch
|
||||
* to interrupt stack if necessary.
|
||||
*/
|
||||
mv s1, sp
|
||||
|
||||
/* Call the exception handler from vector table */
|
||||
|
||||
/* First function arg for C handler is vector number,
|
||||
* and the second is a pointer to exception frame.
|
||||
* a0/mcause/vector number is already loaded above */
|
||||
mv a1, sp
|
||||
|
||||
/* calculate the offset */
|
||||
LADDR t5, bsp_start_vector_table_begin
|
||||
#if __riscv_xlen == 32
|
||||
slli t6, a0, 2
|
||||
#else /* xlen = 64 */
|
||||
slli t6, a0, 3
|
||||
#endif
|
||||
add t5, t5, t6
|
||||
LREG t5, (t5)
|
||||
|
||||
/* Switch to interrupt stack if necessary */
|
||||
bnez t0, .Linterrupt_stack_switch_done
|
||||
LREG sp, PER_CPU_INTERRUPT_STACK_HIGH(s0)
|
||||
.Linterrupt_stack_switch_done:
|
||||
|
||||
jalr t5
|
||||
mv a1, s0
|
||||
call _RISCV_Interrupt_dispatch
|
||||
|
||||
/* Load some per-CPU variables */
|
||||
lw t0, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(s0)
|
||||
@@ -249,3 +232,39 @@ SYM(ISR_Handler):
|
||||
addi sp, sp, CPU_INTERRUPT_FRAME_SIZE
|
||||
|
||||
mret
|
||||
|
||||
.Lsynchronous_exception:
|
||||
|
||||
SREG a0, RISCV_EXCEPTION_FRAME_MCAUSE(sp)
|
||||
addi a0, sp, CPU_INTERRUPT_FRAME_SIZE
|
||||
SREG a0, RISCV_EXCEPTION_FRAME_SP(sp)
|
||||
SREG gp, RISCV_EXCEPTION_FRAME_GP(sp)
|
||||
SREG tp, RISCV_EXCEPTION_FRAME_TP(sp)
|
||||
SREG s2, RISCV_EXCEPTION_FRAME_S2(sp)
|
||||
SREG s3, RISCV_EXCEPTION_FRAME_S3(sp)
|
||||
SREG s4, RISCV_EXCEPTION_FRAME_S4(sp)
|
||||
SREG s5, RISCV_EXCEPTION_FRAME_S5(sp)
|
||||
SREG s6, RISCV_EXCEPTION_FRAME_S6(sp)
|
||||
SREG s7, RISCV_EXCEPTION_FRAME_S7(sp)
|
||||
SREG s8, RISCV_EXCEPTION_FRAME_S8(sp)
|
||||
SREG s9, RISCV_EXCEPTION_FRAME_S9(sp)
|
||||
SREG s10, RISCV_EXCEPTION_FRAME_S10(sp)
|
||||
SREG s11, RISCV_EXCEPTION_FRAME_S11(sp)
|
||||
#if __riscv_flen > 0
|
||||
FSREG fs0, RISCV_EXCEPTION_FRAME_FS0(sp)
|
||||
FSREG fs1, RISCV_EXCEPTION_FRAME_FS1(sp)
|
||||
FSREG fs2, RISCV_EXCEPTION_FRAME_FS2(sp)
|
||||
FSREG fs3, RISCV_EXCEPTION_FRAME_FS3(sp)
|
||||
FSREG fs4, RISCV_EXCEPTION_FRAME_FS4(sp)
|
||||
FSREG fs5, RISCV_EXCEPTION_FRAME_FS5(sp)
|
||||
FSREG fs6, RISCV_EXCEPTION_FRAME_FS6(sp)
|
||||
FSREG fs7, RISCV_EXCEPTION_FRAME_FS7(sp)
|
||||
FSREG fs8, RISCV_EXCEPTION_FRAME_FS8(sp)
|
||||
FSREG fs9, RISCV_EXCEPTION_FRAME_FS9(sp)
|
||||
FSREG fs10, RISCV_EXCEPTION_FRAME_FS10(sp)
|
||||
FSREG fs11, RISCV_EXCEPTION_FRAME_FS11(sp)
|
||||
#endif
|
||||
|
||||
li a0, 9
|
||||
mv a1, sp
|
||||
call _Terminate
|
||||
|
||||
Reference in New Issue
Block a user