summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-07-19 12:11:19 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-07-25 10:07:43 +0200
commit8db3f0e878b7f008ad05716f501220509662e2c4 (patch)
treed55db59defa95096a3ef156427822a9f8744ab58
parentriscv: New CPU_Exception_frame (diff)
downloadrtems-8db3f0e878b7f008ad05716f501220509662e2c4.tar.bz2
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.
-rw-r--r--bsps/include/bsp/fatal.h4
-rw-r--r--bsps/riscv/include/bsp/linker-symbols.h4
-rw-r--r--bsps/riscv/riscv/btimer/btimer.c2
-rw-r--r--bsps/riscv/riscv/clock/clockdrv.c19
-rw-r--r--bsps/riscv/riscv/include/bsp/irq.h15
-rw-r--r--bsps/riscv/riscv/irq/irq.c28
-rw-r--r--bsps/riscv/riscv/start/bspstart.c (renamed from cpukit/score/cpu/riscv/riscv-exception-default.c)17
-rw-r--r--bsps/riscv/riscv/start/start.S37
-rw-r--r--c/src/lib/libbsp/riscv/riscv/Makefile.am2
-rw-r--r--c/src/lib/libbsp/riscv/riscv/configure.ac3
-rw-r--r--cpukit/score/cpu/riscv/Makefile.am1
-rw-r--r--cpukit/score/cpu/riscv/cpu.c46
-rw-r--r--cpukit/score/cpu/riscv/include/rtems/score/cpu.h30
-rw-r--r--cpukit/score/cpu/riscv/include/rtems/score/cpuimpl.h7
-rw-r--r--cpukit/score/cpu/riscv/riscv-exception-handler.S75
15 files changed, 120 insertions, 170 deletions
diff --git a/bsps/include/bsp/fatal.h b/bsps/include/bsp/fatal.h
index 77c056601c..92ab55fbb4 100644
--- a/bsps/include/bsp/fatal.h
+++ b/bsps/include/bsp/fatal.h
@@ -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
diff --git a/bsps/riscv/include/bsp/linker-symbols.h b/bsps/riscv/include/bsp/linker-symbols.h
index 34bf4873ba..426b17451f 100644
--- a/bsps/riscv/include/bsp/linker-symbols.h
+++ b/bsps/riscv/include/bsp/linker-symbols.h
@@ -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)
diff --git a/bsps/riscv/riscv/btimer/btimer.c b/bsps/riscv/riscv/btimer/btimer.c
index 4dd3193685..796979fbb2 100644
--- a/bsps/riscv/riscv/btimer/btimer.c
+++ b/bsps/riscv/riscv/btimer/btimer.c
@@ -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)
diff --git a/bsps/riscv/riscv/clock/clockdrv.c b/bsps/riscv/riscv/clock/clockdrv.c
index d2d7a406a0..52fb441ce1 100644
--- a/bsps/riscv/riscv/clock/clockdrv.c
+++ b/bsps/riscv/riscv/clock/clockdrv.c
@@ -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"
diff --git a/bsps/riscv/riscv/include/bsp/irq.h b/bsps/riscv/riscv/include/bsp/irq.h
index d7ee45b378..353005fadf 100644
--- a/bsps/riscv/riscv/include/bsp/irq.h
+++ b/bsps/riscv/riscv/include/bsp/irq.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 */
diff --git a/bsps/riscv/riscv/irq/irq.c b/bsps/riscv/riscv/irq/irq.c
index ac4f1ca115..61cf13153b 100644
--- a/bsps/riscv/riscv/irq/irq.c
+++ b/bsps/riscv/riscv/irq/irq.c
@@ -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)
+{
+ /*
+ * 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_NOT_IMPLEMENTED;
+ return RTEMS_SUCCESSFUL;
}
void bsp_interrupt_vector_enable(rtems_vector_number vector)
diff --git a/cpukit/score/cpu/riscv/riscv-exception-default.c b/bsps/riscv/riscv/start/bspstart.c
index 62d0dd3803..217e6f23a6 100644
--- a/cpukit/score/cpu/riscv/riscv-exception-default.c
+++ b/bsps/riscv/riscv/start/bspstart.c
@@ -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();
}
diff --git a/bsps/riscv/riscv/start/start.S b/bsps/riscv/riscv/start/start.S
index 0dad170c3c..83926a9272 100644
--- a/bsps/riscv/riscv/start/start.S
+++ b/bsps/riscv/riscv/start/start.S
@@ -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:
diff --git a/c/src/lib/libbsp/riscv/riscv/Makefile.am b/c/src/lib/libbsp/riscv/riscv/Makefile.am
index c8299f3e72..159b4fe2c9 100644
--- a/c/src/lib/libbsp/riscv/riscv/Makefile.am
+++ b/c/src/lib/libbsp/riscv/riscv/Makefile.am
@@ -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
diff --git a/c/src/lib/libbsp/riscv/riscv/configure.ac b/c/src/lib/libbsp/riscv/riscv/configure.ac
index 17f4eb8d88..478e255844 100644
--- a/c/src/lib/libbsp/riscv/riscv/configure.ac
+++ b/c/src/lib/libbsp/riscv/riscv/configure.ac
@@ -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)])
diff --git a/cpukit/score/cpu/riscv/Makefile.am b/cpukit/score/cpu/riscv/Makefile.am
index 3630c038a7..40fcd1ff75 100644
--- a/cpukit/score/cpu/riscv/Makefile.am
+++ b/cpukit/score/cpu/riscv/Makefile.am
@@ -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
diff --git a/cpukit/score/cpu/riscv/cpu.c b/cpukit/score/cpu/riscv/cpu.c
index 6b29de2273..64eef969b7 100644
--- a/cpukit/score/cpu/riscv/cpu.c
+++ b/cpukit/score/cpu/riscv/cpu.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 {
diff --git a/cpukit/score/cpu/riscv/include/rtems/score/cpu.h b/cpukit/score/cpu/riscv/include/rtems/score/cpu.h
index 5553fa9d05..724385cd75 100644
--- a/cpukit/score/cpu/riscv/include/rtems/score/cpu.h
+++ b/cpukit/score/cpu/riscv/include/rtems/score/cpu.h
@@ -361,36 +361,6 @@ void _CPU_Initialize(
);
/*
- * _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
*
* This routine is the CPU dependent IDLE thread body.
diff --git a/cpukit/score/cpu/riscv/include/rtems/score/cpuimpl.h b/cpukit/score/cpu/riscv/include/rtems/score/cpuimpl.h
index cb60a528de..313b671da0 100644
--- a/cpukit/score/cpu/riscv/include/rtems/score/cpuimpl.h
+++ b/cpukit/score/cpu/riscv/include/rtems/score/cpuimpl.h
@@ -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;
diff --git a/cpukit/score/cpu/riscv/riscv-exception-handler.S b/cpukit/score/cpu/riscv/riscv-exception-handler.S
index 875566cb23..897a15cd11 100644
--- a/cpukit/score/cpu/riscv/riscv-exception-handler.S
+++ b/cpukit/score/cpu/riscv/riscv-exception-handler.S
@@ -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