The Ssdtso extension introduces a DTSO field to the {m,s,h}envcfg
register to enable TSO at run-time. Building on top of Ztso support,
this patch treats Ssdtso just like Ztso (always execute in TSO mode),
which should be fine from a correctness perspective.
Similar like Ztso, this is expected to have little overhead on
host machines that operate in TSO mode (e.g. x86).
However, executing the TSO fences on guests without TSO, will
have a negative performance impact, regardless if TSO is enabled
in the guest or not (e.g. running a RV guest with Ssdtso and disabled
DTSO bit on an aarch64 host).
Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu>
---
target/riscv/cpu.c | 8 ++++++--
target/riscv/cpu_bits.h | 3 +++
target/riscv/cpu_cfg.h | 1 +
target/riscv/csr.c | 14 +++++++++++---
target/riscv/translate.c | 2 +-
5 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index b679ecd8c7..ee90c09600 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -174,6 +174,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(smstateen, PRIV_VERSION_1_12_0, ext_smstateen),
ISA_EXT_DATA_ENTRY(ssaia, PRIV_VERSION_1_12_0, ext_ssaia),
ISA_EXT_DATA_ENTRY(sscofpmf, PRIV_VERSION_1_12_0, ext_sscofpmf),
+ ISA_EXT_DATA_ENTRY(ssdtso, PRIV_VERSION_1_12_0, ext_ssdtso),
ISA_EXT_DATA_ENTRY(sstc, PRIV_VERSION_1_12_0, ext_sstc),
ISA_EXT_DATA_ENTRY(svadu, PRIV_VERSION_1_12_0, ext_svadu),
ISA_EXT_DATA_ENTRY(svinval, PRIV_VERSION_1_12_0, ext_svinval),
@@ -950,9 +951,11 @@ static void riscv_cpu_reset_hold(Object *obj)
env->two_stage_lookup = false;
env->menvcfg = (cpu->cfg.ext_svpbmt ? MENVCFG_PBMTE : 0) |
- (cpu->cfg.ext_svadu ? MENVCFG_ADUE : 0);
+ (cpu->cfg.ext_svadu ? MENVCFG_ADUE : 0) |
+ (cpu->cfg.ext_ztso && cpu->cfg.ext_ssdtso ? MENVCFG_DTSO : 0);
env->henvcfg = (cpu->cfg.ext_svpbmt ? HENVCFG_PBMTE : 0) |
- (cpu->cfg.ext_svadu ? HENVCFG_ADUE : 0);
+ (cpu->cfg.ext_svadu ? HENVCFG_ADUE : 0) |
+ (cpu->cfg.ext_ztso && cpu->cfg.ext_ssdtso ? HENVCFG_DTSO : 0);
/* Initialized default priorities of local interrupts. */
for (i = 0; i < ARRAY_SIZE(env->miprio); i++) {
@@ -1460,6 +1463,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
MULTI_EXT_CFG_BOOL("zve32f", ext_zve32f, false),
MULTI_EXT_CFG_BOOL("zve64f", ext_zve64f, false),
MULTI_EXT_CFG_BOOL("zve64d", ext_zve64d, false),
+ MULTI_EXT_CFG_BOOL("ssdtso", ext_ssdtso, false),
MULTI_EXT_CFG_BOOL("sstc", ext_sstc, true),
MULTI_EXT_CFG_BOOL("smepmp", ext_smepmp, false),
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index fc2068ee4d..e11191977d 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -744,6 +744,7 @@ typedef enum RISCVException {
#define MENVCFG_CBIE (3UL << 4)
#define MENVCFG_CBCFE BIT(6)
#define MENVCFG_CBZE BIT(7)
+#define MENVCFG_DTSO BIT(8)
#define MENVCFG_ADUE (1ULL << 61)
#define MENVCFG_PBMTE (1ULL << 62)
#define MENVCFG_STCE (1ULL << 63)
@@ -757,11 +758,13 @@ typedef enum RISCVException {
#define SENVCFG_CBIE MENVCFG_CBIE
#define SENVCFG_CBCFE MENVCFG_CBCFE
#define SENVCFG_CBZE MENVCFG_CBZE
+#define SENVCFG_DTSO MENVCFG_DTSO
#define HENVCFG_FIOM MENVCFG_FIOM
#define HENVCFG_CBIE MENVCFG_CBIE
#define HENVCFG_CBCFE MENVCFG_CBCFE
#define HENVCFG_CBZE MENVCFG_CBZE
+#define HENVCFG_DTSO MENVCFG_DTSO
#define HENVCFG_ADUE MENVCFG_ADUE
#define HENVCFG_PBMTE MENVCFG_PBMTE
#define HENVCFG_STCE MENVCFG_STCE
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index afba8ed0b2..606ae5a120 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -73,6 +73,7 @@ struct RISCVCPUConfig {
bool ext_zihpm;
bool ext_ztso;
bool ext_smstateen;
+ bool ext_ssdtso;
bool ext_sstc;
bool ext_svadu;
bool ext_svinval;
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index d4e8ac13b9..c06b674994 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -2058,7 +2058,9 @@ static RISCVException write_menvcfg(CPURISCVState *env, int csrno,
target_ulong val)
{
const RISCVCPUConfig *cfg = riscv_cpu_cfg(env);
- uint64_t mask = MENVCFG_FIOM | MENVCFG_CBIE | MENVCFG_CBCFE | MENVCFG_CBZE;
+ uint64_t mask = MENVCFG_FIOM | MENVCFG_CBIE | MENVCFG_CBCFE |
+ MENVCFG_CBZE |
+ (cfg->ext_ssdtso && !cfg->ext_ztso ? MENVCFG_DTSO : 0);
if (riscv_cpu_mxl(env) == MXL_RV64) {
mask |= (cfg->ext_svpbmt ? MENVCFG_PBMTE : 0) |
@@ -2108,7 +2110,10 @@ static RISCVException read_senvcfg(CPURISCVState *env, int csrno,
static RISCVException write_senvcfg(CPURISCVState *env, int csrno,
target_ulong val)
{
- uint64_t mask = SENVCFG_FIOM | SENVCFG_CBIE | SENVCFG_CBCFE | SENVCFG_CBZE;
+ const RISCVCPUConfig *cfg = riscv_cpu_cfg(env);
+ uint64_t mask = SENVCFG_FIOM | SENVCFG_CBIE | SENVCFG_CBCFE |
+ SENVCFG_CBZE |
+ (cfg->ext_ssdtso && !cfg->ext_ztso ? SENVCFG_DTSO : 0);
RISCVException ret;
ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG);
@@ -2143,7 +2148,10 @@ static RISCVException read_henvcfg(CPURISCVState *env, int csrno,
static RISCVException write_henvcfg(CPURISCVState *env, int csrno,
target_ulong val)
{
- uint64_t mask = HENVCFG_FIOM | HENVCFG_CBIE | HENVCFG_CBCFE | HENVCFG_CBZE;
+ const RISCVCPUConfig *cfg = riscv_cpu_cfg(env);
+ uint64_t mask = HENVCFG_FIOM | HENVCFG_CBIE | HENVCFG_CBCFE |
+ HENVCFG_CBZE |
+ (cfg->ext_ssdtso && !cfg->ext_ztso ? HENVCFG_DTSO : 0);
RISCVException ret;
ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG);
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index ea5d52b2ef..f0d4db0b64 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -1198,7 +1198,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
ctx->cs = cs;
ctx->pm_mask_enabled = FIELD_EX32(tb_flags, TB_FLAGS, PM_MASK_ENABLED);
ctx->pm_base_enabled = FIELD_EX32(tb_flags, TB_FLAGS, PM_BASE_ENABLED);
- ctx->ztso = cpu->cfg.ext_ztso;
+ ctx->ztso = cpu->cfg.ext_ztso || cpu->cfg.ext_ssdtso;
ctx->itrigger = FIELD_EX32(tb_flags, TB_FLAGS, ITRIGGER);
ctx->zero = tcg_constant_tl(0);
ctx->virt_inst_excp = false;
--
2.43.0
© 2016 - 2024 Red Hat, Inc.