diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index feb650549a..12f01a75f5 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -183,8 +183,25 @@ static void riscv_iommu_pri(RISCVIOMMUState *s, } } -/* Portable implementation of pext_u64, bit-mask extraction. */ -static uint64_t _pext_u64(uint64_t val, uint64_t ext) +/* + * Discards all bits from 'val' whose matching bits in the same + * positions in the mask 'ext' are zeros, and packs the remaining + * bits from 'val' contiguously at the least-significant end of the + * result, keeping the same bit order as 'val' and filling any + * other bits at the most-significant end of the result with zeros. + * + * For example, for the following 'val' and 'ext', the return 'ret' + * will be: + * + * val = a b c d e f g h + * ext = 1 0 1 0 0 1 1 0 + * ret = 0 0 0 0 a c f g + * + * This function, taken from the riscv-iommu 1.0 spec, section 2.3.3 + * "Process to translate addresses of MSIs", is similar to bit manip + * function PEXT (Parallel bits extract) from x86. + */ +static uint64_t riscv_iommu_pext_u64(uint64_t val, uint64_t ext) { uint64_t ret = 0; uint64_t rot = 1; @@ -528,7 +545,7 @@ static MemTxResult riscv_iommu_msi_write(RISCVIOMMUState *s, int cause; /* Interrupt File Number */ - intn = _pext_u64(PPN_DOWN(gpa), ctx->msi_addr_mask); + intn = riscv_iommu_pext_u64(PPN_DOWN(gpa), ctx->msi_addr_mask); if (intn >= 256) { /* Interrupt file number out of range */ res = MEMTX_ACCESS_ERROR;