source: rtems/cpukit/score/cpu/riscv/riscv-exception-handler.S @ 5694b0c

5
Last change on this file since 5694b0c was bca36d9, checked in by Sebastian Huber <sebastian.huber@…>, on 07/06/18 at 09:07:20

riscv: Add LADDR assembler define

An address must be loaded to a register according to the code model.
Add LADDR define for use in assembler code.

Update #3433.

  • Property mode set to 100644
File size: 7.6 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
44EXTERN(bsp_start_vector_table_begin)
45EXTERN(_Thread_Dispatch)
46PUBLIC(ISR_Handler)
47
48        .section        .text, "ax", @progbits
49        .align  2
50
51TYPE_FUNC(ISR_Handler)
52SYM(ISR_Handler):
53        addi    sp, sp, -CPU_INTERRUPT_FRAME_SIZE
54
55        /* Save */
56        SREG    a0, RISCV_INTERRUPT_FRAME_A0(sp)
57        SREG    a1, RISCV_INTERRUPT_FRAME_A1(sp)
58        SREG    a2, RISCV_INTERRUPT_FRAME_A2(sp)
59        SREG    s0, RISCV_INTERRUPT_FRAME_S0(sp)
60        csrr    a0, mcause
61        csrr    a1, mstatus
62        csrr    a2, mepc
63        GET_SELF_CPU_CONTROL    s0
64        SREG    s1, RISCV_INTERRUPT_FRAME_S1(sp)
65#if __riscv_flen > 0
66        frcsr   s1
67#endif
68        SREG    ra, RISCV_INTERRUPT_FRAME_RA(sp)
69        SREG    a3, RISCV_INTERRUPT_FRAME_A3(sp)
70        SREG    a4, RISCV_INTERRUPT_FRAME_A4(sp)
71        SREG    a5, RISCV_INTERRUPT_FRAME_A5(sp)
72        SREG    a6, RISCV_INTERRUPT_FRAME_A6(sp)
73        SREG    a7, RISCV_INTERRUPT_FRAME_A7(sp)
74        SREG    t0, RISCV_INTERRUPT_FRAME_T0(sp)
75        SREG    t1, RISCV_INTERRUPT_FRAME_T1(sp)
76        SREG    t2, RISCV_INTERRUPT_FRAME_T2(sp)
77        SREG    t3, RISCV_INTERRUPT_FRAME_T3(sp)
78        SREG    t4, RISCV_INTERRUPT_FRAME_T4(sp)
79        SREG    t5, RISCV_INTERRUPT_FRAME_T5(sp)
80        SREG    t6, RISCV_INTERRUPT_FRAME_T6(sp)
81        SREG    a1, RISCV_INTERRUPT_FRAME_MSTATUS(sp)
82        SREG    a2, RISCV_INTERRUPT_FRAME_MEPC(sp)
83#if __riscv_flen > 0
84        sw      s1, RISCV_INTERRUPT_FRAME_FCSR(sp)
85        FSREG   ft0, RISCV_INTERRUPT_FRAME_FT0(sp)
86        FSREG   ft1, RISCV_INTERRUPT_FRAME_FT1(sp)
87        FSREG   ft2, RISCV_INTERRUPT_FRAME_FT2(sp)
88        FSREG   ft3, RISCV_INTERRUPT_FRAME_FT3(sp)
89        FSREG   ft4, RISCV_INTERRUPT_FRAME_FT4(sp)
90        FSREG   ft5, RISCV_INTERRUPT_FRAME_FT5(sp)
91        FSREG   ft6, RISCV_INTERRUPT_FRAME_FT6(sp)
92        FSREG   ft7, RISCV_INTERRUPT_FRAME_FT7(sp)
93        FSREG   ft8, RISCV_INTERRUPT_FRAME_FT8(sp)
94        FSREG   ft9, RISCV_INTERRUPT_FRAME_FT9(sp)
95        FSREG   ft10, RISCV_INTERRUPT_FRAME_FT10(sp)
96        FSREG   ft11, RISCV_INTERRUPT_FRAME_FT11(sp)
97        FSREG   fa0, RISCV_INTERRUPT_FRAME_FA0(sp)
98        FSREG   fa1, RISCV_INTERRUPT_FRAME_FA1(sp)
99        FSREG   fa2, RISCV_INTERRUPT_FRAME_FA2(sp)
100        FSREG   fa3, RISCV_INTERRUPT_FRAME_FA3(sp)
101        FSREG   fa4, RISCV_INTERRUPT_FRAME_FA4(sp)
102        FSREG   fa5, RISCV_INTERRUPT_FRAME_FA5(sp)
103        FSREG   fa6, RISCV_INTERRUPT_FRAME_FA6(sp)
104        FSREG   fa7, RISCV_INTERRUPT_FRAME_FA7(sp)
105#endif
106
107        /* FIXME Only handle interrupts for now (MSB = 1) */
108        andi    a0, a0, 0xf
109
110        /* Increment interrupt nest and thread dispatch disable level */
111        lw      t0, PER_CPU_ISR_NEST_LEVEL(s0)
112        lw      t1, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(s0)
113        addi    t2, t0, 1
114        addi    t1, t1, 1
115        sw      t2, PER_CPU_ISR_NEST_LEVEL(s0)
116        sw      t1, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(s0)
117
118        CLEAR_RESERVATIONS      s0
119
120        /* Keep sp (Exception frame address) in s1 */
121        mv      s1, sp
122
123        /* Call the exception handler from vector table */
124
125        /* First function arg for C handler is vector number,
126                * and the second is a pointer to exception frame.
127                * a0/mcause/vector number is already loaded above */
128        mv      a1, sp
129
130        /* calculate the offset */
131        LADDR   t5, bsp_start_vector_table_begin
132#if     __riscv_xlen == 32
133        slli    t6, a0, 2
134#else   /* xlen = 64 */
135        slli    t6, a0, 3
136#endif
137        add     t5, t5, t6
138        LREG    t5, (t5)
139
140        /* Switch to interrupt stack if necessary */
141        bnez    t0, .Linterrupt_stack_switch_done
142        LREG    sp, PER_CPU_INTERRUPT_STACK_HIGH(s0)
143.Linterrupt_stack_switch_done:
144
145        jalr    t5
146
147        /* Load some per-CPU variables */
148        lw      t0, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(s0)
149        lbu     t1, PER_CPU_DISPATCH_NEEDED(s0)
150        lw      t2, PER_CPU_ISR_DISPATCH_DISABLE(s0)
151        lw      t3, PER_CPU_ISR_NEST_LEVEL(s0)
152
153        /* Restore stack pointer */
154        mv      sp, s1
155
156        /* Decrement levels and determine thread dispatch state */
157        xor     t1, t1, t0
158        addi    t0, t0, -1
159        or      t1, t1, t0
160        or      t1, t1, t2
161        addi    t3, t3, -1
162
163        /* Store thread dispatch disable and ISR nest levels */
164        sw      t0, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(s0)
165        sw      t3, PER_CPU_ISR_NEST_LEVEL(s0)
166
167        /*
168         * Check thread dispatch necessary, ISR dispatch disable and thread
169         * dispatch disable level.
170         */
171        bnez    t1, .Lthread_dispatch_done
172
173.Ldo_thread_dispatch:
174
175        /* Set ISR dispatch disable and thread dispatch disable level to one */
176        li      t0, 1
177        sw      t0, PER_CPU_ISR_DISPATCH_DISABLE(s0)
178        sw      t0, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(s0)
179
180        /* Call _Thread_Do_dispatch(), this function will enable interrupts */
181        mv      a0, s0
182        li      a1, RISCV_MSTATUS_MIE
183        call    _Thread_Do_dispatch
184
185        /* Disable interrupts */
186        csrrc   zero, mstatus, RISCV_MSTATUS_MIE
187
188#ifdef RTEMS_SMP
189        GET_SELF_CPU_CONTROL    s0
190#endif
191
192        /* Check if we have to do the thread dispatch again */
193        lbu     t0, PER_CPU_DISPATCH_NEEDED(s0)
194        bnez    t0, .Ldo_thread_dispatch
195
196        /* We are done with thread dispatching */
197        sw      zero, PER_CPU_ISR_DISPATCH_DISABLE(s0)
198
199.Lthread_dispatch_done:
200
201        /* Restore */
202        LREG    a0, RISCV_INTERRUPT_FRAME_MSTATUS(sp)
203        LREG    a1, RISCV_INTERRUPT_FRAME_MEPC(sp)
204        LREG    a2, RISCV_INTERRUPT_FRAME_A2(sp)
205        LREG    s0, RISCV_INTERRUPT_FRAME_S0(sp)
206        LREG    s1, RISCV_INTERRUPT_FRAME_S1(sp)
207        LREG    ra, RISCV_INTERRUPT_FRAME_RA(sp)
208        LREG    a3, RISCV_INTERRUPT_FRAME_A3(sp)
209        LREG    a4, RISCV_INTERRUPT_FRAME_A4(sp)
210        LREG    a5, RISCV_INTERRUPT_FRAME_A5(sp)
211        LREG    a6, RISCV_INTERRUPT_FRAME_A6(sp)
212        LREG    a7, RISCV_INTERRUPT_FRAME_A7(sp)
213        LREG    t0, RISCV_INTERRUPT_FRAME_T0(sp)
214        LREG    t1, RISCV_INTERRUPT_FRAME_T1(sp)
215        LREG    t2, RISCV_INTERRUPT_FRAME_T2(sp)
216        LREG    t3, RISCV_INTERRUPT_FRAME_T3(sp)
217        LREG    t4, RISCV_INTERRUPT_FRAME_T4(sp)
218        LREG    t5, RISCV_INTERRUPT_FRAME_T5(sp)
219        LREG    t6, RISCV_INTERRUPT_FRAME_T6(sp)
220        csrw    mstatus, a0
221        csrw    mepc, a1
222#if __riscv_flen > 0
223        lw      a0, RISCV_INTERRUPT_FRAME_FCSR(sp)
224        FLREG   ft0, RISCV_INTERRUPT_FRAME_FT0(sp)
225        FLREG   ft1, RISCV_INTERRUPT_FRAME_FT1(sp)
226        FLREG   ft2, RISCV_INTERRUPT_FRAME_FT2(sp)
227        FLREG   ft3, RISCV_INTERRUPT_FRAME_FT3(sp)
228        FLREG   ft4, RISCV_INTERRUPT_FRAME_FT4(sp)
229        FLREG   ft5, RISCV_INTERRUPT_FRAME_FT5(sp)
230        FLREG   ft6, RISCV_INTERRUPT_FRAME_FT6(sp)
231        FLREG   ft7, RISCV_INTERRUPT_FRAME_FT7(sp)
232        FLREG   ft8, RISCV_INTERRUPT_FRAME_FT8(sp)
233        FLREG   ft9, RISCV_INTERRUPT_FRAME_FT9(sp)
234        FLREG   ft10, RISCV_INTERRUPT_FRAME_FT10(sp)
235        FLREG   ft11, RISCV_INTERRUPT_FRAME_FT11(sp)
236        FLREG   fa0, RISCV_INTERRUPT_FRAME_FA0(sp)
237        FLREG   fa1, RISCV_INTERRUPT_FRAME_FA1(sp)
238        FLREG   fa2, RISCV_INTERRUPT_FRAME_FA2(sp)
239        FLREG   fa3, RISCV_INTERRUPT_FRAME_FA3(sp)
240        FLREG   fa4, RISCV_INTERRUPT_FRAME_FA4(sp)
241        FLREG   fa5, RISCV_INTERRUPT_FRAME_FA5(sp)
242        FLREG   fa6, RISCV_INTERRUPT_FRAME_FA6(sp)
243        FLREG   fa7, RISCV_INTERRUPT_FRAME_FA7(sp)
244        fscsr   a0
245#endif
246        LREG    a0, RISCV_INTERRUPT_FRAME_A0(sp)
247        LREG    a1, RISCV_INTERRUPT_FRAME_A1(sp)
248
249        addi    sp, sp, CPU_INTERRUPT_FRAME_SIZE
250
251        mret
Note: See TracBrowser for help on using the repository browser.