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

5
Last change on this file since dffc08c was dffc08c, checked in by Sebastian Huber <sebastian.huber@…>, on Jun 28, 2018 at 11:55:29 AM

riscv: Fix interrupt save/restore

Update #3433.

  • Property mode set to 100644
File size: 7.1 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, -1 * 36 * CPU_SIZEOF_POINTER
54
55        SREG    x1, (1 * CPU_SIZEOF_POINTER)(sp)
56        /* Skip x2/sp */
57        SREG    x3, (3 * CPU_SIZEOF_POINTER)(sp)
58        SREG    x4, (4 * CPU_SIZEOF_POINTER)(sp)
59        SREG    x5, (5 * CPU_SIZEOF_POINTER)(sp)
60        SREG    x6, (6 * CPU_SIZEOF_POINTER)(sp)
61        SREG    x7, (7 * CPU_SIZEOF_POINTER)(sp)
62        SREG    x8, (8 * CPU_SIZEOF_POINTER)(sp)
63        SREG    x9, (9 * CPU_SIZEOF_POINTER)(sp)
64        SREG    x10, (10 * CPU_SIZEOF_POINTER)(sp)
65        SREG    x11, (11 * CPU_SIZEOF_POINTER)(sp)
66        SREG    x12, (12 * CPU_SIZEOF_POINTER)(sp)
67        SREG    x13, (13 * CPU_SIZEOF_POINTER)(sp)
68        SREG    x14, (14 * CPU_SIZEOF_POINTER)(sp)
69        SREG    x15, (15 * CPU_SIZEOF_POINTER)(sp)
70        SREG    x16, (16 * CPU_SIZEOF_POINTER)(sp)
71        SREG    x17, (17 * CPU_SIZEOF_POINTER)(sp)
72        SREG    x18, (18 * CPU_SIZEOF_POINTER)(sp)
73        SREG    x19, (19 * CPU_SIZEOF_POINTER)(sp)
74        SREG    x20, (20 * CPU_SIZEOF_POINTER)(sp)
75        SREG    x21, (21 * CPU_SIZEOF_POINTER)(sp)
76        SREG    x22, (22 * CPU_SIZEOF_POINTER)(sp)
77        SREG    x23, (23 * CPU_SIZEOF_POINTER)(sp)
78        SREG    x24, (24 * CPU_SIZEOF_POINTER)(sp)
79        SREG    x25, (25 * CPU_SIZEOF_POINTER)(sp)
80        SREG    x26, (26 * CPU_SIZEOF_POINTER)(sp)
81        SREG    x27, (27 * CPU_SIZEOF_POINTER)(sp)
82        SREG    x28, (28 * CPU_SIZEOF_POINTER)(sp)
83        SREG    x29, (29 * CPU_SIZEOF_POINTER)(sp)
84        SREG    x30, (30 * CPU_SIZEOF_POINTER)(sp)
85        SREG    x31, (31 * CPU_SIZEOF_POINTER)(sp)
86
87        /* Exception level related registers */
88        csrr    a0, mstatus
89        SREG    a0, (32 * CPU_SIZEOF_POINTER)(sp)
90        csrr    a0, mcause
91        SREG    a0, (33 * CPU_SIZEOF_POINTER)(sp)
92        csrr    a1, mepc
93        SREG    a1, (34 * CPU_SIZEOF_POINTER)(sp)
94
95        /* FIXME Only handle interrupts for now (MSB = 1) */
96        andi    a0, a0, 0xf
97
98        /* Get per-CPU control of current processor */
99        GET_SELF_CPU_CONTROL    s0
100
101        /* Increment interrupt nest and thread dispatch disable level */
102        lw      t0, PER_CPU_ISR_NEST_LEVEL(s0)
103        lw      t1, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(s0)
104        addi    t2, t0, 1
105        addi    t1, t1, 1
106        sw      t2, PER_CPU_ISR_NEST_LEVEL(s0)
107        sw      t1, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(s0)
108
109        /* Save interrupted task stack pointer */
110        addi    t4, sp, 36 * CPU_SIZEOF_POINTER
111        SREG    t4, (2 * CPU_SIZEOF_POINTER)(sp)
112
113        /* Keep sp (Exception frame address) in s1 */
114        mv      s1, sp
115
116        /* Call the exception handler from vector table */
117
118        /* First function arg for C handler is vector number,
119                * and the second is a pointer to exception frame.
120                * a0/mcause/vector number is already loaded above */
121        mv      a1, sp
122
123        /* calculate the offset */
124        la      t5, bsp_start_vector_table_begin
125#if     __riscv_xlen == 32
126        slli    t6, a0, 2
127#else   /* xlen = 64 */
128        slli    t6, a0, 3
129#endif
130        add     t5, t5, t6
131        LREG    t5, (t5)
132
133        /* Switch to interrupt stack if necessary */
134        bnez    t0, .Linterrupt_stack_switch_done
135        LREG    sp, PER_CPU_INTERRUPT_STACK_HIGH(s0)
136.Linterrupt_stack_switch_done:
137
138        jalr    t5
139
140        /* Load some per-CPU variables */
141        lw      t0, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(s0)
142        lbu     t1, PER_CPU_DISPATCH_NEEDED(s0)
143        lw      t2, PER_CPU_ISR_DISPATCH_DISABLE(s0)
144        lw      t3, PER_CPU_ISR_NEST_LEVEL(s0)
145
146        /* Restore stack pointer */
147        mv      sp, s1
148
149        /* Decrement levels and determine thread dispatch state */
150        xor     t1, t1, t0
151        addi    t0, t0, -1
152        or      t1, t1, t0
153        or      t1, t1, t2
154        addi    t3, t3, -1
155
156        /* Store thread dispatch disable and ISR nest levels */
157        sw      t0, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(s0)
158        sw      t3, PER_CPU_ISR_NEST_LEVEL(s0)
159
160        /*
161         * Check thread dispatch necessary, ISR dispatch disable and thread
162         * dispatch disable level.
163         */
164        bnez    t1, .Lthread_dispatch_done
165
166.Ldo_thread_dispatch:
167
168        /* Set ISR dispatch disable and thread dispatch disable level to one */
169        li      t0, 1
170        sw      t0, PER_CPU_ISR_DISPATCH_DISABLE(s0)
171        sw      t0, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(s0)
172
173        /* Call _Thread_Do_dispatch(), this function will enable interrupts */
174        mv      a0, s0
175        li      a1, RISCV_MSTATUS_MIE
176        call    _Thread_Do_dispatch
177
178        /* Disable interrupts */
179        csrrc   zero, mstatus, RISCV_MSTATUS_MIE
180
181#ifdef RTEMS_SMP
182        GET_SELF_CPU_CONTROL    s0
183#endif
184
185        /* Check if we have to do the thread dispatch again */
186        lbu     t0, PER_CPU_DISPATCH_NEEDED(s0)
187        bnez    t0, .Ldo_thread_dispatch
188
189        /* We are done with thread dispatching */
190        sw      zero, PER_CPU_ISR_DISPATCH_DISABLE(s0)
191
192.Lthread_dispatch_done:
193
194        LREG    x1, (1 * CPU_SIZEOF_POINTER)(sp)
195        /* Skip sp/x2 */
196        LREG    x3, (3 * CPU_SIZEOF_POINTER)(sp)
197        LREG    x4, (4 * CPU_SIZEOF_POINTER)(sp)
198        LREG    x5, (5 * CPU_SIZEOF_POINTER)(sp)
199        LREG    x6, (6 * CPU_SIZEOF_POINTER)(sp)
200        LREG    x7, (7 * CPU_SIZEOF_POINTER)(sp)
201        LREG    x8, (8 * CPU_SIZEOF_POINTER)(sp)
202        LREG    x9, (9 * CPU_SIZEOF_POINTER)(sp)
203        LREG    x10, (10 * CPU_SIZEOF_POINTER)(sp)
204        LREG    x11, (11 * CPU_SIZEOF_POINTER)(sp)
205        LREG    x12, (12 * CPU_SIZEOF_POINTER)(sp)
206        LREG    x13, (13 * CPU_SIZEOF_POINTER)(sp)
207        LREG    x14, (14 * CPU_SIZEOF_POINTER)(sp)
208        LREG    x15, (15 * CPU_SIZEOF_POINTER)(sp)
209        LREG    x16, (16 * CPU_SIZEOF_POINTER)(sp)
210        LREG    x17, (17 * CPU_SIZEOF_POINTER)(sp)
211        LREG    x18, (18 * CPU_SIZEOF_POINTER)(sp)
212        LREG    x19, (19 * CPU_SIZEOF_POINTER)(sp)
213        LREG    x20, (20 * CPU_SIZEOF_POINTER)(sp)
214        LREG    x21, (21 * CPU_SIZEOF_POINTER)(sp)
215        LREG    x22, (22 * CPU_SIZEOF_POINTER)(sp)
216        LREG    x23, (23 * CPU_SIZEOF_POINTER)(sp)
217        LREG    x24, (24 * CPU_SIZEOF_POINTER)(sp)
218        LREG    x25, (25 * CPU_SIZEOF_POINTER)(sp)
219        LREG    x26, (26 * CPU_SIZEOF_POINTER)(sp)
220        LREG    x27, (27 * CPU_SIZEOF_POINTER)(sp)
221        LREG    x28, (28 * CPU_SIZEOF_POINTER)(sp)
222        LREG    x29, (29 * CPU_SIZEOF_POINTER)(sp)
223        LREG    x30, (30 * CPU_SIZEOF_POINTER)(sp)
224
225        /* Load mstatus */
226        LREG    x31, (32 * CPU_SIZEOF_POINTER)(sp)
227        csrw    mstatus, x31
228        /* Load mepc */
229        LREG    x31, (34 * CPU_SIZEOF_POINTER)(sp)
230        csrw    mepc, x31
231
232        LREG    x31, (31 * CPU_SIZEOF_POINTER)(sp)
233
234        /* Unwind exception frame */
235        addi    sp, sp, 36 * CPU_SIZEOF_POINTER
236
237        mret
Note: See TracBrowser for help on using the repository browser.