@@ -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),
@@ -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
@@ -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;
@@ -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);
@@ -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;
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(-)