target/riscv/cpu_helper.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+)
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 <daniel.barboza@oss.qualcomm.com>
---
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
On Thu, 2026-05-21 at 10:07 -0300, Daniel Henrique Barboza wrote:
> 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
> <daniel.barboza@oss.qualcomm.com>
Thanks!
Applied to riscv-to-apply.next
Alistair
> ---
> 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) {
On Thu, 2026-05-21 at 10:07 -0300, Daniel Henrique Barboza wrote:
> 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
> <daniel.barboza@oss.qualcomm.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Alistair
> ---
> 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) {
© 2016 - 2026 Red Hat, Inc.