diff --git a/firmware/fw_base.S b/firmware/fw_base.S index 4a2652e9..d027e5e2 100644 --- a/firmware/fw_base.S +++ b/firmware/fw_base.S @@ -31,6 +31,16 @@ add \__d4, \__s4, zero .endm +.macro CLEAR_MDT tmp +#if __riscv_xlen == 32 + li \tmp, MSTATUSH_MDT + csrc CSR_MSTATUSH, \tmp +#else + li \tmp, MSTATUS_MDT + csrc CSR_MSTATUS, \tmp +#endif +.endm + .section .entry, "ax", %progbits .align 3 .globl _start @@ -91,6 +101,14 @@ _bss_zero: lla s4, _start_hang csrw CSR_MTVEC, s4 + /* + * While at this point, trap handling is rudimentary, if a trap happens, + * it will end up in _start_hang which is enough to hook up a GDB. Clear + * MDT to avoid generating a double trap and thus entering a + * critical-error state. + */ + CLEAR_MDT t0 + /* Setup temporary stack */ lla s4, _fw_end li s5, (SBI_SCRATCH_SIZE * 2) @@ -348,6 +366,9 @@ _start_warm: _skip_trap_handler_hyp: csrw CSR_MTVEC, a4 + /* Clear MDT here again for all harts */ + CLEAR_MDT t0 + /* Initialize SBI runtime */ csrr a0, CSR_MSCRATCH call sbi_init @@ -545,6 +566,9 @@ memcmp: li t0, 0 .endif REG_S t0, (SBI_TRAP_REGS_SIZE + SBI_TRAP_INFO_OFFSET(gva))(sp) + + /* We are ready to take another trap, clear MDT */ + CLEAR_MDT t0 .endm .macro TRAP_CALL_C_ROUTINE @@ -587,15 +611,18 @@ memcmp: .endm .macro TRAP_RESTORE_MEPC_MSTATUS have_mstatush - /* Restore MEPC and MSTATUS CSRs */ - REG_L t0, SBI_TRAP_REGS_OFFSET(mepc)(a0) - csrw CSR_MEPC, t0 - REG_L t0, SBI_TRAP_REGS_OFFSET(mstatus)(a0) - csrw CSR_MSTATUS, t0 + /* + * Restore MSTATUS and MEPC CSRs starting with MSTATUS/H to set MDT + * flags since we can not take a trap now or MEPC would be cloberred + */ .if \have_mstatush REG_L t0, SBI_TRAP_REGS_OFFSET(mstatusH)(a0) csrw CSR_MSTATUSH, t0 .endif + REG_L t0, SBI_TRAP_REGS_OFFSET(mstatus)(a0) + csrw CSR_MSTATUS, t0 + REG_L t0, SBI_TRAP_REGS_OFFSET(mepc)(a0) + csrw CSR_MEPC, t0 .endm .macro TRAP_RESTORE_A0_T0 diff --git a/include/sbi/riscv_encoding.h b/include/sbi/riscv_encoding.h index 174cc9c1..38997ef4 100644 --- a/include/sbi/riscv_encoding.h +++ b/include/sbi/riscv_encoding.h @@ -42,7 +42,8 @@ #define MSTATUS_GVA _ULL(0x0000004000000000) #define MSTATUS_GVA_SHIFT 38 #define MSTATUS_MPV _ULL(0x0000008000000000) -#define MSTATUS_MPELP _ULL(0x0000020000000000) +#define MSTATUS_MPELP _ULL(0x0000020000000000) +#define MSTATUS_MDT _ULL(0x0000040000000000) #else #define MSTATUSH_SBE _UL(0x00000010) #define MSTATUSH_MBE _UL(0x00000020) @@ -50,6 +51,7 @@ #define MSTATUSH_GVA_SHIFT 6 #define MSTATUSH_MPV _UL(0x00000080) #define MSTATUSH_MPELP _UL(0x00000200) +#define MSTATUSH_MDT _UL(0x00000400) #endif #define MSTATUS32_SD _UL(0x80000000) #define MSTATUS64_SD _ULL(0x8000000000000000)