RISC-V: Raise access fault exceptions on PMP violations
Section 3.6 in RISC-V v1.10 privilege specification states that PMP violations report "access exceptions." The current PMP implementation has a bug which wrongly reports "page exceptions" on PMP violations. This patch fixes this bug by reporting the correct PMP access exceptions trap values. Signed-off-by: Hesham Almatary <Hesham.Almatary@cl.cam.ac.uk> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
This commit is contained in:
parent
e0f8fa72de
commit
635b0b0ea3
|
@ -337,12 +337,13 @@ restart:
|
||||||
}
|
}
|
||||||
|
|
||||||
static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
|
static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
|
||||||
MMUAccessType access_type)
|
MMUAccessType access_type, bool pmp_violation)
|
||||||
{
|
{
|
||||||
CPUState *cs = env_cpu(env);
|
CPUState *cs = env_cpu(env);
|
||||||
int page_fault_exceptions =
|
int page_fault_exceptions =
|
||||||
(env->priv_ver >= PRIV_VERSION_1_10_0) &&
|
(env->priv_ver >= PRIV_VERSION_1_10_0) &&
|
||||||
get_field(env->satp, SATP_MODE) != VM_1_10_MBARE;
|
get_field(env->satp, SATP_MODE) != VM_1_10_MBARE &&
|
||||||
|
!pmp_violation;
|
||||||
switch (access_type) {
|
switch (access_type) {
|
||||||
case MMU_INST_FETCH:
|
case MMU_INST_FETCH:
|
||||||
cs->exception_index = page_fault_exceptions ?
|
cs->exception_index = page_fault_exceptions ?
|
||||||
|
@ -424,6 +425,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||||
CPURISCVState *env = &cpu->env;
|
CPURISCVState *env = &cpu->env;
|
||||||
hwaddr pa = 0;
|
hwaddr pa = 0;
|
||||||
int prot;
|
int prot;
|
||||||
|
bool pmp_violation = false;
|
||||||
int ret = TRANSLATE_FAIL;
|
int ret = TRANSLATE_FAIL;
|
||||||
|
|
||||||
qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
|
qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
|
||||||
|
@ -438,6 +440,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||||
if (riscv_feature(env, RISCV_FEATURE_PMP) &&
|
if (riscv_feature(env, RISCV_FEATURE_PMP) &&
|
||||||
(ret == TRANSLATE_SUCCESS) &&
|
(ret == TRANSLATE_SUCCESS) &&
|
||||||
!pmp_hart_has_privs(env, pa, TARGET_PAGE_SIZE, 1 << access_type)) {
|
!pmp_hart_has_privs(env, pa, TARGET_PAGE_SIZE, 1 << access_type)) {
|
||||||
|
pmp_violation = true;
|
||||||
ret = TRANSLATE_FAIL;
|
ret = TRANSLATE_FAIL;
|
||||||
}
|
}
|
||||||
if (ret == TRANSLATE_SUCCESS) {
|
if (ret == TRANSLATE_SUCCESS) {
|
||||||
|
@ -447,7 +450,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||||
} else if (probe) {
|
} else if (probe) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
raise_mmu_exception(env, address, access_type);
|
raise_mmu_exception(env, address, access_type, pmp_violation);
|
||||||
riscv_raise_exception(env, cs->exception_index, retaddr);
|
riscv_raise_exception(env, cs->exception_index, retaddr);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
Loading…
Reference in a new issue