Skip to content

Commit a88f040

Browse files
frankchang0125alistair23
authored andcommitted
target/riscv: Set mstatus_hs.[SD|FS] bits if Clean and V=1 in mark_fs_dirty()
When V=1, both vsstauts.FS and HS-level sstatus.FS are in effect. Modifying the floating-point state when V=1 causes both fields to be set to 3 (Dirty). However, it's possible that HS-level sstatus.FS is Clean and VS-level vsstatus.FS is Dirty at the time mark_fs_dirty() is called when V=1. We can't early return for this case because we still need to set sstatus.FS to Dirty according to spec. Signed-off-by: Frank Chang <[email protected]> Reviewed-by: Vincent Chen <[email protected]> Tested-by: Vincent Chen <[email protected]> Reviewed-by: Richard Henderson <[email protected]> Reviewed-by: Alistair Francis <[email protected]> Message-id: [email protected] Signed-off-by: Alistair Francis <[email protected]>
1 parent 02c1b56 commit a88f040

File tree

2 files changed

+21
-13
lines changed

2 files changed

+21
-13
lines changed

target/riscv/cpu.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ FIELD(TB_FLAGS, SEW, 5, 3)
393393
FIELD(TB_FLAGS, VILL, 8, 1)
394394
/* Is a Hypervisor instruction load/store allowed? */
395395
FIELD(TB_FLAGS, HLSX, 9, 1)
396+
FIELD(TB_FLAGS, MSTATUS_HS_FS, 10, 2)
396397

397398
bool riscv_cpu_is_32bit(CPURISCVState *env);
398399

@@ -449,6 +450,9 @@ static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
449450
get_field(env->hstatus, HSTATUS_HU))) {
450451
flags = FIELD_DP32(flags, TB_FLAGS, HLSX, 1);
451452
}
453+
454+
flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_FS,
455+
get_field(env->mstatus_hs, MSTATUS_FS));
452456
}
453457
#endif
454458

target/riscv/translate.c

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ typedef struct DisasContext {
5858
target_ulong misa;
5959
uint32_t opcode;
6060
uint32_t mstatus_fs;
61+
uint32_t mstatus_hs_fs;
6162
uint32_t mem_idx;
6263
/* Remember the rounding mode encoded in the previous fp instruction,
6364
which we have already installed into env->fp_status. Or -1 for
@@ -280,27 +281,29 @@ static void gen_jal(DisasContext *ctx, int rd, target_ulong imm)
280281
static void mark_fs_dirty(DisasContext *ctx)
281282
{
282283
TCGv tmp;
283-
target_ulong sd;
284+
target_ulong sd = is_32bit(ctx) ? MSTATUS32_SD : MSTATUS64_SD;
284285

285-
if (ctx->mstatus_fs == MSTATUS_FS) {
286-
return;
287-
}
288-
/* Remember the state change for the rest of the TB. */
289-
ctx->mstatus_fs = MSTATUS_FS;
286+
if (ctx->mstatus_fs != MSTATUS_FS) {
287+
/* Remember the state change for the rest of the TB. */
288+
ctx->mstatus_fs = MSTATUS_FS;
290289

291-
tmp = tcg_temp_new();
292-
sd = is_32bit(ctx) ? MSTATUS32_SD : MSTATUS64_SD;
290+
tmp = tcg_temp_new();
291+
tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
292+
tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | sd);
293+
tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
294+
tcg_temp_free(tmp);
295+
}
293296

294-
tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
295-
tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | sd);
296-
tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
297+
if (ctx->virt_enabled && ctx->mstatus_hs_fs != MSTATUS_FS) {
298+
/* Remember the stage change for the rest of the TB. */
299+
ctx->mstatus_hs_fs = MSTATUS_FS;
297300

298-
if (ctx->virt_enabled) {
301+
tmp = tcg_temp_new();
299302
tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
300303
tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | sd);
301304
tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
305+
tcg_temp_free(tmp);
302306
}
303-
tcg_temp_free(tmp);
304307
}
305308
#else
306309
static inline void mark_fs_dirty(DisasContext *ctx) { }
@@ -539,6 +542,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
539542
ctx->frm = -1; /* unknown rounding mode */
540543
ctx->ext_ifencei = cpu->cfg.ext_ifencei;
541544
ctx->vlen = cpu->cfg.vlen;
545+
ctx->mstatus_hs_fs = FIELD_EX32(tb_flags, TB_FLAGS, MSTATUS_HS_FS);
542546
ctx->hlsx = FIELD_EX32(tb_flags, TB_FLAGS, HLSX);
543547
ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL);
544548
ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW);

0 commit comments

Comments
 (0)