On Mon, Jul 15, 2024 at 7:59 PM Ethan Chen via <qemu-devel@nongnu.org> wrote: > > If the IOMMU granularity is smaller than the TARGET_PAGE size, there may be > multiple entries within the same page. To obtain the correct result, pass > the original address to the IOMMU. > > Similar to the RISC-V PMP solution, the TLB_INVALID_MASK will be set when > there are multiple entries in the same page, ensuring that the IOMMU is > checked on every access. > > Signed-off-by: Ethan Chen <etha...@andestech.com>
Acked-by: Alistair Francis <alistair.fran...@wdc.com> Alistair > --- > accel/tcg/cputlb.c | 20 ++++++++++++++++---- > system/physmem.c | 4 ++++ > 2 files changed, 20 insertions(+), 4 deletions(-) > > diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c > index edb3715017..7df106fea3 100644 > --- a/accel/tcg/cputlb.c > +++ b/accel/tcg/cputlb.c > @@ -1062,8 +1062,23 @@ void tlb_set_page_full(CPUState *cpu, int mmu_idx, > > prot = full->prot; > asidx = cpu_asidx_from_attrs(cpu, full->attrs); > - section = address_space_translate_for_iotlb(cpu, asidx, paddr_page, > + section = address_space_translate_for_iotlb(cpu, asidx, full->phys_addr, > &xlat, &sz, full->attrs, > &prot); > + /* Update page size */ > + full->lg_page_size = ctz64(sz); > + if (full->lg_page_size > TARGET_PAGE_BITS) { > + full->lg_page_size = TARGET_PAGE_BITS; > + } else { > + sz = TARGET_PAGE_SIZE; > + } > + > + is_ram = memory_region_is_ram(section->mr); > + is_romd = memory_region_is_romd(section->mr); > + /* If the translated mr is ram/rom, make xlat align the TARGET_PAGE */ > + if (is_ram || is_romd) { > + xlat &= TARGET_PAGE_MASK; > + } > + > assert(sz >= TARGET_PAGE_SIZE); > > tlb_debug("vaddr=%016" VADDR_PRIx " paddr=0x" HWADDR_FMT_plx > @@ -1076,9 +1091,6 @@ void tlb_set_page_full(CPUState *cpu, int mmu_idx, > read_flags |= TLB_INVALID_MASK; > } > > - is_ram = memory_region_is_ram(section->mr); > - is_romd = memory_region_is_romd(section->mr); > - > if (is_ram || is_romd) { > /* RAM and ROMD both have associated host memory. */ > addend = (uintptr_t)memory_region_get_ram_ptr(section->mr) + xlat; > diff --git a/system/physmem.c b/system/physmem.c > index 2154432cb6..346b015447 100644 > --- a/system/physmem.c > +++ b/system/physmem.c > @@ -702,6 +702,10 @@ address_space_translate_for_iotlb(CPUState *cpu, int > asidx, hwaddr orig_addr, > iotlb = imrc->translate(iommu_mr, addr, IOMMU_NONE, iommu_idx); > addr = ((iotlb.translated_addr & ~iotlb.addr_mask) > | (addr & iotlb.addr_mask)); > + /* Update size */ > + if (iotlb.addr_mask != -1 && *plen > iotlb.addr_mask + 1) { > + *plen = iotlb.addr_mask + 1; > + } > /* Update the caller's prot bits to remove permissions the IOMMU > * is giving us a failure response for. If we get down to no > * permissions left at all we can give up now. > -- > 2.34.1 > >