target/riscv: Check memory access to meet svukte rule

Follow the Svukte spec, do the memory access address checking

1. Include instruction fetches or explicit memory accesses
2. System run in effective privilege U or VU
3. Check senvcfg[UKTE] being set, or hstatus[HUKTE] being set if
instruction is HLV, HLVX, HSV and execute from U mode to VU mode
4. Depend on Sv39 and check virtual addresses bit[SXLEN-1]
5. Raises a page-fault exception corresponding to the original access
type.

Ref: https://github.com/riscv/riscv-isa-manual/pull/1564/files

Signed-off-by: Frank Chang <frank.chang@sifive.com>
Signed-off-by: Fea.Wang <fea.wang@sifive.com>
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Jim Shu <jim.shu@sifive.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-ID: <20241203034932.25185-5-fea.wang@sifive.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
Fea.Wang 2024-12-03 11:49:30 +08:00 committed by Alistair Francis
parent 19eb69d09a
commit ab348b0982

View file

@ -857,6 +857,55 @@ static int get_physical_address_pmp(CPURISCVState *env, int *prot, hwaddr addr,
return TRANSLATE_SUCCESS;
}
/* Returns 'true' if a svukte address check is needed */
static bool do_svukte_check(CPURISCVState *env, bool first_stage,
int mode, bool virt)
{
/* Svukte extension depends on Sv39. */
if (!(env_archcpu(env)->cfg.ext_svukte ||
!first_stage ||
VM_1_10_SV39 != get_field(env->satp, SATP64_MODE))) {
return false;
}
/*
* Check hstatus.HUKTE if the effective mode is switched to VU-mode by
* executing HLV/HLVX/HSV in U-mode.
* For other cases, check senvcfg.UKTE.
*/
if (env->priv == PRV_U && !env->virt_enabled && virt) {
if (!get_field(env->hstatus, HSTATUS_HUKTE)) {
return false;
}
} else if (!get_field(env->senvcfg, SENVCFG_UKTE)) {
return false;
}
/*
* Svukte extension is qualified only in U or VU-mode.
*
* Effective mode can be switched to U or VU-mode by:
* - M-mode + mstatus.MPRV=1 + mstatus.MPP=U-mode.
* - Execute HLV/HLVX/HSV from HS-mode + hstatus.SPVP=0.
* - U-mode.
* - VU-mode.
* - Execute HLV/HLVX/HSV from U-mode + hstatus.HU=1.
*/
if (mode != PRV_U) {
return false;
}
return true;
}
static bool check_svukte_addr(CPURISCVState *env, vaddr addr)
{
/* svukte extension excludes RV32 */
uint32_t sxlen = 32 * riscv_cpu_sxl(env);
uint64_t high_bit = addr & (1UL << (sxlen - 1));
return !high_bit;
}
/*
* get_physical_address - get the physical address for this virtual address
*
@ -894,6 +943,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
MemTxResult res;
MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
int mode = mmuidx_priv(mmu_idx);
bool virt = mmuidx_2stage(mmu_idx);
bool use_background = false;
hwaddr ppn;
int napot_bits = 0;
@ -901,6 +951,11 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
bool is_sstack_idx = ((mmu_idx & MMU_IDX_SS_WRITE) == MMU_IDX_SS_WRITE);
bool sstack_page = false;
if (do_svukte_check(env, first_stage, mode, virt) &&
!check_svukte_addr(env, addr)) {
return TRANSLATE_FAIL;
}
/*
* Check if we should use the background registers for the two
* stage translation. We don't need to check if we actually need