blob: d6a93b0ced17b0f811b0a8f68e5cb39e55e1cc5a [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Early initialization code for riscv
*/
#include <bits.h>
#include <mcall.h>
.macro restore_regs
# restore x registers
LOAD x1, 1 * REGBYTES(sp)
LOAD x3, 3 * REGBYTES(sp)
LOAD x4, 4 * REGBYTES(sp)
LOAD x5, 5 * REGBYTES(sp)
LOAD x6, 6 * REGBYTES(sp)
LOAD x7, 7 * REGBYTES(sp)
LOAD x8, 8 * REGBYTES(sp)
LOAD x9, 9 * REGBYTES(sp)
LOAD x10, 10 * REGBYTES(sp)
LOAD x11, 11 * REGBYTES(sp)
LOAD x12, 12 * REGBYTES(sp)
LOAD x13, 13 * REGBYTES(sp)
LOAD x14, 14 * REGBYTES(sp)
LOAD x15, 15 * REGBYTES(sp)
LOAD x16, 16 * REGBYTES(sp)
LOAD x17, 17 * REGBYTES(sp)
LOAD x18, 18 * REGBYTES(sp)
LOAD x19, 19 * REGBYTES(sp)
LOAD x20, 20 * REGBYTES(sp)
LOAD x21, 21 * REGBYTES(sp)
LOAD x22, 22 * REGBYTES(sp)
LOAD x23, 23 * REGBYTES(sp)
LOAD x24, 24 * REGBYTES(sp)
LOAD x25, 25 * REGBYTES(sp)
LOAD x26, 26 * REGBYTES(sp)
LOAD x27, 27 * REGBYTES(sp)
LOAD x28, 28 * REGBYTES(sp)
LOAD x29, 29 * REGBYTES(sp)
LOAD x30, 30 * REGBYTES(sp)
LOAD x31, 31 * REGBYTES(sp)
.endm
.macro save_tf
# save general purpose registers
# no point in saving x0 since it is always 0
STORE x1, 1 * REGBYTES(sp)
# x2 is our stack pointer and is saved further below
STORE x3, 3 * REGBYTES(sp)
STORE x4, 4 * REGBYTES(sp)
STORE x5, 5 * REGBYTES(sp)
STORE x6, 6 * REGBYTES(sp)
STORE x7, 7 * REGBYTES(sp)
STORE x8, 8 * REGBYTES(sp)
STORE x9, 9 * REGBYTES(sp)
STORE x10, 10 * REGBYTES(sp)
STORE x11, 11 * REGBYTES(sp)
STORE x12, 12 * REGBYTES(sp)
STORE x13, 13 * REGBYTES(sp)
STORE x14, 14 * REGBYTES(sp)
STORE x15, 15 * REGBYTES(sp)
STORE x16, 16 * REGBYTES(sp)
STORE x17, 17 * REGBYTES(sp)
STORE x18, 18 * REGBYTES(sp)
STORE x19, 19 * REGBYTES(sp)
STORE x20, 20 * REGBYTES(sp)
STORE x21, 21 * REGBYTES(sp)
STORE x22, 22 * REGBYTES(sp)
STORE x23, 23 * REGBYTES(sp)
STORE x24, 24 * REGBYTES(sp)
STORE x25, 25 * REGBYTES(sp)
STORE x26, 26 * REGBYTES(sp)
STORE x27, 27 * REGBYTES(sp)
STORE x28, 28 * REGBYTES(sp)
STORE x29, 29 * REGBYTES(sp)
STORE x30, 30 * REGBYTES(sp)
STORE x31, 31 * REGBYTES(sp)
# get sr, epc, badvaddr, cause
csrr t0, mscratch
bnez t0, 1f # t0 == 0, trap come from coreboot
# t0 != 0, t0 is saved old sp
add t0, sp, MENTRY_FRAME_SIZE
1:
csrr s0, mstatus
csrr t1, mepc
csrr t2, mtval
csrr t3, mcause
STORE t0, 2 * REGBYTES(sp)
STORE s0, 32 * REGBYTES(sp)
STORE t1, 33 * REGBYTES(sp)
STORE t2, 34 * REGBYTES(sp)
STORE t3, 35 * REGBYTES(sp)
# get faulting insn, if it wasn't a fetch-related trap
li x5, -1
STORE x5, 36 * REGBYTES(sp)
.endm
.text
.global trap_entry
.align 2 # four byte alignment, as required by mtvec
trap_entry:
# mscratch is initialized to 0
# when exiting coreboot, write sp to mscratch
# before jumping to m-mode firmware we always set trap vector to the entry point of the
# payload and we don't care about mscratch anymore. mscratch is only ever used as
# exception stack if whatever coreboot jumps to is in s-mode.
#TODO we could check MPP field in mstatus to see if come from unpriviledged code. That
# way we could still use mscratch for other purposes inside the code base.
#TODO In case we got called from s-mode firmware we need to protect our stack and trap
# handler with a PMP region.
csrrw sp, mscratch, sp
# sp == 0 => trap came from coreboot
# sp != 0 => trap came from s-mode payload
bnez sp, 1f
csrrw sp, mscratch, sp
1:
addi sp, sp, -MENTRY_FRAME_SIZE
save_tf
mv a0,sp # put trapframe as first argument
LOAD t0, trap_handler
jalr t0
trap_return:
restore_regs
addi sp, sp, MENTRY_FRAME_SIZE
# restore original stack pointer (either sp or mscratch)
csrrw sp, mscratch, sp
bnez sp, 1f
csrrw sp, mscratch, sp
1:
mret