Skip to content

Commit ab2d6e7

Browse files
danielhbMichael Tokarev
authored andcommitted
target/riscv: prioritize pmp errors in raise_mmu_exception()
raise_mmu_exception(), as is today, is prioritizing guest page faults by checking first if virt_enabled && !first_stage, and then considering the regular inst/load/store faults. There's no mention in the spec about guest page fault being a higher priority that PMP faults. In fact, privileged spec section 3.7.1 says: "Attempting to fetch an instruction from a PMP region that does not have execute permissions raises an instruction access-fault exception. Attempting to execute a load or load-reserved instruction which accesses a physical address within a PMP region without read permissions raises a load access-fault exception. Attempting to execute a store, store-conditional, or AMO instruction which accesses a physical address within a PMP region without write permissions raises a store access-fault exception." So, in fact, we're doing it wrong - PMP faults should always be thrown, regardless of also being a first or second stage fault. The way riscv_cpu_tlb_fill() and get_physical_address() work is adequate: a TRANSLATE_PMP_FAIL error is immediately reported and reflected in the 'pmp_violation' flag. What we need is to change raise_mmu_exception() to prioritize it. Reported-by: Joseph Chan <[email protected]> Fixes: 82d53ad ("target/riscv/cpu_helper.c: Invalid exception on MMU translation stage") Signed-off-by: Daniel Henrique Barboza <[email protected]> Reviewed-by: Alistair Francis <[email protected]> Message-ID: <[email protected]> Cc: qemu-stable <[email protected]> Signed-off-by: Alistair Francis <[email protected]> (cherry picked from commit 68e7c86) Signed-off-by: Michael Tokarev <[email protected]>
1 parent 3ee5f0e commit ab2d6e7

File tree

1 file changed

+12
-10
lines changed

1 file changed

+12
-10
lines changed

target/riscv/cpu_helper.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,28 +1176,30 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
11761176

11771177
switch (access_type) {
11781178
case MMU_INST_FETCH:
1179-
if (env->virt_enabled && !first_stage) {
1179+
if (pmp_violation) {
1180+
cs->exception_index = RISCV_EXCP_INST_ACCESS_FAULT;
1181+
} else if (env->virt_enabled && !first_stage) {
11801182
cs->exception_index = RISCV_EXCP_INST_GUEST_PAGE_FAULT;
11811183
} else {
1182-
cs->exception_index = pmp_violation ?
1183-
RISCV_EXCP_INST_ACCESS_FAULT : RISCV_EXCP_INST_PAGE_FAULT;
1184+
cs->exception_index = RISCV_EXCP_INST_PAGE_FAULT;
11841185
}
11851186
break;
11861187
case MMU_DATA_LOAD:
1187-
if (two_stage && !first_stage) {
1188+
if (pmp_violation) {
1189+
cs->exception_index = RISCV_EXCP_LOAD_ACCESS_FAULT;
1190+
} else if (two_stage && !first_stage) {
11881191
cs->exception_index = RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT;
11891192
} else {
1190-
cs->exception_index = pmp_violation ?
1191-
RISCV_EXCP_LOAD_ACCESS_FAULT : RISCV_EXCP_LOAD_PAGE_FAULT;
1193+
cs->exception_index = RISCV_EXCP_LOAD_PAGE_FAULT;
11921194
}
11931195
break;
11941196
case MMU_DATA_STORE:
1195-
if (two_stage && !first_stage) {
1197+
if (pmp_violation) {
1198+
cs->exception_index = RISCV_EXCP_STORE_AMO_ACCESS_FAULT;
1199+
} else if (two_stage && !first_stage) {
11961200
cs->exception_index = RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT;
11971201
} else {
1198-
cs->exception_index = pmp_violation ?
1199-
RISCV_EXCP_STORE_AMO_ACCESS_FAULT :
1200-
RISCV_EXCP_STORE_PAGE_FAULT;
1202+
cs->exception_index = RISCV_EXCP_STORE_PAGE_FAULT;
12011203
}
12021204
break;
12031205
default:

0 commit comments

Comments
 (0)