1/* SPDX-License-Identifier: GPL-2.0-only */ 2/* 3 * Early initialization code for riscv 4 */ 5 6#include <bits.h> 7#include <mcall.h> 8 9.macro restore_regs 10 # restore x registers 11 LOAD x1, 1 * REGBYTES(sp) 12 LOAD x3, 3 * REGBYTES(sp) 13 LOAD x4, 4 * REGBYTES(sp) 14 LOAD x5, 5 * REGBYTES(sp) 15 LOAD x6, 6 * REGBYTES(sp) 16 LOAD x7, 7 * REGBYTES(sp) 17 LOAD x8, 8 * REGBYTES(sp) 18 LOAD x9, 9 * REGBYTES(sp) 19 LOAD x10, 10 * REGBYTES(sp) 20 LOAD x11, 11 * REGBYTES(sp) 21 LOAD x12, 12 * REGBYTES(sp) 22 LOAD x13, 13 * REGBYTES(sp) 23 LOAD x14, 14 * REGBYTES(sp) 24 LOAD x15, 15 * REGBYTES(sp) 25 LOAD x16, 16 * REGBYTES(sp) 26 LOAD x17, 17 * REGBYTES(sp) 27 LOAD x18, 18 * REGBYTES(sp) 28 LOAD x19, 19 * REGBYTES(sp) 29 LOAD x20, 20 * REGBYTES(sp) 30 LOAD x21, 21 * REGBYTES(sp) 31 LOAD x22, 22 * REGBYTES(sp) 32 LOAD x23, 23 * REGBYTES(sp) 33 LOAD x24, 24 * REGBYTES(sp) 34 LOAD x25, 25 * REGBYTES(sp) 35 LOAD x26, 26 * REGBYTES(sp) 36 LOAD x27, 27 * REGBYTES(sp) 37 LOAD x28, 28 * REGBYTES(sp) 38 LOAD x29, 29 * REGBYTES(sp) 39 LOAD x30, 30 * REGBYTES(sp) 40 LOAD x31, 31 * REGBYTES(sp) 41.endm 42 43.macro save_tf 44 # save general purpose registers 45 # no point in saving x0 since it is always 0 46 STORE x1, 1 * REGBYTES(sp) 47 # x2 is our stack pointer and is saved further below 48 STORE x3, 3 * REGBYTES(sp) 49 STORE x4, 4 * REGBYTES(sp) 50 STORE x5, 5 * REGBYTES(sp) 51 STORE x6, 6 * REGBYTES(sp) 52 STORE x7, 7 * REGBYTES(sp) 53 STORE x8, 8 * REGBYTES(sp) 54 STORE x9, 9 * REGBYTES(sp) 55 STORE x10, 10 * REGBYTES(sp) 56 STORE x11, 11 * REGBYTES(sp) 57 STORE x12, 12 * REGBYTES(sp) 58 STORE x13, 13 * REGBYTES(sp) 59 STORE x14, 14 * REGBYTES(sp) 60 STORE x15, 15 * REGBYTES(sp) 61 STORE x16, 16 * REGBYTES(sp) 62 STORE x17, 17 * REGBYTES(sp) 63 STORE x18, 18 * REGBYTES(sp) 64 STORE x19, 19 * REGBYTES(sp) 65 STORE x20, 20 * REGBYTES(sp) 66 STORE x21, 21 * REGBYTES(sp) 67 STORE x22, 22 * REGBYTES(sp) 68 STORE x23, 23 * REGBYTES(sp) 69 STORE x24, 24 * REGBYTES(sp) 70 STORE x25, 25 * REGBYTES(sp) 71 STORE x26, 26 * REGBYTES(sp) 72 STORE x27, 27 * REGBYTES(sp) 73 STORE x28, 28 * REGBYTES(sp) 74 STORE x29, 29 * REGBYTES(sp) 75 STORE x30, 30 * REGBYTES(sp) 76 STORE x31, 31 * REGBYTES(sp) 77 78 # get sr, epc, badvaddr, cause 79 csrr t0, mscratch 80 bnez t0, 1f # t0 == 0, trap come from coreboot 81 # t0 != 0, t0 is saved old sp 82 add t0, sp, MENTRY_FRAME_SIZE 831: 84 csrr s0, mstatus 85 csrr t1, mepc 86 csrr t2, mtval 87 csrr t3, mcause 88 STORE t0, 2 * REGBYTES(sp) 89 STORE s0, 32 * REGBYTES(sp) 90 STORE t1, 33 * REGBYTES(sp) 91 STORE t2, 34 * REGBYTES(sp) 92 STORE t3, 35 * REGBYTES(sp) 93 94 # get faulting insn, if it wasn't a fetch-related trap 95 li x5, -1 96 STORE x5, 36 * REGBYTES(sp) 97.endm 98 99 .text 100 .global trap_entry 101 .align 2 # four byte alignment, as required by mtvec 102trap_entry: 103 # mscratch is initialized to 0 104 # when exiting coreboot, write sp to mscratch 105 # before jumping to m-mode firmware we always set trap vector to the entry point of the 106 # payload and we don't care about mscratch anymore. mscratch is only ever used as 107 # exception stack if whatever coreboot jumps to is in s-mode. 108 #TODO we could check MPP field in mstatus to see if come from unpriviledged code. That 109 # way we could still use mscratch for other purposes inside the code base. 110 #TODO In case we got called from s-mode firmware we need to protect our stack and trap 111 # handler with a PMP region. 112 csrrw sp, mscratch, sp 113 # sp == 0 => trap came from coreboot 114 # sp != 0 => trap came from s-mode payload 115 bnez sp, 1f 116 csrrw sp, mscratch, sp 1171: 118 addi sp, sp, -MENTRY_FRAME_SIZE 119 save_tf 120 121 mv a0,sp # put trapframe as first argument 122 123 LOAD t0, trap_handler 124 jalr t0 125 126trap_return: 127 restore_regs 128 addi sp, sp, MENTRY_FRAME_SIZE 129 130 # restore original stack pointer (either sp or mscratch) 131 csrrw sp, mscratch, sp 132 bnez sp, 1f 133 csrrw sp, mscratch, sp 1341: 135 mret 136