From: Christoph Müllner
This patch adds support for the XTheadSync ISA extension.
The patch uses the T-Head specific decoder and translation.
The implementation introduces a helper to execute synchronization tasks:
helper_tlb_flush_all() performs a synchronized TLB flush on all CPUs.
Co-developed-by: LIU Zhiwei
Reviewed-by: Alistair Francis
Signed-off-by: Christoph Müllner
---
Changes in v2:
- Add ISA_EXT_DATA_ENTRY()
- Use helper to synchronize CPUs and perform TLB flushes
- Change implemenation to follow latest spec update
- Use single decoder for XThead extensions
Changes in v3:
- Adjust for renamed REQUIRE_PRIV_* test macros
target/riscv/cpu.c | 2 +
target/riscv/cpu.h | 1 +
target/riscv/helper.h | 1 +
target/riscv/insn_trans/trans_xthead.c.inc | 86 ++
target/riscv/op_helper.c | 6 ++
target/riscv/translate.c | 2 +-
target/riscv/xthead.decode | 9 +++
7 files changed, 106 insertions(+), 1 deletion(-)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 43a3b9218f..ae2009e89c 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -110,6 +110,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(svnapot, true, PRIV_VERSION_1_12_0, ext_svnapot),
ISA_EXT_DATA_ENTRY(svpbmt, true, PRIV_VERSION_1_12_0, ext_svpbmt),
ISA_EXT_DATA_ENTRY(xtheadcmo, true, PRIV_VERSION_1_11_0, ext_xtheadcmo),
+ISA_EXT_DATA_ENTRY(xtheadsync, true, PRIV_VERSION_1_11_0, ext_xtheadsync),
ISA_EXT_DATA_ENTRY(xventanacondops, true, PRIV_VERSION_1_12_0,
ext_XVentanaCondOps),
};
@@ -1073,6 +1074,7 @@ static Property riscv_cpu_extensions[] = {
/* Vendor-specific custom extensions */
DEFINE_PROP_BOOL("xtheadcmo", RISCVCPU, cfg.ext_xtheadcmo, false),
+DEFINE_PROP_BOOL("xtheadsync", RISCVCPU, cfg.ext_xtheadsync, false),
DEFINE_PROP_BOOL("xventanacondops", RISCVCPU, cfg.ext_XVentanaCondOps,
false),
/* These are experimental so mark with 'x-' */
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 680dd3dfbd..d0ab5c7bb0 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -474,6 +474,7 @@ struct RISCVCPUConfig {
/* Vendor-specific custom extensions */
bool ext_xtheadcmo;
+bool ext_xtheadsync;
bool ext_XVentanaCondOps;
uint8_t pmu_num;
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index 227c7122ef..d22656698a 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -109,6 +109,7 @@ DEF_HELPER_1(sret, tl, env)
DEF_HELPER_1(mret, tl, env)
DEF_HELPER_1(wfi, void, env)
DEF_HELPER_1(tlb_flush, void, env)
+DEF_HELPER_1(tlb_flush_all, void, env)
/* Native Debug */
DEF_HELPER_1(itrigger_match, void, env)
#endif
diff --git a/target/riscv/insn_trans/trans_xthead.c.inc
b/target/riscv/insn_trans/trans_xthead.c.inc
index 24acaf188c..bf5b39c749 100644
--- a/target/riscv/insn_trans/trans_xthead.c.inc
+++ b/target/riscv/insn_trans/trans_xthead.c.inc
@@ -22,6 +22,12 @@
}\
} while (0)
+#define REQUIRE_XTHEADSYNC(ctx) do { \
+if (!ctx->cfg_ptr->ext_xtheadsync) { \
+return false;\
+}\
+} while (0)
+
/* XTheadCmo */
static inline int priv_level(DisasContext *ctx)
@@ -79,3 +85,83 @@ NOP_PRIVCHECK(th_icache_iva, REQUIRE_XTHEADCMO,
REQUIRE_PRIV_MSU)
NOP_PRIVCHECK(th_l2cache_call, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
NOP_PRIVCHECK(th_l2cache_ciall, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
NOP_PRIVCHECK(th_l2cache_iall, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS)
+
+/* XTheadSync */
+
+static bool trans_th_sfence_vmas(DisasContext *ctx, arg_th_sfence_vmas *a)
+{
+(void) a;
+REQUIRE_XTHEADSYNC(ctx);
+
+#ifndef CONFIG_USER_ONLY
+REQUIRE_PRIV_MS(ctx);
+decode_save_opc(ctx);
+gen_helper_tlb_flush_all(cpu_env);
+return true;
+#else
+return false;
+#endif
+}
+
+#ifndef CONFIG_USER_ONLY
+static void gen_th_sync_local(DisasContext *ctx)
+{
+/*
+ * Emulate out-of-order barriers with pipeline flush
+ * by exiting the translation block.
+ */
+gen_set_pc_imm(ctx, ctx->pc_succ_insn);
+tcg_gen_exit_tb(NULL, 0);
+ctx->base.is_jmp = DISAS_NORETURN;
+}
+#endif
+
+static bool trans_th_sync(DisasContext *ctx, arg_th_sync *a)
+{
+(void) a;
+REQUIRE_XTHEADSYNC(ctx);
+
+#ifndef CONFIG_USER_ONLY
+REQUIRE_PRIV_MSU(ctx);
+
+/*
+ * th.sync is an out-of-order barrier.
+ */
+gen_th_sync_local(ctx);
+
+return true;
+#else
+return false;
+#endif
+}
+
+static bool trans_th_sync_i(DisasContext *ctx, arg_th_sync_i *a)
+{
+(void) a;
+REQUIRE_XTHEADSYNC(ctx);
+
+#ifndef CONFIG_USER_ONLY
+REQUIRE_PRIV_MSU(ctx);
+
+/*
+ * th.sync.i is th.sync plus pipeline flush.
+ */
+gen_th_sync_local(ctx);
+
+return true;
+#else
+