We need to fault during any access done while PTE bits 62-61 are both set, according to the RISC-V priv spec.
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3494 Signed-off-by: Daniel Henrique Barboza <[email protected]> --- target/riscv/cpu_helper.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 17305e1bb7..bc63713ddf 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -1446,6 +1446,25 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical, return TRANSLATE_FAIL; } + /* + * priv spec, "Svpbmt" chapter: + * "For non-leaf PTEs, bits 62-61 are reserved for future + * standard use. Until their use is defined by a standard + * extension, they must be cleared by software for forward + * compatibility, or else a page-fault exception is raised." + * + * For leaf PTEs the same bits are also reserved but in that + * case the page-fault is mandatory. Make both cases consistent + * by also page faulting here. + */ + if ((pte & PTE_PBMT) == PTE_PBMT) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: PBMT bits 62 and 61 are " + "reserved but are set in PTE: " + "addr: 0x%" HWADDR_PRIx " pte: 0x" TARGET_FMT_lx "\n", + __func__, pte_addr, pte); + return TRANSLATE_FAIL; + } + if (!riscv_cpu_cfg(env)->ext_svnapot && (pte & PTE_N)) { /* Reserved without Svnapot extension */ qemu_log_mask(LOG_GUEST_ERROR, "%s: N bit set in PTE, " @@ -1498,6 +1517,23 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical, return TRANSLATE_FAIL; } + /* + * priv spec, "Svpbmt" chapter: + * "For leaf PTEs, setting bits 62-61 to the value 3 is reserved + * for future standard use. Until this value is defined by a + * standard extension, using this reserved value in a leaf PTE + * raises a page-fault exception. " + * + * Raise a fault if 62-61 (i.e. PTE_PBMT) are set. + */ + if ((pte & PTE_PBMT) == PTE_PBMT) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: PBMT bits 62 and 61 are " + "reserved but are set in leaf PTE: " + "addr: 0x%" HWADDR_PRIx " pte: 0x" TARGET_FMT_lx "\n", + __func__, pte_addr, pte); + return TRANSLATE_FAIL; + } + target_ulong rwx = pte & (PTE_R | PTE_W | PTE_X); /* Check for reserved combinations of RWX flags. */ switch (rwx) { -- 2.43.0
