On Thu, Nov 14, 2024 at 4:57 PM Jason Chien <jason.ch...@sifive.com> wrote: > > From RISCV IOMMU spec section 2.1.3: > When SXL is 1, the following rules apply: > - If the first-stage is not Bare, then a page fault corresponding to the > original access type occurs if the IOVA has bits beyond bit 31 set to 1. > - If the second-stage is not Bare, then a guest page fault corresponding > to the original access type occurs if the incoming GPA has bits beyond bit > 33 set to 1. > > From RISCV IOMMU spec section 2.3 step 17: > Use the process specified in Section "Two-Stage Address Translation" of > the RISC-V Privileged specification to determine the GPA accessed by the > transaction. > > From RISCV IOMMU spec section 2.3 step 19: > Use the second-stage address translation process specified in Section > "Two-Stage Address Translation" of the RISC-V Privileged specification > to translate the GPA A to determine the SPA accessed by the transaction. > > This commit adds the iova check with the following rules: > - For Sv32, Sv32x4, Sv39x4, Sv48x4 and Sv57x4, the iova must be zero > extended. > - For Sv39, Sv48 and Sv57, the iova must be signed extended with most > significant bit. > > Signed-off-by: Jason Chien <jason.ch...@sifive.com> > Reviewed-by: Daniel Henrique Barboza <dbarb...@ventanamicro.com>
Thanks! Applied to riscv-to-apply.next Alistair > --- > hw/riscv/riscv-iommu.c | 23 ++++++++++++++++++++--- > 1 file changed, 20 insertions(+), 3 deletions(-) > > diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c > index bbc95425b3..ff9deefe37 100644 > --- a/hw/riscv/riscv-iommu.c > +++ b/hw/riscv/riscv-iommu.c > @@ -392,9 +392,26 @@ static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, > RISCVIOMMUContext *ctx, > > /* Address range check before first level lookup */ > if (!sc[pass].step) { > - const uint64_t va_mask = (1ULL << (va_skip + va_bits)) - 1; > - if ((addr & va_mask) != addr) { > - return RISCV_IOMMU_FQ_CAUSE_DMA_DISABLED; > + const uint64_t va_len = va_skip + va_bits; > + const uint64_t va_mask = (1ULL << va_len) - 1; > + > + if (pass == S_STAGE && va_len > 32) { > + target_ulong mask, masked_msbs; > + > + mask = (1L << (TARGET_LONG_BITS - (va_len - 1))) - 1; > + masked_msbs = (addr >> (va_len - 1)) & mask; > + > + if (masked_msbs != 0 && masked_msbs != mask) { > + return (iotlb->perm & IOMMU_WO) ? > + RISCV_IOMMU_FQ_CAUSE_WR_FAULT_S : > + RISCV_IOMMU_FQ_CAUSE_RD_FAULT_S; > + } > + } else { > + if ((addr & va_mask) != addr) { > + return (iotlb->perm & IOMMU_WO) ? > + RISCV_IOMMU_FQ_CAUSE_WR_FAULT_VS : > + RISCV_IOMMU_FQ_CAUSE_RD_FAULT_VS; > + } > } > } > > -- > 2.43.2 > >