@samitouri / QOSamiQemu / commits / b795ea0ba4

hw/riscv/riscv-iommu.c: fault when !PTE_U and no priv access

All IOMMU accesses are assumed to be user mode unless told otherwise, i.e. we have a process_id. In case we have a non-user mode leaf PTE (PTE_U isn't set) and we are running in user mode, we need to throw a fault. This also reflects on qos-riscv-iommu tests: the tests always run in user mode so our PTEs must have PTE_U (bit 0x10) set. Fixes: 0c54acb8243d ("hw/riscv: add RISC-V IOMMU base emulation") Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3553 Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Nutty Liu <nutty.liu@hotmail.com> Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com> Message-ID: <20260701121111.537654-3-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>

Daniel Henrique Barboza committed Jul 1, 2026 at 09:11 UTC b795ea0ba4715182805994db0cdabd2650a553a7
2 files changed +10 -2
hw/riscv/riscv-iommu.c
+8
@@ -298,6 +298,7 @@ static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, RISCVIOMMUContext *ctx,
298 G_STAGE = 1,
299 } pass;
300 MemTxResult ret;
301 + bool pv = !!ctx->process_id;
302
303 satp = get_field(ctx->satp, RISCV_IOMMU_ATP_MODE_FIELD);
304 gatp = get_field(ctx->gatp, RISCV_IOMMU_ATP_MODE_FIELD);
@@ -471,6 +472,13 @@ static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, RISCVIOMMUContext *ctx,
472 break; /* Invalid PTE */
473 } else if (pte & PTE_RESERVED(false)) {
474 break; /* Reserved PTE bits set */
475 + } else if (!(pte & PTE_U) && !pv) {
476 + /*
477 + * All accesses are assumed to be User mode unless
478 + * process_id is valid (pv). In case we have a
479 + * non-user mode PTE and !pv we need to fault.
480 + */
481 + break;
482 } else if (!(pte & (PTE_R | PTE_W | PTE_X))) {
483 base = PPN_PHYS(ppn); /* Inner PTE, continue walking */
484 } else if ((pte & (PTE_R | PTE_W | PTE_X)) == PTE_W) {
tests/qtest/libqos/qos-riscv-iommu.h
+2 -2
@@ -54,8 +54,8 @@
54 * PTE masks for RISC-V IOMMU page tables.
55 * Values match PTE_V, PTE_R, PTE_W, PTE_A, PTE_D in target/riscv/cpu_bits.h
56 */
57 -#define QRIOMMU_NON_LEAF_PTE_MASK 0x001 /* PTE_V */
58 -#define QRIOMMU_LEAF_PTE_RW_MASK 0x0c7 /* V|R|W|A|D */
57 +#define QRIOMMU_NON_LEAF_PTE_MASK 0x011 /* PTE_V | PTE_U */
58 +#define QRIOMMU_LEAF_PTE_RW_MASK 0x0d7 /* V | R | W | A | D | PTE_U */
59 #define QRIOMMU_PTE_PPN_MASK 0x003ffffffffffc00ull
60
61 /* Address-space base offset for test tables */