riscvarchive / riscv-qemu

QEMU with RISC-V (RV64G, RV32G) Emulation Support
384 stars 154 forks source link

PMP address bugs #149

Closed dayeol closed 6 years ago

dayeol commented 6 years ago

Hi, I appreciate your hard work!

I found two bugs in pmp.c

(1) A legitimate memory access fails and complains "pmp violation - access is partially inside"

In function pmp_hart_has_privs(), following code

e = pmp_is_in_range(env, i, addr + size);

should be changed to

e = pmp_is_in_range(env, i, addr + size - 1);

because the ending address of the pmp range (i.e., pmp_state.addr[i].ea) is set to the last address in the range.

For example, assume that a PMP range is 4KB from 0x87654000 such that the last address within the range is 0x87654fff. 1-byte access to 0x87654fff should be considered to be fully inside the PMP range. However the access now fails and complains partial inclusion because pmp_is _in_range(env, i, addr + size) returns 0 whereas pmp_is_in_range(env, i, addr) returns 1.

(2) Wrong NAPOT decoding in pmp_decode_napot()

According to the RISC-V priv. v1.10 ISA document and these slides, pmpaddr register stores (base_addr | (size/2 - 1)) >> 2 for a NAPOT-encoded address. However, the current code decodes (base_addr | (size - 1)) >> 3 which leads to a wrong base address and size.

Created a pull request for this issue. Please review!

dayeol commented 6 years ago

Resolved with #153