source: rtems/cpukit/score/cpu/riscv/riscv-exception-handler.S @ 7fe4855

Last change on this file since 7fe4855 was 8db3f0e, checked in by Sebastian Huber <sebastian.huber@…>, on Jul 19, 2018 at 10:11:19 AM

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.

  • Property mode set to 100644
File size: 8.5 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup ScoreCPU
5 *
6 * @brief RISC-V exception support implementation.
7 */
8
9/*
10 * Copyright (c) 2018 embedded brains GmbH
11
12 * Copyright (c) 2015 University of York.
13 * Hesham Almatary <hesham@alumni.york.ac.uk>
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 *    notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 *    notice, this list of conditions and the following disclaimer in the
22 *    documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifdef HAVE_CONFIG_H
38#include "config.h"
39#endif
40
41#include <rtems/asm.h>
42#include <rtems/score/percpu.h>
43
44PUBLIC(_RISCV_Exception_handler)
45
46        .section        .text, "ax", @progbits
47        .align  2
48
49TYPE_FUNC(_RISCV_Exception_handler)
50SYM(_RISCV_Exception_handler):
51        addi    sp, sp, -CPU_INTERRUPT_FRAME_SIZE
52
53        /* Save */
54        SREG    a0, RISCV_INTERRUPT_FRAME_A0(sp)
55        SREG    a1, RISCV_INTERRUPT_FRAME_A1(sp)
56        SREG    a2, RISCV_INTERRUPT_FRAME_A2(sp)
57        SREG    s0, RISCV_INTERRUPT_FRAME_S0(sp)
58        csrr    a0, mcause
59        csrr    a1, mstatus
60        csrr    a2, mepc
61        GET_SELF_CPU_CONTROL    s0
62        SREG    s1, RISCV_INTERRUPT_FRAME_S1(sp)
63#if __riscv_flen > 0
64        frcsr   s1
65#endif
66        SREG    ra, RISCV_INTERRUPT_FRAME_RA(sp)
67        SREG    a3, RISCV_INTERRUPT_FRAME_A3(sp)
68        SREG    a4, RISCV_INTERRUPT_FRAME_A4(sp)
69        SREG    a5, RISCV_INTERRUPT_FRAME_A5(sp)
70        SREG    a6, RISCV_INTERRUPT_FRAME_A6(sp)
71        SREG    a7, RISCV_INTERRUPT_FRAME_A7(sp)
72        SREG    t0, RISCV_INTERRUPT_FRAME_T0(sp)
73        SREG    t1, RISCV_INTERRUPT_FRAME_T1(sp)
74        SREG    t2, RISCV_INTERRUPT_FRAME_T2(sp)
75        SREG    t3, RISCV_INTERRUPT_FRAME_T3(sp)
76        SREG    t4, RISCV_INTERRUPT_FRAME_T4(sp)
77        SREG    t5, RISCV_INTERRUPT_FRAME_T5(sp)
78        SREG    t6, RISCV_INTERRUPT_FRAME_T6(sp)
79        SREG    a1, RISCV_INTERRUPT_FRAME_MSTATUS(sp)
80        SREG    a2, RISCV_INTERRUPT_FRAME_MEPC(sp)
81#if __riscv_flen > 0
82        sw      s1, RISCV_INTERRUPT_FRAME_FCSR(sp)
83        FSREG   ft0, RISCV_INTERRUPT_FRAME_FT0(sp)
84        FSREG   ft1, RISCV_INTERRUPT_FRAME_FT1(sp)
85        FSREG   ft2, RISCV_INTERRUPT_FRAME_FT2(sp)
86        FSREG   ft3, RISCV_INTERRUPT_FRAME_FT3(sp)
87        FSREG   ft4, RISCV_INTERRUPT_FRAME_FT4(sp)
88        FSREG   ft5, RISCV_INTERRUPT_FRAME_FT5(sp)
89        FSREG   ft6, RISCV_INTERRUPT_FRAME_FT6(sp)
90        FSREG   ft7, RISCV_INTERRUPT_FRAME_FT7(sp)
91        FSREG   ft8, RISCV_INTERRUPT_FRAME_FT8(sp)
92        FSREG   ft9, RISCV_INTERRUPT_FRAME_FT9(sp)
93        FSREG   ft10, RISCV_INTERRUPT_FRAME_FT10(sp)
94        FSREG   ft11, RISCV_INTERRUPT_FRAME_FT11(sp)
95        FSREG   fa0, RISCV_INTERRUPT_FRAME_FA0(sp)
96        FSREG   fa1, RISCV_INTERRUPT_FRAME_FA1(sp)
97        FSREG   fa2, RISCV_INTERRUPT_FRAME_FA2(sp)
98        FSREG   fa3, RISCV_INTERRUPT_FRAME_FA3(sp)
99        FSREG   fa4, RISCV_INTERRUPT_FRAME_FA4(sp)
100        FSREG   fa5, RISCV_INTERRUPT_FRAME_FA5(sp)
101        FSREG   fa6, RISCV_INTERRUPT_FRAME_FA6(sp)
102        FSREG   fa7, RISCV_INTERRUPT_FRAME_FA7(sp)
103#endif
104
105        /* Check if this is a synchronous or interrupt exception */
106        bgez    a0, .Lsynchronous_exception
107
108        /* Increment interrupt nest and thread dispatch disable level */
109        lw      t0, PER_CPU_ISR_NEST_LEVEL(s0)
110        lw      t1, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(s0)
111        addi    t2, t0, 1
112        addi    t1, t1, 1
113        sw      t2, PER_CPU_ISR_NEST_LEVEL(s0)
114        sw      t1, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(s0)
115
116        CLEAR_RESERVATIONS      s0
117
118        /*
119         * Remember current stack pointer in non-volatile register s1.  Switch
120         * to interrupt stack if necessary.
121         */
122        mv      s1, sp
123        bnez    t0, .Linterrupt_stack_switch_done
124        LREG    sp, PER_CPU_INTERRUPT_STACK_HIGH(s0)
125.Linterrupt_stack_switch_done:
126
127        mv      a1, s0
128        call    _RISCV_Interrupt_dispatch
129
130        /* Load some per-CPU variables */
131        lw      t0, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(s0)
132        lbu     t1, PER_CPU_DISPATCH_NEEDED(s0)
133        lw      t2, PER_CPU_ISR_DISPATCH_DISABLE(s0)
134        lw      t3, PER_CPU_ISR_NEST_LEVEL(s0)
135
136        /* Restore stack pointer */
137        mv      sp, s1
138
139        /* Decrement levels and determine thread dispatch state */
140        xor     t1, t1, t0
141        addi    t0, t0, -1
142        or      t1, t1, t0
143        or      t1, t1, t2
144        addi    t3, t3, -1
145
146        /* Store thread dispatch disable and ISR nest levels */
147        sw      t0, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(s0)
148        sw      t3, PER_CPU_ISR_NEST_LEVEL(s0)
149
150        /*
151         * Check thread dispatch necessary, ISR dispatch disable and thread
152         * dispatch disable level.
153         */
154        bnez    t1, .Lthread_dispatch_done
155
156.Ldo_thread_dispatch:
157
158        /* Set ISR dispatch disable and thread dispatch disable level to one */
159        li      t0, 1
160        sw      t0, PER_CPU_ISR_DISPATCH_DISABLE(s0)
161        sw      t0, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(s0)
162
163        /* Call _Thread_Do_dispatch(), this function will enable interrupts */
164        mv      a0, s0
165        li      a1, RISCV_MSTATUS_MIE
166        call    _Thread_Do_dispatch
167
168        /* Disable interrupts */
169        csrrc   zero, mstatus, RISCV_MSTATUS_MIE
170
171#ifdef RTEMS_SMP
172        GET_SELF_CPU_CONTROL    s0
173#endif
174
175        /* Check if we have to do the thread dispatch again */
176        lbu     t0, PER_CPU_DISPATCH_NEEDED(s0)
177        bnez    t0, .Ldo_thread_dispatch
178
179        /* We are done with thread dispatching */
180        sw      zero, PER_CPU_ISR_DISPATCH_DISABLE(s0)
181
182.Lthread_dispatch_done:
183
184        /* Restore */
185        LREG    a0, RISCV_INTERRUPT_FRAME_MSTATUS(sp)
186        LREG    a1, RISCV_INTERRUPT_FRAME_MEPC(sp)
187        LREG    a2, RISCV_INTERRUPT_FRAME_A2(sp)
188        LREG    s0, RISCV_INTERRUPT_FRAME_S0(sp)
189        LREG    s1, RISCV_INTERRUPT_FRAME_S1(sp)
190        LREG    ra, RISCV_INTERRUPT_FRAME_RA(sp)
191        LREG    a3, RISCV_INTERRUPT_FRAME_A3(sp)
192        LREG    a4, RISCV_INTERRUPT_FRAME_A4(sp)
193        LREG    a5, RISCV_INTERRUPT_FRAME_A5(sp)
194        LREG    a6, RISCV_INTERRUPT_FRAME_A6(sp)
195        LREG    a7, RISCV_INTERRUPT_FRAME_A7(sp)
196        LREG    t0, RISCV_INTERRUPT_FRAME_T0(sp)
197        LREG    t1, RISCV_INTERRUPT_FRAME_T1(sp)
198        LREG    t2, RISCV_INTERRUPT_FRAME_T2(sp)
199        LREG    t3, RISCV_INTERRUPT_FRAME_T3(sp)
200        LREG    t4, RISCV_INTERRUPT_FRAME_T4(sp)
201        LREG    t5, RISCV_INTERRUPT_FRAME_T5(sp)
202        LREG    t6, RISCV_INTERRUPT_FRAME_T6(sp)
203        csrw    mstatus, a0
204        csrw    mepc, a1
205#if __riscv_flen > 0
206        lw      a0, RISCV_INTERRUPT_FRAME_FCSR(sp)
207        FLREG   ft0, RISCV_INTERRUPT_FRAME_FT0(sp)
208        FLREG   ft1, RISCV_INTERRUPT_FRAME_FT1(sp)
209        FLREG   ft2, RISCV_INTERRUPT_FRAME_FT2(sp)
210        FLREG   ft3, RISCV_INTERRUPT_FRAME_FT3(sp)
211        FLREG   ft4, RISCV_INTERRUPT_FRAME_FT4(sp)
212        FLREG   ft5, RISCV_INTERRUPT_FRAME_FT5(sp)
213        FLREG   ft6, RISCV_INTERRUPT_FRAME_FT6(sp)
214        FLREG   ft7, RISCV_INTERRUPT_FRAME_FT7(sp)
215        FLREG   ft8, RISCV_INTERRUPT_FRAME_FT8(sp)
216        FLREG   ft9, RISCV_INTERRUPT_FRAME_FT9(sp)
217        FLREG   ft10, RISCV_INTERRUPT_FRAME_FT10(sp)
218        FLREG   ft11, RISCV_INTERRUPT_FRAME_FT11(sp)
219        FLREG   fa0, RISCV_INTERRUPT_FRAME_FA0(sp)
220        FLREG   fa1, RISCV_INTERRUPT_FRAME_FA1(sp)
221        FLREG   fa2, RISCV_INTERRUPT_FRAME_FA2(sp)
222        FLREG   fa3, RISCV_INTERRUPT_FRAME_FA3(sp)
223        FLREG   fa4, RISCV_INTERRUPT_FRAME_FA4(sp)
224        FLREG   fa5, RISCV_INTERRUPT_FRAME_FA5(sp)
225        FLREG   fa6, RISCV_INTERRUPT_FRAME_FA6(sp)
226        FLREG   fa7, RISCV_INTERRUPT_FRAME_FA7(sp)
227        fscsr   a0
228#endif
229        LREG    a0, RISCV_INTERRUPT_FRAME_A0(sp)
230        LREG    a1, RISCV_INTERRUPT_FRAME_A1(sp)
231
232        addi    sp, sp, CPU_INTERRUPT_FRAME_SIZE
233
234        mret
235
236.Lsynchronous_exception:
237
238        SREG    a0, RISCV_EXCEPTION_FRAME_MCAUSE(sp)
239        addi    a0, sp, CPU_INTERRUPT_FRAME_SIZE
240        SREG    a0, RISCV_EXCEPTION_FRAME_SP(sp)
241        SREG    gp, RISCV_EXCEPTION_FRAME_GP(sp)
242        SREG    tp, RISCV_EXCEPTION_FRAME_TP(sp)
243        SREG    s2, RISCV_EXCEPTION_FRAME_S2(sp)
244        SREG    s3, RISCV_EXCEPTION_FRAME_S3(sp)
245        SREG    s4, RISCV_EXCEPTION_FRAME_S4(sp)
246        SREG    s5, RISCV_EXCEPTION_FRAME_S5(sp)
247        SREG    s6, RISCV_EXCEPTION_FRAME_S6(sp)
248        SREG    s7, RISCV_EXCEPTION_FRAME_S7(sp)
249        SREG    s8, RISCV_EXCEPTION_FRAME_S8(sp)
250        SREG    s9, RISCV_EXCEPTION_FRAME_S9(sp)
251        SREG    s10, RISCV_EXCEPTION_FRAME_S10(sp)
252        SREG    s11, RISCV_EXCEPTION_FRAME_S11(sp)
253#if __riscv_flen > 0
254        FSREG   fs0, RISCV_EXCEPTION_FRAME_FS0(sp)
255        FSREG   fs1, RISCV_EXCEPTION_FRAME_FS1(sp)
256        FSREG   fs2, RISCV_EXCEPTION_FRAME_FS2(sp)
257        FSREG   fs3, RISCV_EXCEPTION_FRAME_FS3(sp)
258        FSREG   fs4, RISCV_EXCEPTION_FRAME_FS4(sp)
259        FSREG   fs5, RISCV_EXCEPTION_FRAME_FS5(sp)
260        FSREG   fs6, RISCV_EXCEPTION_FRAME_FS6(sp)
261        FSREG   fs7, RISCV_EXCEPTION_FRAME_FS7(sp)
262        FSREG   fs8, RISCV_EXCEPTION_FRAME_FS8(sp)
263        FSREG   fs9, RISCV_EXCEPTION_FRAME_FS9(sp)
264        FSREG   fs10, RISCV_EXCEPTION_FRAME_FS10(sp)
265        FSREG   fs11, RISCV_EXCEPTION_FRAME_FS11(sp)
266#endif
267
268        li      a0, 9
269        mv      a1, sp
270        call    _Terminate
Note: See TracBrowser for help on using the repository browser.