mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-08 02:03:56 -06:00
hw/riscv/riscv-iommu.c: Correct the validness check of iova
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.chien@sifive.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Message-ID: <20241114065617.25133-1-jason.chien@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
parent
3e9793ab01
commit
e5d28bf2b3
1 changed files with 20 additions and 3 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue