xref: /freebsd/sys/riscv/riscv/exception.S (revision 3b35d2a8)
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>
36fc2a8776SEd Maste#include "assym.inc"
3728029b68SRuslan Bukin
3828029b68SRuslan Bukin#include <machine/trap.h>
3928029b68SRuslan Bukin#include <machine/riscvreg.h>
4028029b68SRuslan Bukin
41da8944d9SJessica Clarke.macro save_registers mode
424d50647dSRuslan Bukin	addi	sp, sp, -(TF_SIZE)
4328029b68SRuslan Bukin
4428029b68SRuslan Bukin	sd	ra, (TF_RA)(sp)
453c6fb586SChristos Margiolis	sd	tp, (TF_TP)(sp)
463b35d2a8SJohn Baldwin	sd	gp, (TF_GP)(sp)
4728029b68SRuslan Bukin
48da8944d9SJessica Clarke.if \mode == 0	/* We came from userspace. */
496ae48dd8SMitchell Horne.option push
506ae48dd8SMitchell Horne.option norelax
516ae48dd8SMitchell Horne	/* Load the kernel's global pointer */
526ae48dd8SMitchell Horne	la	gp, __global_pointer$
536ae48dd8SMitchell Horne.option pop
546ae48dd8SMitchell Horne
556ae48dd8SMitchell Horne	/* Load our pcpu */
566ae48dd8SMitchell Horne	ld	tp, (TF_SIZE)(sp)
574d50647dSRuslan Bukin.endif
584d50647dSRuslan Bukin
5928029b68SRuslan Bukin	sd	t0, (TF_T + 0 * 8)(sp)
6028029b68SRuslan Bukin	sd	t1, (TF_T + 1 * 8)(sp)
6128029b68SRuslan Bukin	sd	t2, (TF_T + 2 * 8)(sp)
6228029b68SRuslan Bukin	sd	t3, (TF_T + 3 * 8)(sp)
6328029b68SRuslan Bukin	sd	t4, (TF_T + 4 * 8)(sp)
6428029b68SRuslan Bukin	sd	t5, (TF_T + 5 * 8)(sp)
6528029b68SRuslan Bukin	sd	t6, (TF_T + 6 * 8)(sp)
6628029b68SRuslan Bukin
6728029b68SRuslan Bukin	sd	s0, (TF_S + 0 * 8)(sp)
6828029b68SRuslan Bukin	sd	s1, (TF_S + 1 * 8)(sp)
6928029b68SRuslan Bukin	sd	s2, (TF_S + 2 * 8)(sp)
7028029b68SRuslan Bukin	sd	s3, (TF_S + 3 * 8)(sp)
7128029b68SRuslan Bukin	sd	s4, (TF_S + 4 * 8)(sp)
7228029b68SRuslan Bukin	sd	s5, (TF_S + 5 * 8)(sp)
7328029b68SRuslan Bukin	sd	s6, (TF_S + 6 * 8)(sp)
7428029b68SRuslan Bukin	sd	s7, (TF_S + 7 * 8)(sp)
7528029b68SRuslan Bukin	sd	s8, (TF_S + 8 * 8)(sp)
7628029b68SRuslan Bukin	sd	s9, (TF_S + 9 * 8)(sp)
7728029b68SRuslan Bukin	sd	s10, (TF_S + 10 * 8)(sp)
7828029b68SRuslan Bukin	sd	s11, (TF_S + 11 * 8)(sp)
7928029b68SRuslan Bukin
8028029b68SRuslan Bukin	sd	a0, (TF_A + 0 * 8)(sp)
8128029b68SRuslan Bukin	sd	a1, (TF_A + 1 * 8)(sp)
8228029b68SRuslan Bukin	sd	a2, (TF_A + 2 * 8)(sp)
8328029b68SRuslan Bukin	sd	a3, (TF_A + 3 * 8)(sp)
8428029b68SRuslan Bukin	sd	a4, (TF_A + 4 * 8)(sp)
8528029b68SRuslan Bukin	sd	a5, (TF_A + 5 * 8)(sp)
8628029b68SRuslan Bukin	sd	a6, (TF_A + 6 * 8)(sp)
8728029b68SRuslan Bukin	sd	a7, (TF_A + 7 * 8)(sp)
8828029b68SRuslan Bukin
89da8944d9SJessica Clarke.if \mode == 1
9028029b68SRuslan Bukin	/* Store kernel sp */
91892933d0SRuslan Bukin	li	t1, TF_SIZE
92892933d0SRuslan Bukin	add	t0, sp, t1
93892933d0SRuslan Bukin	sd	t0, (TF_SP)(sp)
9428029b68SRuslan Bukin.else
9528029b68SRuslan Bukin	/* Store user sp */
9628029b68SRuslan Bukin	csrr	t0, sscratch
9728029b68SRuslan Bukin	sd	t0, (TF_SP)(sp)
9828029b68SRuslan Bukin.endif
9928029b68SRuslan Bukin	li	t0, 0
10028029b68SRuslan Bukin	csrw	sscratch, t0
10128029b68SRuslan Bukin	csrr	t0, sepc
10228029b68SRuslan Bukin	sd	t0, (TF_SEPC)(sp)
10328029b68SRuslan Bukin	csrr	t0, sstatus
10428029b68SRuslan Bukin	sd	t0, (TF_SSTATUS)(sp)
105753bcca4SJohn Baldwin.if \mode == 1
106753bcca4SJohn Baldwin	/* Disable user address access for supervisor mode exceptions. */
107753bcca4SJohn Baldwin	li	t0, SSTATUS_SUM
108753bcca4SJohn Baldwin	csrc	sstatus, t0
109753bcca4SJohn Baldwin.endif
11053941c0aSMark Johnston	csrr	t0, stval
11153941c0aSMark Johnston	sd	t0, (TF_STVAL)(sp)
11228029b68SRuslan Bukin	csrr	t0, scause
11328029b68SRuslan Bukin	sd	t0, (TF_SCAUSE)(sp)
11428029b68SRuslan Bukin.endm
11528029b68SRuslan Bukin
116da8944d9SJessica Clarke.macro load_registers mode
11728029b68SRuslan Bukin	ld	t0, (TF_SSTATUS)(sp)
118da8944d9SJessica Clarke.if \mode == 0
119157654d0SRuslan Bukin	/* Ensure user interrupts will be enabled on eret */
120157654d0SRuslan Bukin	li	t1, SSTATUS_SPIE
12198f50c44SRuslan Bukin	or	t0, t0, t1
12228029b68SRuslan Bukin.else
12328029b68SRuslan Bukin	/*
12428029b68SRuslan Bukin	 * Disable interrupts for supervisor mode exceptions.
12528029b68SRuslan Bukin	 * For user mode exceptions we have already done this
12628029b68SRuslan Bukin	 * in do_ast.
12728029b68SRuslan Bukin	 */
12898f50c44SRuslan Bukin	li	t1, ~SSTATUS_SIE
12928029b68SRuslan Bukin	and	t0, t0, t1
13028029b68SRuslan Bukin.endif
13128029b68SRuslan Bukin	csrw	sstatus, t0
13228029b68SRuslan Bukin
13328029b68SRuslan Bukin	ld	t0, (TF_SEPC)(sp)
13428029b68SRuslan Bukin	csrw	sepc, t0
13528029b68SRuslan Bukin
136da8944d9SJessica Clarke.if \mode == 0
1374d50647dSRuslan Bukin	/* We go to userspace. Load user sp */
13828029b68SRuslan Bukin	ld	t0, (TF_SP)(sp)
13928029b68SRuslan Bukin	csrw	sscratch, t0
1404d50647dSRuslan Bukin
1416ae48dd8SMitchell Horne	/* Store our pcpu */
1426ae48dd8SMitchell Horne	sd	tp, (TF_SIZE)(sp)
1436ae48dd8SMitchell Horne	ld	tp, (TF_TP)(sp)
1446ae48dd8SMitchell Horne
1456ae48dd8SMitchell Horne	/* And restore the user's global pointer */
1464d50647dSRuslan Bukin	ld	gp, (TF_GP)(sp)
14728029b68SRuslan Bukin.endif
14828029b68SRuslan Bukin
14928029b68SRuslan Bukin	ld	ra, (TF_RA)(sp)
15028029b68SRuslan Bukin
15128029b68SRuslan Bukin	ld	t0, (TF_T + 0 * 8)(sp)
15228029b68SRuslan Bukin	ld	t1, (TF_T + 1 * 8)(sp)
15328029b68SRuslan Bukin	ld	t2, (TF_T + 2 * 8)(sp)
15428029b68SRuslan Bukin	ld	t3, (TF_T + 3 * 8)(sp)
15528029b68SRuslan Bukin	ld	t4, (TF_T + 4 * 8)(sp)
15628029b68SRuslan Bukin	ld	t5, (TF_T + 5 * 8)(sp)
15728029b68SRuslan Bukin	ld	t6, (TF_T + 6 * 8)(sp)
15828029b68SRuslan Bukin
15928029b68SRuslan Bukin	ld	s0, (TF_S + 0 * 8)(sp)
16028029b68SRuslan Bukin	ld	s1, (TF_S + 1 * 8)(sp)
16128029b68SRuslan Bukin	ld	s2, (TF_S + 2 * 8)(sp)
16228029b68SRuslan Bukin	ld	s3, (TF_S + 3 * 8)(sp)
16328029b68SRuslan Bukin	ld	s4, (TF_S + 4 * 8)(sp)
16428029b68SRuslan Bukin	ld	s5, (TF_S + 5 * 8)(sp)
16528029b68SRuslan Bukin	ld	s6, (TF_S + 6 * 8)(sp)
16628029b68SRuslan Bukin	ld	s7, (TF_S + 7 * 8)(sp)
16728029b68SRuslan Bukin	ld	s8, (TF_S + 8 * 8)(sp)
16828029b68SRuslan Bukin	ld	s9, (TF_S + 9 * 8)(sp)
16928029b68SRuslan Bukin	ld	s10, (TF_S + 10 * 8)(sp)
17028029b68SRuslan Bukin	ld	s11, (TF_S + 11 * 8)(sp)
17128029b68SRuslan Bukin
17228029b68SRuslan Bukin	ld	a0, (TF_A + 0 * 8)(sp)
17328029b68SRuslan Bukin	ld	a1, (TF_A + 1 * 8)(sp)
17428029b68SRuslan Bukin	ld	a2, (TF_A + 2 * 8)(sp)
17528029b68SRuslan Bukin	ld	a3, (TF_A + 3 * 8)(sp)
17628029b68SRuslan Bukin	ld	a4, (TF_A + 4 * 8)(sp)
17728029b68SRuslan Bukin	ld	a5, (TF_A + 5 * 8)(sp)
17828029b68SRuslan Bukin	ld	a6, (TF_A + 6 * 8)(sp)
17928029b68SRuslan Bukin	ld	a7, (TF_A + 7 * 8)(sp)
18028029b68SRuslan Bukin
1814d50647dSRuslan Bukin	addi	sp, sp, (TF_SIZE)
18228029b68SRuslan Bukin.endm
18328029b68SRuslan Bukin
18428029b68SRuslan Bukin.macro	do_ast
18528029b68SRuslan Bukin	/* Disable interrupts */
18628029b68SRuslan Bukin	csrr	a4, sstatus
18728029b68SRuslan Bukin1:
18898f50c44SRuslan Bukin	csrci	sstatus, (SSTATUS_SIE)
18928029b68SRuslan Bukin
1906ae48dd8SMitchell Horne	ld	a1, PC_CURTHREAD(tp)
191c6d31b83SKonstantin Belousov	lw	a2, TD_AST(a1)
19228029b68SRuslan Bukin
19328029b68SRuslan Bukin	beqz	a2, 2f
19428029b68SRuslan Bukin
19528029b68SRuslan Bukin	/* Restore interrupts */
19698f50c44SRuslan Bukin	andi	a4, a4, (SSTATUS_SIE)
19728029b68SRuslan Bukin	csrs	sstatus, a4
19828029b68SRuslan Bukin
19928029b68SRuslan Bukin	/* Handle the ast */
20028029b68SRuslan Bukin	mv	a0, sp
20128029b68SRuslan Bukin	call	_C_LABEL(ast)
20228029b68SRuslan Bukin
20328029b68SRuslan Bukin	/* Re-check for new ast scheduled */
20428029b68SRuslan Bukin	j	1b
20528029b68SRuslan Bukin2:
20628029b68SRuslan Bukin.endm
20728029b68SRuslan Bukin
20898f50c44SRuslan BukinENTRY(cpu_exception_handler)
20998f50c44SRuslan Bukin	csrrw	sp, sscratch, sp
21098f50c44SRuslan Bukin	beqz	sp, 1f
21198f50c44SRuslan Bukin	/* User mode detected */
21298f50c44SRuslan Bukin	j	cpu_exception_handler_user
21398f50c44SRuslan Bukin1:
21498f50c44SRuslan Bukin	/* Supervisor mode detected */
21598f50c44SRuslan Bukin	csrrw	sp, sscratch, sp
21698f50c44SRuslan Bukin	j	cpu_exception_handler_supervisor
21798f50c44SRuslan BukinEND(cpu_exception_handler)
21898f50c44SRuslan Bukin
21928029b68SRuslan BukinENTRY(cpu_exception_handler_supervisor)
22028029b68SRuslan Bukin	save_registers 1
22128029b68SRuslan Bukin	mv	a0, sp
22228029b68SRuslan Bukin	call	_C_LABEL(do_trap_supervisor)
22328029b68SRuslan Bukin	load_registers 1
22498f50c44SRuslan Bukin	sret
22528029b68SRuslan BukinEND(cpu_exception_handler_supervisor)
22628029b68SRuslan Bukin
22728029b68SRuslan BukinENTRY(cpu_exception_handler_user)
22828029b68SRuslan Bukin	save_registers 0
22928029b68SRuslan Bukin	mv	a0, sp
23028029b68SRuslan Bukin	call	_C_LABEL(do_trap_user)
23128029b68SRuslan Bukin	do_ast
23228029b68SRuslan Bukin	load_registers 0
23328029b68SRuslan Bukin	csrrw	sp, sscratch, sp
23498f50c44SRuslan Bukin	sret
23528029b68SRuslan BukinEND(cpu_exception_handler_user)
236