|
|
|
|
// See LICENSE for license details.
|
|
|
|
|
|
|
|
|
|
#include "mtrap.h"
|
|
|
|
|
#include "bits.h"
|
|
|
|
|
|
|
|
|
|
.data
|
|
|
|
|
.align 6
|
|
|
|
|
trap_table:
|
|
|
|
|
.word bad_trap
|
|
|
|
|
.word bad_trap
|
|
|
|
|
.word illegal_insn_trap
|
|
|
|
|
.word bad_trap
|
|
|
|
|
.word misaligned_load_trap
|
|
|
|
|
.word bad_trap
|
|
|
|
|
.word misaligned_store_trap
|
|
|
|
|
.word bad_trap
|
|
|
|
|
.word bad_trap
|
|
|
|
|
.word mcall_trap
|
|
|
|
|
.word bad_trap
|
|
|
|
|
.word bad_trap
|
|
|
|
|
#define SOFTWARE_INTERRUPT_VECTOR 12
|
|
|
|
|
.word software_interrupt
|
|
|
|
|
#define TIMER_INTERRUPT_VECTOR 13
|
|
|
|
|
.word timer_interrupt
|
|
|
|
|
#define TRAP_FROM_MACHINE_MODE_VECTOR 14
|
|
|
|
|
.word __trap_from_machine_mode
|
|
|
|
|
|
|
|
|
|
.option norvc
|
|
|
|
|
.section .text.init,"ax",@progbits
|
|
|
|
|
.globl reset_vector
|
|
|
|
|
reset_vector:
|
|
|
|
|
j do_reset
|
|
|
|
|
|
|
|
|
|
nmi_vector:
|
|
|
|
|
.Lunhandleable_trap:
|
|
|
|
|
j bad_trap
|
|
|
|
|
|
|
|
|
|
trap_vector:
|
|
|
|
|
csrrw sp, mscratch, sp
|
|
|
|
|
beqz sp, .Ltrap_from_machine_mode
|
|
|
|
|
|
|
|
|
|
STORE a0, 10*REGBYTES(sp)
|
|
|
|
|
STORE a1, 11*REGBYTES(sp)
|
|
|
|
|
|
|
|
|
|
csrr a1, mcause
|
|
|
|
|
bgez a1, .Lhandle_trap_in_machine_mode
|
|
|
|
|
|
|
|
|
|
# This is an interrupt. Discard the mcause MSB and decode the rest.
|
|
|
|
|
sll a1, a1, 1
|
|
|
|
|
|
|
|
|
|
# Is it a machine timer interrupt?
|
|
|
|
|
li a0, IRQ_M_TIMER * 2
|
|
|
|
|
bne a0, a1, 1f
|
|
|
|
|
li a1, TIMER_INTERRUPT_VECTOR
|
|
|
|
|
j .Lhandle_trap_in_machine_mode
|
|
|
|
|
|
|
|
|
|
.Lmret:
|
|
|
|
|
# Go back whence we came.
|
|
|
|
|
LOAD a0, 10*REGBYTES(sp)
|
|
|
|
|
LOAD a1, 11*REGBYTES(sp)
|
|
|
|
|
csrrw sp, mscratch, sp
|
|
|
|
|
mret
|
|
|
|
|
|
|
|
|
|
1:
|
|
|
|
|
# Is it an IPI?
|
|
|
|
|
li a0, IRQ_M_SOFT * 2
|
|
|
|
|
bne a0, a1, .Lunhandleable_trap
|
|
|
|
|
li a1, SOFTWARE_INTERRUPT_VECTOR
|
|
|
|
|
j .Lhandle_trap_in_machine_mode
|
|
|
|
|
|
|
|
|
|
.Lhandle_trap_in_machine_mode:
|
|
|
|
|
# Preserve the registers. Compute the address of the trap handler.
|
|
|
|
|
STORE ra, 1*REGBYTES(sp)
|
|
|
|
|
STORE gp, 3*REGBYTES(sp)
|
|
|
|
|
STORE tp, 4*REGBYTES(sp)
|
|
|
|
|
STORE t0, 5*REGBYTES(sp)
|
|
|
|
|
1:auipc t0, %pcrel_hi(trap_table) # t0 <- %hi(trap_table)
|
|
|
|
|
STORE t1, 6*REGBYTES(sp)
|
|
|
|
|
sll t1, a1, 2 # t1 <- mcause << 2
|
|
|
|
|
STORE t2, 7*REGBYTES(sp)
|
|
|
|
|
add t1, t0, t1 # t1 <- %hi(trap_table)[mcause]
|
|
|
|
|
STORE s0, 8*REGBYTES(sp)
|
|
|
|
|
LWU t1, %pcrel_lo(1b)(t1) # t1 <- trap_table[mcause]
|
|
|
|
|
STORE s1, 9*REGBYTES(sp)
|
|
|
|
|
mv a0, sp # a0 <- regs
|
|
|
|
|
STORE a2,12*REGBYTES(sp)
|
|
|
|
|
csrr a2, mepc # a2 <- mepc
|
|
|
|
|
STORE a3,13*REGBYTES(sp)
|
|
|
|
|
csrrw t0, mscratch, x0 # t0 <- user sp
|
|
|
|
|
STORE a4,14*REGBYTES(sp)
|
|
|
|
|
STORE a5,15*REGBYTES(sp)
|
|
|
|
|
STORE a6,16*REGBYTES(sp)
|
|
|
|
|
STORE a7,17*REGBYTES(sp)
|
|
|
|
|
STORE s2,18*REGBYTES(sp)
|
|
|
|
|
STORE s3,19*REGBYTES(sp)
|
|
|
|
|
STORE s4,20*REGBYTES(sp)
|
|
|
|
|
STORE s5,21*REGBYTES(sp)
|
|
|
|
|
STORE s6,22*REGBYTES(sp)
|
|
|
|
|
STORE s7,23*REGBYTES(sp)
|
|
|
|
|
STORE s8,24*REGBYTES(sp)
|
|
|
|
|
STORE s9,25*REGBYTES(sp)
|
|
|
|
|
STORE s10,26*REGBYTES(sp)
|
|
|
|
|
STORE s11,27*REGBYTES(sp)
|
|
|
|
|
STORE t3,28*REGBYTES(sp)
|
|
|
|
|
STORE t4,29*REGBYTES(sp)
|
|
|
|
|
STORE t5,30*REGBYTES(sp)
|
|
|
|
|
STORE t6,31*REGBYTES(sp)
|
|
|
|
|
STORE t0, 2*REGBYTES(sp) # sp
|
|
|
|
|
|
|
|
|
|
#ifndef __riscv_hard_float
|
|
|
|
|
lw tp, (sp) # Move the emulated FCSR from x0's save slot into tp.
|
|
|
|
|
#endif
|
|
|
|
|
STORE x0, (sp) # Zero x0's save slot.
|
|
|
|
|
|
|
|
|
|
# Invoke the handler.
|
|
|
|
|
jalr t1
|
|
|
|
|
|
|
|
|
|
#ifndef __riscv_hard_float
|
|
|
|
|
sw tp, (sp) # Move the emulated FCSR from tp into x0's save slot.
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
restore_mscratch:
|
|
|
|
|
# Restore mscratch, so future traps will know they didn't come from M-mode.
|
|
|
|
|
csrw mscratch, sp
|
|
|
|
|
|
|
|
|
|
restore_regs:
|
|
|
|
|
# Restore all of the registers.
|
|
|
|
|
LOAD ra, 1*REGBYTES(sp)
|
|
|
|
|
LOAD gp, 3*REGBYTES(sp)
|
|
|
|
|
LOAD tp, 4*REGBYTES(sp)
|
|
|
|
|
LOAD t0, 5*REGBYTES(sp)
|
|
|
|
|
LOAD t1, 6*REGBYTES(sp)
|
|
|
|
|
LOAD t2, 7*REGBYTES(sp)
|
|
|
|
|
LOAD s0, 8*REGBYTES(sp)
|
|
|
|
|
LOAD s1, 9*REGBYTES(sp)
|
|
|
|
|
LOAD a0,10*REGBYTES(sp)
|
|
|
|
|
LOAD a1,11*REGBYTES(sp)
|
|
|
|
|
LOAD a2,12*REGBYTES(sp)
|
|
|
|
|
LOAD a3,13*REGBYTES(sp)
|
|
|
|
|
LOAD a4,14*REGBYTES(sp)
|
|
|
|
|
LOAD a5,15*REGBYTES(sp)
|
|
|
|
|
LOAD a6,16*REGBYTES(sp)
|
|
|
|
|
LOAD a7,17*REGBYTES(sp)
|
|
|
|
|
LOAD s2,18*REGBYTES(sp)
|
|
|
|
|
LOAD s3,19*REGBYTES(sp)
|
|
|
|
|
LOAD s4,20*REGBYTES(sp)
|
|
|
|
|
LOAD s5,21*REGBYTES(sp)
|
|
|
|
|
LOAD s6,22*REGBYTES(sp)
|
|
|
|
|
LOAD s7,23*REGBYTES(sp)
|
|
|
|
|
LOAD s8,24*REGBYTES(sp)
|
|
|
|
|
LOAD s9,25*REGBYTES(sp)
|
|
|
|
|
LOAD s10,26*REGBYTES(sp)
|
|
|
|
|
LOAD s11,27*REGBYTES(sp)
|
|
|
|
|
LOAD t3,28*REGBYTES(sp)
|
|
|
|
|
LOAD t4,29*REGBYTES(sp)
|
|
|
|
|
LOAD t5,30*REGBYTES(sp)
|
|
|
|
|
LOAD t6,31*REGBYTES(sp)
|
|
|
|
|
LOAD sp, 2*REGBYTES(sp)
|
|
|
|
|
mret
|
|
|
|
|
|
|
|
|
|
.Ltrap_from_machine_mode:
|
|
|
|
|
csrr sp, mscratch
|
|
|
|
|
addi sp, sp, -INTEGER_CONTEXT_SIZE
|
|
|
|
|
STORE a0,10*REGBYTES(sp)
|
|
|
|
|
STORE a1,11*REGBYTES(sp)
|
|
|
|
|
li a1, TRAP_FROM_MACHINE_MODE_VECTOR
|
|
|
|
|
j .Lhandle_trap_in_machine_mode
|
|
|
|
|
|
|
|
|
|
.globl __redirect_trap
|
|
|
|
|
__redirect_trap:
|
|
|
|
|
# reset sp to top of M-mode stack
|
|
|
|
|
li t0, MACHINE_STACK_SIZE
|
|
|
|
|
add sp, sp, t0
|
|
|
|
|
neg t0, t0
|
|
|
|
|
and sp, sp, t0
|
|
|
|
|
addi sp, sp, -MENTRY_FRAME_SIZE
|
|
|
|
|
j restore_mscratch
|
|
|
|
|
|
|
|
|
|
__trap_from_machine_mode:
|
|
|
|
|
jal trap_from_machine_mode
|
|
|
|
|
j restore_regs
|
|
|
|
|
|
|
|
|
|
do_reset:
|
|
|
|
|
li x1, 0
|
|
|
|
|
li x2, 0
|
|
|
|
|
li x3, 0
|
|
|
|
|
li x4, 0
|
|
|
|
|
li x5, 0
|
|
|
|
|
li x6, 0
|
|
|
|
|
li x7, 0
|
|
|
|
|
li x8, 0
|
|
|
|
|
li x9, 0
|
|
|
|
|
li x10, 0
|
|
|
|
|
li x11, 0
|
|
|
|
|
li x12, 0
|
|
|
|
|
li x13, 0
|
|
|
|
|
li x14, 0
|
|
|
|
|
li x15, 0
|
|
|
|
|
li x16, 0
|
|
|
|
|
li x17, 0
|
|
|
|
|
li x18, 0
|
|
|
|
|
li x19, 0
|
|
|
|
|
li x20, 0
|
|
|
|
|
li x21, 0
|
|
|
|
|
li x22, 0
|
|
|
|
|
li x23, 0
|
|
|
|
|
li x24, 0
|
|
|
|
|
li x25, 0
|
|
|
|
|
li x26, 0
|
|
|
|
|
li x27, 0
|
|
|
|
|
li x28, 0
|
|
|
|
|
li x29, 0
|
|
|
|
|
li x30, 0
|
|
|
|
|
li x31, 0
|
|
|
|
|
csrw mscratch, x0
|
|
|
|
|
|
|
|
|
|
# write mtvec and make sure it sticks
|
|
|
|
|
la t0, trap_vector
|
|
|
|
|
csrw mtvec, t0
|
|
|
|
|
csrr t1, mtvec
|
|
|
|
|
1:bne t0, t1, 1b
|
|
|
|
|
|
|
|
|
|
# sp <- end of first full page after the end of the binary
|
|
|
|
|
la sp, _end + 2*RISCV_PGSIZE - 1
|
|
|
|
|
li t0, -RISCV_PGSIZE
|
|
|
|
|
and sp, sp, t0
|
|
|
|
|
addi sp, sp, -MENTRY_FRAME_SIZE
|
|
|
|
|
|
|
|
|
|
csrr a0, mhartid
|
|
|
|
|
slli a1, a0, RISCV_PGSHIFT
|
|
|
|
|
add sp, sp, a1
|
|
|
|
|
|
|
|
|
|
beqz a0, init_first_hart
|
|
|
|
|
|
|
|
|
|
.LmultiHart:
|
|
|
|
|
#if MAX_HARTS > 1
|
|
|
|
|
# make sure our hart id is within a valid range
|
|
|
|
|
li a1, MAX_HARTS
|
|
|
|
|
bltu a0, a1, init_other_hart
|
|
|
|
|
wfi
|
|
|
|
|
#endif
|
|
|
|
|
j .LmultiHart
|