From 587949838488587e7d12c7fa831b61804060c1ca Mon Sep 17 00:00:00 2001 From: Xiang W Date: Wed, 2 Aug 2023 00:40:51 +0800 Subject: [PATCH] target/riscv: prevent the fence.i from triggering the exception On platforms that do not support Zifencei, executing fence.i will trigger an exception, this patch eliminates the impact of the exception Change-Id: I459cff096374064fdb6e18a9d95170510ae1f32e Signed-off-by: Xiang W --- src/target/riscv/gdb_regs.h | 1 + src/target/riscv/riscv-013.c | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/target/riscv/gdb_regs.h b/src/target/riscv/gdb_regs.h index ea0c0145d7..b46811e1fb 100644 --- a/src/target/riscv/gdb_regs.h +++ b/src/target/riscv/gdb_regs.h @@ -91,6 +91,7 @@ enum gdb_regno { GDB_REGNO_TDATA3 = CSR_TDATA3 + GDB_REGNO_CSR0, GDB_REGNO_TINFO = CSR_TINFO + GDB_REGNO_CSR0, GDB_REGNO_MISA = CSR_MISA + GDB_REGNO_CSR0, + GDB_REGNO_MTVEC = CSR_MTVEC + GDB_REGNO_CSR0, GDB_REGNO_DPC = CSR_DPC + GDB_REGNO_CSR0, GDB_REGNO_DCSR = CSR_DCSR + GDB_REGNO_CSR0, GDB_REGNO_DSCRATCH0 = CSR_DSCRATCH0 + GDB_REGNO_CSR0, diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 817d65f6cf..986692c4f7 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, GDB_REGNO_MTVEC); + + /* set mtvec after fence.i */ + riscv_program_insert(&program, auipc(S0)); + riscv_program_addi(&program, S0, S0, 16); + riscv_program_csrw(&program, S0, GDB_REGNO_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, GDB_REGNO_MTVEC); + riscv_program_fence_rw_rw(&program); int result = riscv_program_exec(&program, target); if (result != ERROR_OK)