From 1e769a5f449319504890c7b3cebcc2f07c60982e Mon Sep 17 00:00:00 2001 From: ChinYikMing Date: Mon, 17 Jun 2024 03:24:12 +0800 Subject: [PATCH] Add supervisor memory fence instruction SFENCE.VMA (#458) The supervisor memory-management fence instruction SFENCE.VMA is used to synchronize updates to in-memory memory-management data structures with current execution. Linux kernel leverage this instruction for synchronization, support emulating this instruction is needed to boot Linux kernel. Since we have only one hart and we have not yet support cache (TLB) at present, the implementation of this instruction is straight forward and it could be further improved in the future. Related: #310, #438 --- src/decode.c | 10 ++++++++++ src/decode.h | 1 + src/rv32_constopt.c | 7 ++++++- src/rv32_template.c | 14 ++++++++++++++ src/t2c_template.c | 2 ++ 5 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/decode.c b/src/decode.c index 45a2a5e7d..ac65d3db7 100644 --- a/src/decode.c +++ b/src/decode.c @@ -810,12 +810,22 @@ static inline bool op_system(rv_insn_t *ir, const uint32_t insn) * MRET 001100000010 00000 000 00000 1110011 */ + /* inst funct7 rs2 rs1 funct3 rd opcode + * -----------+-------+---+---+------+------+------- + * SFENCE.VMA 0001001 rs2 rs1 000 00000 1110011 + */ + /* decode I-type */ decode_itype(ir, insn); /* dispatch from funct3 field */ switch (decode_funct3(insn)) { case 0: + if ((insn >> 25) == 0b0001001) { /* SFENCE.VMA */ + ir->opcode = rv_insn_sfencevma; + break; + } + /* dispatch from imm field */ switch (ir->imm) { case 0: /* ECALL: Environment Call */ diff --git a/src/decode.h b/src/decode.h index 98d60977d..4ff38b6e6 100644 --- a/src/decode.h +++ b/src/decode.h @@ -80,6 +80,7 @@ enum op_field { _(sret, 1, 4, 0, ENC(rs1, rd)) \ _(hret, 0, 4, 0, ENC(rs1, rd)) \ _(mret, 1, 4, 0, ENC(rs1, rd)) \ + _(sfencevma, 1, 4, 0, ENC(rs1, rs2, rd)) \ /* RV32 Zifencei Standard Extension */ \ IIF(RV32_HAS(Zifencei))( \ _(fencei, 1, 4, 0, ENC(rs1, rd)) \ diff --git a/src/rv32_constopt.c b/src/rv32_constopt.c index f47b3a3ba..adc35dee3 100644 --- a/src/rv32_constopt.c +++ b/src/rv32_constopt.c @@ -374,9 +374,14 @@ CONSTOPT(sret, {}) /* HRET: return from traps in H-mode */ CONSTOPT(hret, {}) -/* MRET: return from traps in U-mode */ +/* MRET: return from traps in M-mode */ CONSTOPT(mret, {}) +/* SFENCE.VMA: synchronize updates to in-memory memory-management data + * structures with current execution + */ +CONSTOPT(sfencevma, {}) + #if RV32_HAS(Zifencei) /* RV32 Zifencei Standard Extension */ CONSTOPT(fencei, {}) #endif diff --git a/src/rv32_template.c b/src/rv32_template.c index ee7920c6e..cf66ced67 100644 --- a/src/rv32_template.c +++ b/src/rv32_template.c @@ -1019,6 +1019,20 @@ RVOP( assert; /* FIXME: Implement */ })) +/* SFENCE.VMA: synchronize updates to in-memory memory-management data + * structures with current execution + */ +RVOP( + sfencevma, + { + PC += 4; + /* FIXME: fill real implementations */ + goto end_op; + }, + GEN({ + assert; /* FIXME: Implement */ + })) + #if RV32_HAS(Zifencei) /* RV32 Zifencei Standard Extension */ RVOP( fencei, diff --git a/src/t2c_template.c b/src/t2c_template.c index 386e6949c..1ce4dd786 100644 --- a/src/t2c_template.c +++ b/src/t2c_template.c @@ -305,6 +305,8 @@ T2C_OP(hret, { __UNREACHABLE; }) T2C_OP(mret, { __UNREACHABLE; }) +T2C_OP(sfencevma, { __UNREACHABLE; }) + #if RV32_HAS(Zifencei) T2C_OP(fencei, { __UNREACHABLE; }) #endif