target/riscv: UPDATE xATP write CSR

Added xATP_MODE validation for vsatp/hgatp CSRs.
The xATP register is an SXLEN-bit read/write WARL register, so
the legal value must be returned (See riscv-privileged-20211203, SATP/VSATP/HGATP CSRs).

Signed-off-by: Irina Ryapolova <irina.ryapolova@syntacore.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-ID: <20240109145923.37893-2-irina.ryapolova@syntacore.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
Irina Ryapolova 2024-01-09 17:59:22 +03:00 committed by Alistair Francis
parent 57020a464c
commit 1349f96952

View file

@ -1299,6 +1299,32 @@ static bool validate_vm(CPURISCVState *env, target_ulong vm)
return get_field(mode_supported, (1 << vm));
}
static target_ulong legalize_xatp(CPURISCVState *env, target_ulong old_xatp,
target_ulong val)
{
target_ulong mask;
bool vm;
if (riscv_cpu_mxl(env) == MXL_RV32) {
vm = validate_vm(env, get_field(val, SATP32_MODE));
mask = (val ^ old_xatp) & (SATP32_MODE | SATP32_ASID | SATP32_PPN);
} else {
vm = validate_vm(env, get_field(val, SATP64_MODE));
mask = (val ^ old_xatp) & (SATP64_MODE | SATP64_ASID | SATP64_PPN);
}
if (vm && mask) {
/*
* The ISA defines SATP.MODE=Bare as "no translation", but we still
* pass these through QEMU's TLB emulation as it improves
* performance. Flushing the TLB on SATP writes with paging
* enabled avoids leaking those invalid cached mappings.
*/
tlb_flush(env_cpu(env));
return val;
}
return old_xatp;
}
static target_ulong legalize_mpp(CPURISCVState *env, target_ulong old_mpp,
target_ulong val)
{
@ -3021,31 +3047,11 @@ static RISCVException read_satp(CPURISCVState *env, int csrno,
static RISCVException write_satp(CPURISCVState *env, int csrno,
target_ulong val)
{
target_ulong mask;
bool vm;
if (!riscv_cpu_cfg(env)->mmu) {
return RISCV_EXCP_NONE;
}
if (riscv_cpu_mxl(env) == MXL_RV32) {
vm = validate_vm(env, get_field(val, SATP32_MODE));
mask = (val ^ env->satp) & (SATP32_MODE | SATP32_ASID | SATP32_PPN);
} else {
vm = validate_vm(env, get_field(val, SATP64_MODE));
mask = (val ^ env->satp) & (SATP64_MODE | SATP64_ASID | SATP64_PPN);
}
if (vm && mask) {
/*
* The ISA defines SATP.MODE=Bare as "no translation", but we still
* pass these through QEMU's TLB emulation as it improves
* performance. Flushing the TLB on SATP writes with paging
* enabled avoids leaking those invalid cached mappings.
*/
tlb_flush(env_cpu(env));
env->satp = val;
}
env->satp = legalize_xatp(env, env->satp, val);
return RISCV_EXCP_NONE;
}
@ -3532,7 +3538,7 @@ static RISCVException read_hgatp(CPURISCVState *env, int csrno,
static RISCVException write_hgatp(CPURISCVState *env, int csrno,
target_ulong val)
{
env->hgatp = val;
env->hgatp = legalize_xatp(env, env->hgatp, val);
return RISCV_EXCP_NONE;
}
@ -3809,7 +3815,7 @@ static RISCVException read_vsatp(CPURISCVState *env, int csrno,
static RISCVException write_vsatp(CPURISCVState *env, int csrno,
target_ulong val)
{
env->vsatp = val;
env->vsatp = legalize_xatp(env, env->vsatp, val);
return RISCV_EXCP_NONE;
}