@@ -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;
+ }
}
}