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:
Hesham Almatary 2019-06-14 05:17:28 -07:00 committed by Palmer Dabbelt
parent e0f8fa72de
commit 635b0b0ea3
No known key found for this signature in database
GPG key ID: EF4CA1502CCBAB41

View file

@ -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