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
>
>

Reply via email to