diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 817d65f6cf..428b207332 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -2844,7 +2844,26 @@ static int execute_fence(struct target *target) * here, but there's no ISA-defined way of doing that. */ struct riscv_program program; riscv_program_init(&program, target); + + /* s0 s1 used, need backup and restore*/ + program.writes_xreg[GDB_REGNO_S0] = true; + program.writes_xreg[GDB_REGNO_S1] = true; + + /* backup mtvec to s1 */ + riscv_program_csrr(&program, S1, CSR_MTVEC); + + /* set mtvec after fence.i */ + riscv_program_insert(&program, auipc(S0)); + riscv_program_addi(&program, S0, S0, 16); + riscv_program_csrw(&program, S0, CSR_MTVEC); + + /* fence.i may cause exception, Because mtvec is set after fence.i, + * triggering an exception does not affect the execution flow */ riscv_program_fence_i(&program); + + /* restore mtvec from s1 */ + riscv_program_csrw(&program, S1, CSR_MTVEC); + riscv_program_fence_rw_rw(&program); int result = riscv_program_exec(&program, target); if (result != ERROR_OK)