aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorHesham Almatary <Hesham.Almatary@cl.cam.ac.uk>2019-05-30 14:51:34 +0100
committerPalmer Dabbelt <palmer@sifive.com>2019-06-23 23:44:42 -0700
commitf8162068f18f2f264a0355938784f54089234211 (patch)
treefea319920a4f27af65a6d64ab573e74fdcc1a7d5 /target
parent1f447aec787bfbbd078afccae44fc4c92acb4fed (diff)
downloadqemu-f8162068f18f2f264a0355938784f54089234211.zip
qemu-f8162068f18f2f264a0355938784f54089234211.tar.gz
qemu-f8162068f18f2f264a0355938784f54089234211.tar.bz2
RISC-V: Fix a PMP bug where it succeeds even if PMP entry is off
The current implementation returns 1 (PMP check success) if the address is in range even if the PMP entry is off. This is a bug. For example, if there is a PMP check in S-Mode which is in range, but its PMP entry is off, this will succeed, which it should not. The patch fixes this bug by only checking the PMP permissions if the address is in range and its corresponding PMP entry it not off. Otherwise, it will keep the ret = -1 which will be checked and handled correctly at the end of the function. 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>
Diffstat (limited to 'target')
-rw-r--r--target/riscv/pmp.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
index 5944f4c..958c750 100644
--- a/target/riscv/pmp.c
+++ b/target/riscv/pmp.c
@@ -258,11 +258,12 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr,
/* fully inside */
const uint8_t a_field =
pmp_get_a_field(env->pmp_state.pmp[i].cfg_reg);
- if ((s + e) == 2) {
- if (PMP_AMATCH_OFF == a_field) {
- return 1;
- }
+ /*
+ * If the PMP entry is not off and the address is in range, do the priv
+ * check
+ */
+ if (((s + e) == 2) && (PMP_AMATCH_OFF != a_field)) {
allowed_privs = PMP_READ | PMP_WRITE | PMP_EXEC;
if ((mode != PRV_M) || pmp_is_locked(env, i)) {
allowed_privs &= env->pmp_state.pmp[i].cfg_reg;