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