target/riscv: Preliminary textra trigger CSR writting support

This commit allows program to write textra trigger CSR for type 2, 3, 6
triggers. In this preliminary patch, the textra.MHVALUE and the
textra.MHSELECT fields are allowed to be configured. Other fields, such
as textra.SBYTEMASK, textra.SVALUE, and textra.SSELECT, are hardwired to
zero for now.

For textra.MHSELECT field, the only legal values are 0 (ignore) and 4
(mcontext). Writing 1~3 into textra.MHSELECT will be changed to 0, and
writing 5~7 into textra.MHSELECT will be changed to 4. This behavior is
aligned to RISC-V SPIKE simulator.

Signed-off-by: Alvin Chang <alvinga@andestech.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-ID: <20240826024657.262553-2-alvinga@andestech.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
Alvin Chang 2024-08-26 10:46:56 +08:00 committed by Alistair Francis
parent c5757f808b
commit c4db48cc24
2 changed files with 73 additions and 6 deletions

View file

@ -217,6 +217,66 @@ static inline void warn_always_zero_bit(target_ulong val, target_ulong mask,
}
}
static target_ulong textra_validate(CPURISCVState *env, target_ulong tdata3)
{
target_ulong mhvalue, mhselect;
target_ulong mhselect_new;
target_ulong textra;
const uint32_t mhselect_no_rvh[8] = { 0, 0, 0, 0, 4, 4, 4, 4 };
switch (riscv_cpu_mxl(env)) {
case MXL_RV32:
mhvalue = get_field(tdata3, TEXTRA32_MHVALUE);
mhselect = get_field(tdata3, TEXTRA32_MHSELECT);
/* Validate unimplemented (always zero) bits */
warn_always_zero_bit(tdata3, (target_ulong)TEXTRA32_SBYTEMASK,
"sbytemask");
warn_always_zero_bit(tdata3, (target_ulong)TEXTRA32_SVALUE,
"svalue");
warn_always_zero_bit(tdata3, (target_ulong)TEXTRA32_SSELECT,
"sselect");
break;
case MXL_RV64:
case MXL_RV128:
mhvalue = get_field(tdata3, TEXTRA64_MHVALUE);
mhselect = get_field(tdata3, TEXTRA64_MHSELECT);
/* Validate unimplemented (always zero) bits */
warn_always_zero_bit(tdata3, (target_ulong)TEXTRA64_SBYTEMASK,
"sbytemask");
warn_always_zero_bit(tdata3, (target_ulong)TEXTRA64_SVALUE,
"svalue");
warn_always_zero_bit(tdata3, (target_ulong)TEXTRA64_SSELECT,
"sselect");
break;
default:
g_assert_not_reached();
}
/* Validate mhselect. */
mhselect_new = mhselect_no_rvh[mhselect];
if (mhselect != mhselect_new) {
qemu_log_mask(LOG_UNIMP, "mhselect only supports 0 or 4 for now\n");
}
/* Write legal values into textra */
textra = 0;
switch (riscv_cpu_mxl(env)) {
case MXL_RV32:
textra = set_field(textra, TEXTRA32_MHVALUE, mhvalue);
textra = set_field(textra, TEXTRA32_MHSELECT, mhselect_new);
break;
case MXL_RV64:
case MXL_RV128:
textra = set_field(textra, TEXTRA64_MHVALUE, mhvalue);
textra = set_field(textra, TEXTRA64_MHSELECT, mhselect_new);
break;
default:
g_assert_not_reached();
}
return textra;
}
static void do_trigger_action(CPURISCVState *env, target_ulong trigger_index)
{
trigger_action_t action = get_trigger_action(env, trigger_index);
@ -441,8 +501,7 @@ static void type2_reg_write(CPURISCVState *env, target_ulong index,
}
break;
case TDATA3:
qemu_log_mask(LOG_UNIMP,
"tdata3 is not supported for type 2 trigger\n");
env->tdata3[index] = textra_validate(env, val);
break;
default:
g_assert_not_reached();
@ -558,8 +617,7 @@ static void type6_reg_write(CPURISCVState *env, target_ulong index,
}
break;
case TDATA3:
qemu_log_mask(LOG_UNIMP,
"tdata3 is not supported for type 6 trigger\n");
env->tdata3[index] = textra_validate(env, val);
break;
default:
g_assert_not_reached();
@ -741,8 +799,7 @@ static void itrigger_reg_write(CPURISCVState *env, target_ulong index,
"tdata2 is not supported for icount trigger\n");
break;
case TDATA3:
qemu_log_mask(LOG_UNIMP,
"tdata3 is not supported for icount trigger\n");
env->tdata3[index] = textra_validate(env, val);
break;
default:
g_assert_not_reached();