static MemoryRegionSection address_space_do_translate(AddressSpace *as,

                                                      hwaddr addr,

                                                      hwaddr *xlat,

                                                      hwaddr *plen,

                                                      bool is_write,

                                                      bool is_mmio)

{

    IOMMUTLBEntry iotlb;

    MemoryRegionSection *section;

    MemoryRegion *mr;



    for (;;) {

        AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch);

        section = address_space_translate_internal(d, addr, &addr, plen, is_mmio);

        mr = section->mr;



        if (!mr->iommu_ops) {

            break;

        }



        iotlb = mr->iommu_ops->translate(mr, addr, is_write);

        addr = ((iotlb.translated_addr & ~iotlb.addr_mask)

                | (addr & iotlb.addr_mask));

        *plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1);

        if (!(iotlb.perm & (1 << is_write))) {

            goto translate_fail;

        }



        as = iotlb.target_as;

    }



    *xlat = addr;



    return *section;



translate_fail:

    return (MemoryRegionSection) { .mr = &io_mem_unassigned };

}

static MemoryRegionSection address_space_do_translate(AddressSpace *as,

                                                      hwaddr addr,

                                                      hwaddr *xlat,

                                                      hwaddr *plen,

                                                      bool is_write,

                                                      bool is_mmio)

{

    IOMMUTLBEntry iotlb;

    MemoryRegionSection *section;

    MemoryRegion *mr;



    for (;;) {

        AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch);

        section = address_space_translate_internal(d, addr, &addr, plen, is_mmio);

        mr = section->mr;



        if (!mr->iommu_ops) {

            break;

        }



        iotlb = mr->iommu_ops->translate(mr, addr, is_write);

        addr = ((iotlb.translated_addr & ~iotlb.addr_mask)

                | (addr & iotlb.addr_mask));

        *plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1);

        if (!(iotlb.perm & (1 << is_write))) {

            goto translate_fail;

        }



        as = iotlb.target_as;

    }



    *xlat = addr;



    return *section;



translate_fail:

    return (MemoryRegionSection) { .mr = &io_mem_unassigned };

}

static MemoryRegionSection FUNC_0(AddressSpace *as,

                                                      hwaddr addr,

                                                      hwaddr *xlat,

                                                      hwaddr *plen,

                                                      bool is_write,

                                                      bool is_mmio)

{

    IOMMUTLBEntry iotlb;

    MemoryRegionSection *section;

    MemoryRegion *mr;



    for (;;) {

        AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch);

        section = address_space_translate_internal(d, addr, &addr, plen, is_mmio);

        mr = section->mr;



        if (!mr->iommu_ops) {

            break;

        }



        iotlb = mr->iommu_ops->translate(mr, addr, is_write);

        addr = ((iotlb.translated_addr & ~iotlb.addr_mask)

                | (addr & iotlb.addr_mask));

        *plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1);

        if (!(iotlb.perm & (1 << is_write))) {

            goto translate_fail;

        }



        as = iotlb.target_as;

    }



    *xlat = addr;



    return *section;



translate_fail:

    return (MemoryRegionSection) { .mr = &io_mem_unassigned };

}

static MemoryRegionSection FUNC_0(AddressSpace *as,
hwaddr addr,
hwaddr *xlat,
hwaddr *plen,
bool is_write,
bool is_mmio)
{ IOMMUTLBEntry iotlb; MemoryRegionSection *section; MemoryRegion *mr; for (;;) { AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch); section = address_space_translate_internal(d, addr, &addr, plen, is_mmio); mr = section->mr; if (!mr->iommu_ops) { break; } iotlb = mr->iommu_ops->translate(mr, addr, is_write); addr = ((iotlb.translated_addr & ~iotlb.addr_mask)
| (addr & iotlb.addr_mask)); *plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1); if (!(iotlb.perm & (1 << is_write))) { goto translate_fail; } as = iotlb.target_as; } *xlat = addr; return *section; translate_fail:
return (MemoryRegionSection) { .mr = &io_mem_unassigned }; }