xref: /freebsd/sys/riscv/riscv/exception.S (revision b00ab754)
1/*-
2 * Copyright (c) 2015-2017 Ruslan Bukin <br@bsdpad.com>
3 * All rights reserved.
4 *
5 * Portions of this software were developed by SRI International and the
6 * University of Cambridge Computer Laboratory under DARPA/AFRL contract
7 * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
8 *
9 * Portions of this software were developed by the University of Cambridge
10 * Computer Laboratory as part of the CTSRD Project, with support from the
11 * UK Higher Education Innovation Fund (HEIF).
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 *    notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 *    notice, this list of conditions and the following disclaimer in the
20 *    documentation and/or other materials provided with the distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#include <machine/asm.h>
36__FBSDID("$FreeBSD$");
37
38#include "assym.inc"
39
40#include <machine/trap.h>
41#include <machine/riscvreg.h>
42
43.macro save_registers el
44	addi	sp, sp, -(TF_SIZE)
45
46	sd	ra, (TF_RA)(sp)
47	sd	tp, (TF_TP)(sp)
48
49.if \el == 0	/* We came from userspace. Load our pcpu */
50	sd	gp, (TF_GP)(sp)
51	ld	gp, (TF_SIZE)(sp)
52.endif
53
54	sd	t0, (TF_T + 0 * 8)(sp)
55	sd	t1, (TF_T + 1 * 8)(sp)
56	sd	t2, (TF_T + 2 * 8)(sp)
57	sd	t3, (TF_T + 3 * 8)(sp)
58	sd	t4, (TF_T + 4 * 8)(sp)
59	sd	t5, (TF_T + 5 * 8)(sp)
60	sd	t6, (TF_T + 6 * 8)(sp)
61
62	sd	s0, (TF_S + 0 * 8)(sp)
63	sd	s1, (TF_S + 1 * 8)(sp)
64	sd	s2, (TF_S + 2 * 8)(sp)
65	sd	s3, (TF_S + 3 * 8)(sp)
66	sd	s4, (TF_S + 4 * 8)(sp)
67	sd	s5, (TF_S + 5 * 8)(sp)
68	sd	s6, (TF_S + 6 * 8)(sp)
69	sd	s7, (TF_S + 7 * 8)(sp)
70	sd	s8, (TF_S + 8 * 8)(sp)
71	sd	s9, (TF_S + 9 * 8)(sp)
72	sd	s10, (TF_S + 10 * 8)(sp)
73	sd	s11, (TF_S + 11 * 8)(sp)
74
75	sd	a0, (TF_A + 0 * 8)(sp)
76	sd	a1, (TF_A + 1 * 8)(sp)
77	sd	a2, (TF_A + 2 * 8)(sp)
78	sd	a3, (TF_A + 3 * 8)(sp)
79	sd	a4, (TF_A + 4 * 8)(sp)
80	sd	a5, (TF_A + 5 * 8)(sp)
81	sd	a6, (TF_A + 6 * 8)(sp)
82	sd	a7, (TF_A + 7 * 8)(sp)
83
84#if 0
85	/* XXX: temporary test: spin if stack is not kernel one */
86.if \el == 1	/* kernel */
87	mv	t0, sp
88	srli	t0, t0, 63
891:
90	beqz	t0, 1b
91.endif
92#endif
93
94.if \el == 1
95	/* Store kernel sp */
96	li	t1, TF_SIZE
97	add	t0, sp, t1
98	sd	t0, (TF_SP)(sp)
99.else
100	/* Store user sp */
101	csrr	t0, sscratch
102	sd	t0, (TF_SP)(sp)
103.endif
104	li	t0, 0
105	csrw	sscratch, t0
106	csrr	t0, sepc
107	sd	t0, (TF_SEPC)(sp)
108	csrr	t0, sstatus
109	sd	t0, (TF_SSTATUS)(sp)
110	csrr	t0, sbadaddr
111	sd	t0, (TF_SBADADDR)(sp)
112	csrr	t0, scause
113	sd	t0, (TF_SCAUSE)(sp)
114.endm
115
116.macro load_registers el
117	ld	t0, (TF_SSTATUS)(sp)
118.if \el == 0
119	/*
120	 * Ensure user interrupts will be enabled on eret
121	 * and supervisor mode can access userspace on trap.
122	 */
123	li	t1, (SSTATUS_SPIE | SSTATUS_SUM)
124	or	t0, t0, t1
125.else
126	/*
127	 * Disable interrupts for supervisor mode exceptions.
128	 * For user mode exceptions we have already done this
129	 * in do_ast.
130	 */
131	li	t1, ~SSTATUS_SIE
132	and	t0, t0, t1
133.endif
134	csrw	sstatus, t0
135
136	ld	t0, (TF_SEPC)(sp)
137	csrw	sepc, t0
138
139.if \el == 0
140	/* We go to userspace. Load user sp */
141	ld	t0, (TF_SP)(sp)
142	csrw	sscratch, t0
143
144	/* And store our pcpu */
145	sd	gp, (TF_SIZE)(sp)
146	ld	gp, (TF_GP)(sp)
147.endif
148
149	ld	ra, (TF_RA)(sp)
150	ld	tp, (TF_TP)(sp)
151
152	ld	t0, (TF_T + 0 * 8)(sp)
153	ld	t1, (TF_T + 1 * 8)(sp)
154	ld	t2, (TF_T + 2 * 8)(sp)
155	ld	t3, (TF_T + 3 * 8)(sp)
156	ld	t4, (TF_T + 4 * 8)(sp)
157	ld	t5, (TF_T + 5 * 8)(sp)
158	ld	t6, (TF_T + 6 * 8)(sp)
159
160	ld	s0, (TF_S + 0 * 8)(sp)
161	ld	s1, (TF_S + 1 * 8)(sp)
162	ld	s2, (TF_S + 2 * 8)(sp)
163	ld	s3, (TF_S + 3 * 8)(sp)
164	ld	s4, (TF_S + 4 * 8)(sp)
165	ld	s5, (TF_S + 5 * 8)(sp)
166	ld	s6, (TF_S + 6 * 8)(sp)
167	ld	s7, (TF_S + 7 * 8)(sp)
168	ld	s8, (TF_S + 8 * 8)(sp)
169	ld	s9, (TF_S + 9 * 8)(sp)
170	ld	s10, (TF_S + 10 * 8)(sp)
171	ld	s11, (TF_S + 11 * 8)(sp)
172
173	ld	a0, (TF_A + 0 * 8)(sp)
174	ld	a1, (TF_A + 1 * 8)(sp)
175	ld	a2, (TF_A + 2 * 8)(sp)
176	ld	a3, (TF_A + 3 * 8)(sp)
177	ld	a4, (TF_A + 4 * 8)(sp)
178	ld	a5, (TF_A + 5 * 8)(sp)
179	ld	a6, (TF_A + 6 * 8)(sp)
180	ld	a7, (TF_A + 7 * 8)(sp)
181
182	addi	sp, sp, (TF_SIZE)
183.endm
184
185.macro	do_ast
186	/* Disable interrupts */
187	csrr	a4, sstatus
1881:
189	csrci	sstatus, (SSTATUS_SIE)
190
191	ld	a1, PC_CURTHREAD(gp)
192	lw	a2, TD_FLAGS(a1)
193
194	li	a3, (TDF_ASTPENDING|TDF_NEEDRESCHED)
195	and	a2, a2, a3
196	beqz	a2, 2f
197
198	/* Restore interrupts */
199	andi	a4, a4, (SSTATUS_SIE)
200	csrs	sstatus, a4
201
202	/* Handle the ast */
203	mv	a0, sp
204	call	_C_LABEL(ast)
205
206	/* Re-check for new ast scheduled */
207	j	1b
2082:
209.endm
210
211ENTRY(cpu_exception_handler)
212	csrrw	sp, sscratch, sp
213	beqz	sp, 1f
214	/* User mode detected */
215	csrrw	sp, sscratch, sp
216	j	cpu_exception_handler_user
2171:
218	/* Supervisor mode detected */
219	csrrw	sp, sscratch, sp
220	j	cpu_exception_handler_supervisor
221END(cpu_exception_handler)
222
223ENTRY(cpu_exception_handler_supervisor)
224	save_registers 1
225	mv	a0, sp
226	call	_C_LABEL(do_trap_supervisor)
227	load_registers 1
228	sret
229END(cpu_exception_handler_supervisor)
230
231ENTRY(cpu_exception_handler_user)
232	csrrw	sp, sscratch, sp
233	save_registers 0
234	mv	a0, sp
235	call	_C_LABEL(do_trap_user)
236	do_ast
237	load_registers 0
238	csrrw	sp, sscratch, sp
239	sret
240END(cpu_exception_handler_user)
241