[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v2 1/1] target/riscv/pmp: Fix bug preventing

From: Chris Williams
Subject: [PATCH v2 1/1] target/riscv/pmp: Fix bug preventing
Date: Sun, 6 Oct 2019 10:32:06 +0200 (CEST)

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 <address@hidden <mailto:address@hidden>>

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
     /* 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) {

reply via email to

[Prev in Thread] Current Thread [Next in Thread]