func: 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 };
  
  }
  