Message ID | 20191022212129.8452-1-dayeol@berkeley.edu |
---|---|
State | New |
Headers | show |
Series | target/riscv: PMP violation due to wrong size parameter | expand |
On Tue, 22 Oct 2019 14:21:29 PDT (-0700), dayeol@berkeley.edu wrote: > riscv_cpu_tlb_fill() uses the `size` parameter to check PMP violation > using pmp_hart_has_privs(). > However, if the size is unknown (=0), the ending address will be > `addr - 1` as it is `addr + size - 1` in `pmp_hart_has_privs()`. > This always causes a false PMP violation on the starting address of the > range, as `addr - 1` is not in the range. > > In order to fix, we just assume that all bytes from addr to the end of > the page will be accessed if the size is unknown. > > Signed-off-by: Dayeol Lee <dayeol@berkeley.edu> > Reviewed-by: Richard Henderson <richard.henderson@linaro.org> > --- > target/riscv/pmp.c | 13 ++++++++++++- > 1 file changed, 12 insertions(+), 1 deletion(-) > > diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c > index 958c7502a0..7a9fd415ba 100644 > --- a/target/riscv/pmp.c > +++ b/target/riscv/pmp.c > @@ -232,6 +232,7 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr, > { > int i = 0; > int ret = -1; > + int pmp_size = 0; > target_ulong s = 0; > target_ulong e = 0; > pmp_priv_t allowed_privs = 0; > @@ -241,11 +242,21 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr, > return true; > } > > + /* > + * if size is unknown (0), assume that all bytes > + * from addr to the end of the page will be accessed. > + */ > + if (size == 0) { > + pmp_size = -(addr | TARGET_PAGE_MASK); > + } else { > + pmp_size = size; > + } > + > /* 1.10 draft priv spec states there is an implicit order > from low to high */ > 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, addr + pmp_size - 1); > > /* partially inside */ > if ((s + e) == 1) { Thanks. I've queued this up for my next pull request.
diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c index 958c7502a0..7a9fd415ba 100644 --- a/target/riscv/pmp.c +++ b/target/riscv/pmp.c @@ -232,6 +232,7 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr, { int i = 0; int ret = -1; + int pmp_size = 0; target_ulong s = 0; target_ulong e = 0; pmp_priv_t allowed_privs = 0; @@ -241,11 +242,21 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr, return true; } + /* + * if size is unknown (0), assume that all bytes + * from addr to the end of the page will be accessed. + */ + if (size == 0) { + pmp_size = -(addr | TARGET_PAGE_MASK); + } else { + pmp_size = size; + } + /* 1.10 draft priv spec states there is an implicit order from low to high */ 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, addr + pmp_size - 1); /* partially inside */ if ((s + e) == 1) {