xref: /freebsd/sys/riscv/riscv/exception.S (revision 753bcca4)
128029b68SRuslan Bukin/*-
2157654d0SRuslan Bukin * Copyright (c) 2015-2018 Ruslan Bukin <br@bsdpad.com>
328029b68SRuslan Bukin * All rights reserved.
428029b68SRuslan Bukin *
528029b68SRuslan Bukin * Portions of this software were developed by SRI International and the
628029b68SRuslan Bukin * University of Cambridge Computer Laboratory under DARPA/AFRL contract
728029b68SRuslan Bukin * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
828029b68SRuslan Bukin *
928029b68SRuslan Bukin * Portions of this software were developed by the University of Cambridge
1028029b68SRuslan Bukin * Computer Laboratory as part of the CTSRD Project, with support from the
1128029b68SRuslan Bukin * UK Higher Education Innovation Fund (HEIF).
1228029b68SRuslan Bukin *
1328029b68SRuslan Bukin * Redistribution and use in source and binary forms, with or without
1428029b68SRuslan Bukin * modification, are permitted provided that the following conditions
1528029b68SRuslan Bukin * are met:
1628029b68SRuslan Bukin * 1. Redistributions of source code must retain the above copyright
1728029b68SRuslan Bukin *    notice, this list of conditions and the following disclaimer.
1828029b68SRuslan Bukin * 2. Redistributions in binary form must reproduce the above copyright
1928029b68SRuslan Bukin *    notice, this list of conditions and the following disclaimer in the
2028029b68SRuslan Bukin *    documentation and/or other materials provided with the distribution.
2128029b68SRuslan Bukin *
2228029b68SRuslan Bukin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2328029b68SRuslan Bukin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2428029b68SRuslan Bukin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2528029b68SRuslan Bukin * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2628029b68SRuslan Bukin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2728029b68SRuslan Bukin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2828029b68SRuslan Bukin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2928029b68SRuslan Bukin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3028029b68SRuslan Bukin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3128029b68SRuslan Bukin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3228029b68SRuslan Bukin * SUCH DAMAGE.
3328029b68SRuslan Bukin */
3428029b68SRuslan Bukin
3528029b68SRuslan Bukin#include <machine/asm.h>
3628029b68SRuslan Bukin__FBSDID("$FreeBSD$");
3728029b68SRuslan Bukin
38fc2a8776SEd Maste#include "assym.inc"
3928029b68SRuslan Bukin
4028029b68SRuslan Bukin#include <machine/trap.h>
4128029b68SRuslan Bukin#include <machine/riscvreg.h>
4228029b68SRuslan Bukin
43da8944d9SJessica Clarke.macro save_registers mode
444d50647dSRuslan Bukin	addi	sp, sp, -(TF_SIZE)
4528029b68SRuslan Bukin
4628029b68SRuslan Bukin	sd	ra, (TF_RA)(sp)
4728029b68SRuslan Bukin
48da8944d9SJessica Clarke.if \mode == 0	/* We came from userspace. */
494d50647dSRuslan Bukin	sd	gp, (TF_GP)(sp)
506ae48dd8SMitchell Horne.option push
516ae48dd8SMitchell Horne.option norelax
526ae48dd8SMitchell Horne	/* Load the kernel's global pointer */
536ae48dd8SMitchell Horne	la	gp, __global_pointer$
546ae48dd8SMitchell Horne.option pop
556ae48dd8SMitchell Horne
566ae48dd8SMitchell Horne	/* Load our pcpu */
576ae48dd8SMitchell Horne	sd	tp, (TF_TP)(sp)
586ae48dd8SMitchell Horne	ld	tp, (TF_SIZE)(sp)
594d50647dSRuslan Bukin.endif
604d50647dSRuslan Bukin
6128029b68SRuslan Bukin	sd	t0, (TF_T + 0 * 8)(sp)
6228029b68SRuslan Bukin	sd	t1, (TF_T + 1 * 8)(sp)
6328029b68SRuslan Bukin	sd	t2, (TF_T + 2 * 8)(sp)
6428029b68SRuslan Bukin	sd	t3, (TF_T + 3 * 8)(sp)
6528029b68SRuslan Bukin	sd	t4, (TF_T + 4 * 8)(sp)
6628029b68SRuslan Bukin	sd	t5, (TF_T + 5 * 8)(sp)
6728029b68SRuslan Bukin	sd	t6, (TF_T + 6 * 8)(sp)
6828029b68SRuslan Bukin
6928029b68SRuslan Bukin	sd	s0, (TF_S + 0 * 8)(sp)
7028029b68SRuslan Bukin	sd	s1, (TF_S + 1 * 8)(sp)
7128029b68SRuslan Bukin	sd	s2, (TF_S + 2 * 8)(sp)
7228029b68SRuslan Bukin	sd	s3, (TF_S + 3 * 8)(sp)
7328029b68SRuslan Bukin	sd	s4, (TF_S + 4 * 8)(sp)
7428029b68SRuslan Bukin	sd	s5, (TF_S + 5 * 8)(sp)
7528029b68SRuslan Bukin	sd	s6, (TF_S + 6 * 8)(sp)
7628029b68SRuslan Bukin	sd	s7, (TF_S + 7 * 8)(sp)
7728029b68SRuslan Bukin	sd	s8, (TF_S + 8 * 8)(sp)
7828029b68SRuslan Bukin	sd	s9, (TF_S + 9 * 8)(sp)
7928029b68SRuslan Bukin	sd	s10, (TF_S + 10 * 8)(sp)
8028029b68SRuslan Bukin	sd	s11, (TF_S + 11 * 8)(sp)
8128029b68SRuslan Bukin
8228029b68SRuslan Bukin	sd	a0, (TF_A + 0 * 8)(sp)
8328029b68SRuslan Bukin	sd	a1, (TF_A + 1 * 8)(sp)
8428029b68SRuslan Bukin	sd	a2, (TF_A + 2 * 8)(sp)
8528029b68SRuslan Bukin	sd	a3, (TF_A + 3 * 8)(sp)
8628029b68SRuslan Bukin	sd	a4, (TF_A + 4 * 8)(sp)
8728029b68SRuslan Bukin	sd	a5, (TF_A + 5 * 8)(sp)
8828029b68SRuslan Bukin	sd	a6, (TF_A + 6 * 8)(sp)
8928029b68SRuslan Bukin	sd	a7, (TF_A + 7 * 8)(sp)
9028029b68SRuslan Bukin
91da8944d9SJessica Clarke.if \mode == 1
9228029b68SRuslan Bukin	/* Store kernel sp */
93892933d0SRuslan Bukin	li	t1, TF_SIZE
94892933d0SRuslan Bukin	add	t0, sp, t1
95892933d0SRuslan Bukin	sd	t0, (TF_SP)(sp)
9628029b68SRuslan Bukin.else
9728029b68SRuslan Bukin	/* Store user sp */
9828029b68SRuslan Bukin	csrr	t0, sscratch
9928029b68SRuslan Bukin	sd	t0, (TF_SP)(sp)
10028029b68SRuslan Bukin.endif
10128029b68SRuslan Bukin	li	t0, 0
10228029b68SRuslan Bukin	csrw	sscratch, t0
10328029b68SRuslan Bukin	csrr	t0, sepc
10428029b68SRuslan Bukin	sd	t0, (TF_SEPC)(sp)
10528029b68SRuslan Bukin	csrr	t0, sstatus
10628029b68SRuslan Bukin	sd	t0, (TF_SSTATUS)(sp)
107753bcca4SJohn Baldwin.if \mode == 1
108753bcca4SJohn Baldwin	/* Disable user address access for supervisor mode exceptions. */
109753bcca4SJohn Baldwin	li	t0, SSTATUS_SUM
110753bcca4SJohn Baldwin	csrc	sstatus, t0
111753bcca4SJohn Baldwin.endif
11253941c0aSMark Johnston	csrr	t0, stval
11353941c0aSMark Johnston	sd	t0, (TF_STVAL)(sp)
11428029b68SRuslan Bukin	csrr	t0, scause
11528029b68SRuslan Bukin	sd	t0, (TF_SCAUSE)(sp)
11628029b68SRuslan Bukin.endm
11728029b68SRuslan Bukin
118da8944d9SJessica Clarke.macro load_registers mode
11928029b68SRuslan Bukin	ld	t0, (TF_SSTATUS)(sp)
120da8944d9SJessica Clarke.if \mode == 0
121157654d0SRuslan Bukin	/* Ensure user interrupts will be enabled on eret */
122157654d0SRuslan Bukin	li	t1, SSTATUS_SPIE
12398f50c44SRuslan Bukin	or	t0, t0, t1
12428029b68SRuslan Bukin.else
12528029b68SRuslan Bukin	/*
12628029b68SRuslan Bukin	 * Disable interrupts for supervisor mode exceptions.
12728029b68SRuslan Bukin	 * For user mode exceptions we have already done this
12828029b68SRuslan Bukin	 * in do_ast.
12928029b68SRuslan Bukin	 */
13098f50c44SRuslan Bukin	li	t1, ~SSTATUS_SIE
13128029b68SRuslan Bukin	and	t0, t0, t1
13228029b68SRuslan Bukin.endif
13328029b68SRuslan Bukin	csrw	sstatus, t0
13428029b68SRuslan Bukin
13528029b68SRuslan Bukin	ld	t0, (TF_SEPC)(sp)
13628029b68SRuslan Bukin	csrw	sepc, t0
13728029b68SRuslan Bukin
138da8944d9SJessica Clarke.if \mode == 0
1394d50647dSRuslan Bukin	/* We go to userspace. Load user sp */
14028029b68SRuslan Bukin	ld	t0, (TF_SP)(sp)
14128029b68SRuslan Bukin	csrw	sscratch, t0
1424d50647dSRuslan Bukin
1436ae48dd8SMitchell Horne	/* Store our pcpu */
1446ae48dd8SMitchell Horne	sd	tp, (TF_SIZE)(sp)
1456ae48dd8SMitchell Horne	ld	tp, (TF_TP)(sp)
1466ae48dd8SMitchell Horne
1476ae48dd8SMitchell Horne	/* And restore the user's global pointer */
1484d50647dSRuslan Bukin	ld	gp, (TF_GP)(sp)
14928029b68SRuslan Bukin.endif
15028029b68SRuslan Bukin
15128029b68SRuslan Bukin	ld	ra, (TF_RA)(sp)
15228029b68SRuslan Bukin
15328029b68SRuslan Bukin	ld	t0, (TF_T + 0 * 8)(sp)
15428029b68SRuslan Bukin	ld	t1, (TF_T + 1 * 8)(sp)
15528029b68SRuslan Bukin	ld	t2, (TF_T + 2 * 8)(sp)
15628029b68SRuslan Bukin	ld	t3, (TF_T + 3 * 8)(sp)
15728029b68SRuslan Bukin	ld	t4, (TF_T + 4 * 8)(sp)
15828029b68SRuslan Bukin	ld	t5, (TF_T + 5 * 8)(sp)
15928029b68SRuslan Bukin	ld	t6, (TF_T + 6 * 8)(sp)
16028029b68SRuslan Bukin
16128029b68SRuslan Bukin	ld	s0, (TF_S + 0 * 8)(sp)
16228029b68SRuslan Bukin	ld	s1, (TF_S + 1 * 8)(sp)
16328029b68SRuslan Bukin	ld	s2, (TF_S + 2 * 8)(sp)
16428029b68SRuslan Bukin	ld	s3, (TF_S + 3 * 8)(sp)
16528029b68SRuslan Bukin	ld	s4, (TF_S + 4 * 8)(sp)
16628029b68SRuslan Bukin	ld	s5, (TF_S + 5 * 8)(sp)
16728029b68SRuslan Bukin	ld	s6, (TF_S + 6 * 8)(sp)
16828029b68SRuslan Bukin	ld	s7, (TF_S + 7 * 8)(sp)
16928029b68SRuslan Bukin	ld	s8, (TF_S + 8 * 8)(sp)
17028029b68SRuslan Bukin	ld	s9, (TF_S + 9 * 8)(sp)
17128029b68SRuslan Bukin	ld	s10, (TF_S + 10 * 8)(sp)
17228029b68SRuslan Bukin	ld	s11, (TF_S + 11 * 8)(sp)
17328029b68SRuslan Bukin
17428029b68SRuslan Bukin	ld	a0, (TF_A + 0 * 8)(sp)
17528029b68SRuslan Bukin	ld	a1, (TF_A + 1 * 8)(sp)
17628029b68SRuslan Bukin	ld	a2, (TF_A + 2 * 8)(sp)
17728029b68SRuslan Bukin	ld	a3, (TF_A + 3 * 8)(sp)
17828029b68SRuslan Bukin	ld	a4, (TF_A + 4 * 8)(sp)
17928029b68SRuslan Bukin	ld	a5, (TF_A + 5 * 8)(sp)
18028029b68SRuslan Bukin	ld	a6, (TF_A + 6 * 8)(sp)
18128029b68SRuslan Bukin	ld	a7, (TF_A + 7 * 8)(sp)
18228029b68SRuslan Bukin
1834d50647dSRuslan Bukin	addi	sp, sp, (TF_SIZE)
18428029b68SRuslan Bukin.endm
18528029b68SRuslan Bukin
18628029b68SRuslan Bukin.macro	do_ast
18728029b68SRuslan Bukin	/* Disable interrupts */
18828029b68SRuslan Bukin	csrr	a4, sstatus
18928029b68SRuslan Bukin1:
19098f50c44SRuslan Bukin	csrci	sstatus, (SSTATUS_SIE)
19128029b68SRuslan Bukin
1926ae48dd8SMitchell Horne	ld	a1, PC_CURTHREAD(tp)
19328029b68SRuslan Bukin	lw	a2, TD_FLAGS(a1)
19428029b68SRuslan Bukin
19528029b68SRuslan Bukin	li	a3, (TDF_ASTPENDING|TDF_NEEDRESCHED)
19628029b68SRuslan Bukin	and	a2, a2, a3
19728029b68SRuslan Bukin	beqz	a2, 2f
19828029b68SRuslan Bukin
19928029b68SRuslan Bukin	/* Restore interrupts */
20098f50c44SRuslan Bukin	andi	a4, a4, (SSTATUS_SIE)
20128029b68SRuslan Bukin	csrs	sstatus, a4
20228029b68SRuslan Bukin
20328029b68SRuslan Bukin	/* Handle the ast */
20428029b68SRuslan Bukin	mv	a0, sp
20528029b68SRuslan Bukin	call	_C_LABEL(ast)
20628029b68SRuslan Bukin
20728029b68SRuslan Bukin	/* Re-check for new ast scheduled */
20828029b68SRuslan Bukin	j	1b
20928029b68SRuslan Bukin2:
21028029b68SRuslan Bukin.endm
21128029b68SRuslan Bukin
21298f50c44SRuslan BukinENTRY(cpu_exception_handler)
21398f50c44SRuslan Bukin	csrrw	sp, sscratch, sp
21498f50c44SRuslan Bukin	beqz	sp, 1f
21598f50c44SRuslan Bukin	/* User mode detected */
21698f50c44SRuslan Bukin	j	cpu_exception_handler_user
21798f50c44SRuslan Bukin1:
21898f50c44SRuslan Bukin	/* Supervisor mode detected */
21998f50c44SRuslan Bukin	csrrw	sp, sscratch, sp
22098f50c44SRuslan Bukin	j	cpu_exception_handler_supervisor
22198f50c44SRuslan BukinEND(cpu_exception_handler)
22298f50c44SRuslan Bukin
22328029b68SRuslan BukinENTRY(cpu_exception_handler_supervisor)
22428029b68SRuslan Bukin	save_registers 1
22528029b68SRuslan Bukin	mv	a0, sp
22628029b68SRuslan Bukin	call	_C_LABEL(do_trap_supervisor)
22728029b68SRuslan Bukin	load_registers 1
22898f50c44SRuslan Bukin	sret
22928029b68SRuslan BukinEND(cpu_exception_handler_supervisor)
23028029b68SRuslan Bukin
23128029b68SRuslan BukinENTRY(cpu_exception_handler_user)
23228029b68SRuslan Bukin	save_registers 0
23328029b68SRuslan Bukin	mv	a0, sp
23428029b68SRuslan Bukin	call	_C_LABEL(do_trap_user)
23528029b68SRuslan Bukin	do_ast
23628029b68SRuslan Bukin	load_registers 0
23728029b68SRuslan Bukin	csrrw	sp, sscratch, sp
23898f50c44SRuslan Bukin	sret
23928029b68SRuslan BukinEND(cpu_exception_handler_user)
240