diff options
Diffstat (limited to 'machine/mentry.S')
-rw-r--r-- | machine/mentry.S | 119 |
1 files changed, 84 insertions, 35 deletions
diff --git a/machine/mentry.S b/machine/mentry.S index 95653c1..11c053c 100644 --- a/machine/mentry.S +++ b/machine/mentry.S @@ -6,24 +6,24 @@ .data .align 6 trap_table: +#define BAD_TRAP_VECTOR 0 .word bad_trap - .word bad_trap + .word pmp_trap .word illegal_insn_trap .word bad_trap .word misaligned_load_trap - .word bad_trap + .word pmp_trap .word misaligned_store_trap - .word bad_trap + .word pmp_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 bad_trap +#define TRAP_FROM_MACHINE_MODE_VECTOR 13 .word __trap_from_machine_mode + .word bad_trap + .word bad_trap .option norvc .section .text.init,"ax",@progbits @@ -31,10 +31,6 @@ trap_table: reset_vector: j do_reset -nmi_vector: -.Lunhandleable_trap: - j bad_trap - trap_vector: csrrw sp, mscratch, sp beqz sp, .Ltrap_from_machine_mode @@ -51,8 +47,12 @@ trap_vector: # 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 + + # Yes. Simply clear MSIE and raise SSIP. + li a0, MIP_MTIP + csrc mie, a0 + li a0, MIP_STIP + csrs mip, a0 .Lmret: # Go back whence we came. @@ -64,9 +64,35 @@ trap_vector: 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 + bne a0, a1, .Lbad_trap + + # Yes. First, clear the MIPI bit. + LOAD a0, MENTRY_IPI_OFFSET(sp) + sw x0, (a0) + fence + + # Now, decode the cause(s). +#ifdef __riscv_atomic + addi a0, sp, MENTRY_IPI_PENDING_OFFSET + amoswap.w a0, x0, (a0) +#else + lw a0, MENTRY_IPI_PENDING_OFFSET(a0) + sw x0, MENTRY_IPI_PENDING_OFFSET(a0) +#endif + and a1, a0, IPI_SOFT + beqz a1, 1f + csrs mip, MIP_SSIP +1: + andi a1, a0, IPI_FENCE_I + beqz a1, 1f + fence.i +1: + andi a1, a0, IPI_SFENCE_VMA + beqz a1, 1f + sfence.vma +1: + j .Lmret + .Lhandle_trap_in_machine_mode: # Preserve the registers. Compute the address of the trap handler. @@ -166,6 +192,10 @@ restore_regs: li a1, TRAP_FROM_MACHINE_MODE_VECTOR j .Lhandle_trap_in_machine_mode +.Lbad_trap: + li a1, BAD_TRAP_VECTOR + j .Lhandle_trap_in_machine_mode + .globl __redirect_trap __redirect_trap: # reset sp to top of M-mode stack @@ -190,8 +220,9 @@ do_reset: li x7, 0 li x8, 0 li x9, 0 - li x10, 0 - li x11, 0 +// save a0 and a1; arguments from previous boot loader stage: +// li x10, 0 +// li x11, 0 li x12, 0 li x13, 0 li x14, 0 @@ -220,34 +251,52 @@ do_reset: 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 + la sp, stacks + RISCV_PGSIZE - MENTRY_FRAME_SIZE - csrr a0, mhartid - slli a1, a0, RISCV_PGSHIFT - add sp, sp, a1 + csrr a3, mhartid + slli a2, a3, RISCV_PGSHIFT + add sp, sp, a2 - beqz a0, init_first_hart + # Boot on the first unmasked hart + la a4, disabled_hart_mask + LOAD a4, 0(a4) + addi a5, a4, 1 + not a4, a4 + and a4, a4, a5 + srl a4, a4, a3 + andi a4, a4, 1 + bnez a4, init_first_hart # set MSIE bit to receive IPI - li a1, MIP_MSIP - csrw mie, a1 + li a2, MIP_MSIP + csrw mie, a2 .LmultiHart: #if MAX_HARTS > 1 # wait for an IPI to signal that it's safe to boot wfi - csrr a1, mip - andi a1, a1, MIP_MSIP - beqz a1, .LmultiHart + + # masked harts never start + la a4, disabled_hart_mask + LOAD a4, 0(a4) + srl a4, a4, a3 + andi a4, a4, 1 + bnez a4, .LmultiHart + + # only start if mip is set + csrr a2, mip + andi a2, a2, MIP_MSIP + beqz a2, .LmultiHart # make sure our hart id is within a valid range fence - li a1, MAX_HARTS - bltu a0, a1, init_other_hart + li a2, MAX_HARTS + bltu a3, a2, init_other_hart #endif wfi j .LmultiHart + + .bss + .align RISCV_PGSHIFT +stacks: + .skip RISCV_PGSIZE * MAX_HARTS |