Allow Qemu guest code to execute from the very start of a PMP range without faulting.
When an instruction is fetched from the first word of a PMP range, pmp_hart_has_privs() is called with a size of zero. This causes pmp_is_in_range() to be called with an address lower than addr, when obtaining a value for e, and a fault is incorrectly generated. This fault was observed by creating a PMP range with RWX access, filling the range with valid code from its base address, and then jumping to the first instruction at the base address. Qemu generates an instruction access fault: the correct behavior is to allow the instruction fetch. This patch checks a size is non-zero before applying a calculation operation that would bring it below addr, and thus erroneously raise a fault. Signed-off-by: Chris Williams <diodes...@tuta.io <mailto:diodes...@tuta.io>> --- target/riscv/pmp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c index 958c7502a0..06f2cd52f0 100644 --- a/target/riscv/pmp.c +++ b/target/riscv/pmp.c @@ -242,10 +242,12 @@ 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 */ + from low to high. Also, catch attempts to check a request + size of zero, and ensure it does not accidentally fail by + checking for an address *below* addr */ for (i = 0; i < MAX_RISCV_PMPS; i++) { 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) { -- 2.20.1