Hello. I hope you don't mind me resubmitting this patch. Please let me know if I've formatted it incorrectly or if it needs more explanation. My previous attempt probably wasn't formatted quite right. This is my first time contributing to Qemu, so I'm keen to get it right - thanks.
This fixes an issue that prevents a RISC-V CPU from executing instructions immediately from the base address of a PMP TOR region. When jumping to an instruction in a PMP TOR region, pmp_hart_has_privs() is called to validate the access. If this instruction is the very first word of a PMP TOR region, at address 0 relative to the start address of the region, then the access will fail. This is because pmp_hart_has_privs() is called with size 0 to perform this validation, causing this check... e = pmp_is_in_range(env, i, addr + size - 1); ... to fail, as (addr + size - 1) falls below the base address of the PMP region. Really, the access should succeed. For example, if I have a region spanning 0x80d96000 to 0x88d95fff and the CPU jumps to 0x80d96000, then: s = 0x80d96000 e = 0x80d95fff And the validation fails. The size check proposed below catches these zero-size instruction fetch access probes. The word alignment in pmpaddr{0-15} and earlier instruction alignment checks should prevent the execution of instructions over the upper boundary of the PMP region, though I'm happy to give this more attention if this is a concern. Signed-off-by: Chris Williams <diodes...@tuta.io <mailto:diodes...@tuta.io>> diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c index d4f1007109..9308672e20 100644 --- a/target/riscv/pmp.c +++ b/target/riscv/pmp.c @@ -235,8 +235,9 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr, /* 1.10 draft priv spec states there is an implicit order from low to high */ for (i = 0; i < MAX_RISCV_PMPS; i++) { + /* catch zero-size instruction checks */ s = pmp_is_in_range(env, i, addr); - e = pmp_is_in_range(env, i, addr + size - 1); + e = pmp_is_in_range(env, i, (size == 0) ? addr : addr + size - 1); /* partially inside */ if ((s + e) == 1) {