From 809c15189cef79cd2a6b9ffb41e695db05acccc4 Mon Sep 17 00:00:00 2001 From: ChinYikMing Date: Mon, 17 Jun 2024 01:58:11 +0800 Subject: [PATCH] Preliminary support "Svinval" Standard Extension Add supervisor memory-management fence instruction SFENCE.VMA to decoder. 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) in the emulator, the implemention 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