static void vfio_listener_region_add(MemoryListener *listener,

                                     MemoryRegionSection *section)

{

    VFIOContainer *container = container_of(listener, VFIOContainer, listener);

    hwaddr iova, end;

    Int128 llend, llsize;

    void *vaddr;

    int ret;

    VFIOHostDMAWindow *hostwin;

    bool hostwin_found;



    if (vfio_listener_skipped_section(section)) {

        trace_vfio_listener_region_add_skip(

                section->offset_within_address_space,

                section->offset_within_address_space +

                int128_get64(int128_sub(section->size, int128_one())));

        return;

    }



    if (unlikely((section->offset_within_address_space & ~TARGET_PAGE_MASK) !=

                 (section->offset_within_region & ~TARGET_PAGE_MASK))) {

        error_report("%s received unaligned region", __func__);

        return;

    }



    iova = TARGET_PAGE_ALIGN(section->offset_within_address_space);

    llend = int128_make64(section->offset_within_address_space);

    llend = int128_add(llend, section->size);

    llend = int128_and(llend, int128_exts64(TARGET_PAGE_MASK));



    if (int128_ge(int128_make64(iova), llend)) {

        return;

    }

    end = int128_get64(int128_sub(llend, int128_one()));



    if (container->iommu_type == VFIO_SPAPR_TCE_v2_IOMMU) {

        VFIOHostDMAWindow *hostwin;

        hwaddr pgsize = 0;



        /* For now intersections are not allowed, we may relax this later */

        QLIST_FOREACH(hostwin, &container->hostwin_list, hostwin_next) {

            if (ranges_overlap(hostwin->min_iova,

                               hostwin->max_iova - hostwin->min_iova + 1,

                               section->offset_within_address_space,

                               int128_get64(section->size))) {

                ret = -1;

                goto fail;

            }

        }



        ret = vfio_spapr_create_window(container, section, &pgsize);

        if (ret) {

            goto fail;

        }



        vfio_host_win_add(container, section->offset_within_address_space,

                          section->offset_within_address_space +

                          int128_get64(section->size) - 1, pgsize);

    }



    hostwin_found = false;

    QLIST_FOREACH(hostwin, &container->hostwin_list, hostwin_next) {

        if (hostwin->min_iova <= iova && end <= hostwin->max_iova) {

            hostwin_found = true;

            break;

        }

    }



    if (!hostwin_found) {

        error_report("vfio: IOMMU container %p can't map guest IOVA region"

                     " 0x%"HWADDR_PRIx"..0x%"HWADDR_PRIx,

                     container, iova, end);

        ret = -EFAULT;

        goto fail;

    }



    memory_region_ref(section->mr);



    if (memory_region_is_iommu(section->mr)) {

        VFIOGuestIOMMU *giommu;



        trace_vfio_listener_region_add_iommu(iova, end);

        /*

         * FIXME: For VFIO iommu types which have KVM acceleration to

         * avoid bouncing all map/unmaps through qemu this way, this

         * would be the right place to wire that up (tell the KVM

         * device emulation the VFIO iommu handles to use).

         */

        giommu = g_malloc0(sizeof(*giommu));

        giommu->iommu = section->mr;

        giommu->iommu_offset = section->offset_within_address_space -

                               section->offset_within_region;

        giommu->container = container;

        giommu->n.notify = vfio_iommu_map_notify;

        giommu->n.notifier_flags = IOMMU_NOTIFIER_ALL;

        QLIST_INSERT_HEAD(&container->giommu_list, giommu, giommu_next);



        memory_region_register_iommu_notifier(giommu->iommu, &giommu->n);

        memory_region_iommu_replay(giommu->iommu, &giommu->n, false);



        return;

    }



    /* Here we assume that memory_region_is_ram(section->mr)==true */



    vaddr = memory_region_get_ram_ptr(section->mr) +

            section->offset_within_region +

            (iova - section->offset_within_address_space);



    trace_vfio_listener_region_add_ram(iova, end, vaddr);



    llsize = int128_sub(llend, int128_make64(iova));



    ret = vfio_dma_map(container, iova, int128_get64(llsize),

                       vaddr, section->readonly);

    if (ret) {

        error_report("vfio_dma_map(%p, 0x%"HWADDR_PRIx", "

                     "0x%"HWADDR_PRIx", %p) = %d (%m)",

                     container, iova, int128_get64(llsize), vaddr, ret);

        goto fail;

    }



    return;



fail:

    /*

     * On the initfn path, store the first error in the container so we

     * can gracefully fail.  Runtime, there's not much we can do other

     * than throw a hardware error.

     */

    if (!container->initialized) {

        if (!container->error) {

            container->error = ret;

        }

    } else {

        hw_error("vfio: DMA mapping failed, unable to continue");

    }

}

static void vfio_listener_region_add(MemoryListener *listener,

                                     MemoryRegionSection *section)

{

    VFIOContainer *container = container_of(listener, VFIOContainer, listener);

    hwaddr iova, end;

    Int128 llend, llsize;

    void *vaddr;

    int ret;

    VFIOHostDMAWindow *hostwin;

    bool hostwin_found;



    if (vfio_listener_skipped_section(section)) {

        trace_vfio_listener_region_add_skip(

                section->offset_within_address_space,

                section->offset_within_address_space +

                int128_get64(int128_sub(section->size, int128_one())));

        return;

    }



    if (unlikely((section->offset_within_address_space & ~TARGET_PAGE_MASK) !=

                 (section->offset_within_region & ~TARGET_PAGE_MASK))) {

        error_report("%s received unaligned region", __func__);

        return;

    }



    iova = TARGET_PAGE_ALIGN(section->offset_within_address_space);

    llend = int128_make64(section->offset_within_address_space);

    llend = int128_add(llend, section->size);

    llend = int128_and(llend, int128_exts64(TARGET_PAGE_MASK));



    if (int128_ge(int128_make64(iova), llend)) {

        return;

    }

    end = int128_get64(int128_sub(llend, int128_one()));



    if (container->iommu_type == VFIO_SPAPR_TCE_v2_IOMMU) {

        VFIOHostDMAWindow *hostwin;

        hwaddr pgsize = 0;



        

        QLIST_FOREACH(hostwin, &container->hostwin_list, hostwin_next) {

            if (ranges_overlap(hostwin->min_iova,

                               hostwin->max_iova - hostwin->min_iova + 1,

                               section->offset_within_address_space,

                               int128_get64(section->size))) {

                ret = -1;

                goto fail;

            }

        }



        ret = vfio_spapr_create_window(container, section, &pgsize);

        if (ret) {

            goto fail;

        }



        vfio_host_win_add(container, section->offset_within_address_space,

                          section->offset_within_address_space +

                          int128_get64(section->size) - 1, pgsize);

    }



    hostwin_found = false;

    QLIST_FOREACH(hostwin, &container->hostwin_list, hostwin_next) {

        if (hostwin->min_iova <= iova && end <= hostwin->max_iova) {

            hostwin_found = true;

            break;

        }

    }



    if (!hostwin_found) {

        error_report("vfio: IOMMU container %p can't map guest IOVA region"

                     " 0x%"HWADDR_PRIx"..0x%"HWADDR_PRIx,

                     container, iova, end);

        ret = -EFAULT;

        goto fail;

    }



    memory_region_ref(section->mr);



    if (memory_region_is_iommu(section->mr)) {

        VFIOGuestIOMMU *giommu;



        trace_vfio_listener_region_add_iommu(iova, end);

        











        giommu = g_malloc0(sizeof(*giommu));

        giommu->iommu = section->mr;

        giommu->iommu_offset = section->offset_within_address_space -

                               section->offset_within_region;

        giommu->container = container;

        giommu->n.notify = vfio_iommu_map_notify;

        giommu->n.notifier_flags = IOMMU_NOTIFIER_ALL;

        QLIST_INSERT_HEAD(&container->giommu_list, giommu, giommu_next);



        memory_region_register_iommu_notifier(giommu->iommu, &giommu->n);

        memory_region_iommu_replay(giommu->iommu, &giommu->n, false);



        return;

    }



    



    vaddr = memory_region_get_ram_ptr(section->mr) +

            section->offset_within_region +

            (iova - section->offset_within_address_space);



    trace_vfio_listener_region_add_ram(iova, end, vaddr);



    llsize = int128_sub(llend, int128_make64(iova));



    ret = vfio_dma_map(container, iova, int128_get64(llsize),

                       vaddr, section->readonly);

    if (ret) {

        error_report("vfio_dma_map(%p, 0x%"HWADDR_PRIx", "

                     "0x%"HWADDR_PRIx", %p) = %d (%m)",

                     container, iova, int128_get64(llsize), vaddr, ret);

        goto fail;

    }



    return;



fail:

    









    if (!container->initialized) {

        if (!container->error) {

            container->error = ret;

        }

    } else {

        hw_error("vfio: DMA mapping failed, unable to continue");

    }

}

static void FUNC_0(MemoryListener *VAR_0,

                                     MemoryRegionSection *VAR_1)

{

    VFIOContainer *container = container_of(VAR_0, VFIOContainer, VAR_0);

    hwaddr iova, end;

    Int128 llend, llsize;

    void *VAR_2;

    int VAR_3;

    VFIOHostDMAWindow *hostwin;

    bool hostwin_found;



    if (vfio_listener_skipped_section(VAR_1)) {

        trace_vfio_listener_region_add_skip(

                VAR_1->offset_within_address_space,

                VAR_1->offset_within_address_space +

                int128_get64(int128_sub(VAR_1->size, int128_one())));

        return;

    }



    if (unlikely((VAR_1->offset_within_address_space & ~TARGET_PAGE_MASK) !=

                 (VAR_1->offset_within_region & ~TARGET_PAGE_MASK))) {

        error_report("%s received unaligned region", __func__);

        return;

    }



    iova = TARGET_PAGE_ALIGN(VAR_1->offset_within_address_space);

    llend = int128_make64(VAR_1->offset_within_address_space);

    llend = int128_add(llend, VAR_1->size);

    llend = int128_and(llend, int128_exts64(TARGET_PAGE_MASK));



    if (int128_ge(int128_make64(iova), llend)) {

        return;

    }

    end = int128_get64(int128_sub(llend, int128_one()));



    if (container->iommu_type == VFIO_SPAPR_TCE_v2_IOMMU) {

        VFIOHostDMAWindow *hostwin;

        hwaddr pgsize = 0;



        

        QLIST_FOREACH(hostwin, &container->hostwin_list, hostwin_next) {

            if (ranges_overlap(hostwin->min_iova,

                               hostwin->max_iova - hostwin->min_iova + 1,

                               VAR_1->offset_within_address_space,

                               int128_get64(VAR_1->size))) {

                VAR_3 = -1;

                goto fail;

            }

        }



        VAR_3 = vfio_spapr_create_window(container, VAR_1, &pgsize);

        if (VAR_3) {

            goto fail;

        }



        vfio_host_win_add(container, VAR_1->offset_within_address_space,

                          VAR_1->offset_within_address_space +

                          int128_get64(VAR_1->size) - 1, pgsize);

    }



    hostwin_found = false;

    QLIST_FOREACH(hostwin, &container->hostwin_list, hostwin_next) {

        if (hostwin->min_iova <= iova && end <= hostwin->max_iova) {

            hostwin_found = true;

            break;

        }

    }



    if (!hostwin_found) {

        error_report("vfio: IOMMU container %p can't map guest IOVA region"

                     " 0x%"HWADDR_PRIx"..0x%"HWADDR_PRIx,

                     container, iova, end);

        VAR_3 = -EFAULT;

        goto fail;

    }



    memory_region_ref(VAR_1->mr);



    if (memory_region_is_iommu(VAR_1->mr)) {

        VFIOGuestIOMMU *giommu;



        trace_vfio_listener_region_add_iommu(iova, end);

        











        giommu = g_malloc0(sizeof(*giommu));

        giommu->iommu = VAR_1->mr;

        giommu->iommu_offset = VAR_1->offset_within_address_space -

                               VAR_1->offset_within_region;

        giommu->container = container;

        giommu->n.notify = vfio_iommu_map_notify;

        giommu->n.notifier_flags = IOMMU_NOTIFIER_ALL;

        QLIST_INSERT_HEAD(&container->giommu_list, giommu, giommu_next);



        memory_region_register_iommu_notifier(giommu->iommu, &giommu->n);

        memory_region_iommu_replay(giommu->iommu, &giommu->n, false);



        return;

    }



    



    VAR_2 = memory_region_get_ram_ptr(VAR_1->mr) +

            VAR_1->offset_within_region +

            (iova - VAR_1->offset_within_address_space);



    trace_vfio_listener_region_add_ram(iova, end, VAR_2);



    llsize = int128_sub(llend, int128_make64(iova));



    VAR_3 = vfio_dma_map(container, iova, int128_get64(llsize),

                       VAR_2, VAR_1->readonly);

    if (VAR_3) {

        error_report("vfio_dma_map(%p, 0x%"HWADDR_PRIx", "

                     "0x%"HWADDR_PRIx", %p) = %d (%m)",

                     container, iova, int128_get64(llsize), VAR_2, VAR_3);

        goto fail;

    }



    return;



fail:

    









    if (!container->initialized) {

        if (!container->error) {

            container->error = VAR_3;

        }

    } else {

        hw_error("vfio: DMA mapping failed, unable to continue");

    }

}

static void FUNC_0(MemoryListener *VAR_0,
MemoryRegionSection *VAR_1)
{ VFIOContainer *container = container_of(VAR_0, VFIOContainer, VAR_0); hwaddr iova, end; Int128 llend, llsize; void *VAR_2; int VAR_3; VFIOHostDMAWindow *hostwin; bool hostwin_found; if (vfio_listener_skipped_section(VAR_1)) { trace_vfio_listener_region_add_skip(
VAR_1->offset_within_address_space,
VAR_1->offset_within_address_space +
int128_get64(int128_sub(VAR_1->size, int128_one()))); return; } if (unlikely((VAR_1->offset_within_address_space & ~TARGET_PAGE_MASK) !=
(VAR_1->offset_within_region & ~TARGET_PAGE_MASK))) { error_report("%s received unaligned region", __func__); return; } iova = TARGET_PAGE_ALIGN(VAR_1->offset_within_address_space); llend = int128_make64(VAR_1->offset_within_address_space); llend = int128_add(llend, VAR_1->size); llend = int128_and(llend, int128_exts64(TARGET_PAGE_MASK)); if (int128_ge(int128_make64(iova), llend)) { return; } end = int128_get64(int128_sub(llend, int128_one())); if (container->iommu_type == VFIO_SPAPR_TCE_v2_IOMMU) { VFIOHostDMAWindow *hostwin; hwaddr pgsize = 0; QLIST_FOREACH(hostwin, &container->hostwin_list, hostwin_next) { if (ranges_overlap(hostwin->min_iova,
hostwin->max_iova - hostwin->min_iova + 1,
VAR_1->offset_within_address_space,
int128_get64(VAR_1->size))) { VAR_3 = -1; goto fail; } } VAR_3 = vfio_spapr_create_window(container, VAR_1, &pgsize); if (VAR_3) { goto fail; } vfio_host_win_add(container, VAR_1->offset_within_address_space,
VAR_1->offset_within_address_space +
int128_get64(VAR_1->size) - 1, pgsize); } hostwin_found = false; QLIST_FOREACH(hostwin, &container->hostwin_list, hostwin_next) { if (hostwin->min_iova <= iova && end <= hostwin->max_iova) { hostwin_found = true; break; } } if (!hostwin_found) { error_report("vfio: IOMMU container %p can't map guest IOVA region"
" 0x%"HWADDR_PRIx"..0x%"HWADDR_PRIx,
container, iova, end); VAR_3 = -EFAULT; goto fail; } memory_region_ref(VAR_1->mr); if (memory_region_is_iommu(VAR_1->mr)) { VFIOGuestIOMMU *giommu; trace_vfio_listener_region_add_iommu(iova, end); giommu = g_malloc0(sizeof(*giommu)); giommu->iommu = VAR_1->mr; giommu->iommu_offset = VAR_1->offset_within_address_space -
VAR_1->offset_within_region; giommu->container = container; giommu->n.notify = vfio_iommu_map_notify; giommu->n.notifier_flags = IOMMU_NOTIFIER_ALL; QLIST_INSERT_HEAD(&container->giommu_list, giommu, giommu_next); memory_region_register_iommu_notifier(giommu->iommu, &giommu->n); memory_region_iommu_replay(giommu->iommu, &giommu->n, false); return; } VAR_2 = memory_region_get_ram_ptr(VAR_1->mr) +
VAR_1->offset_within_region +
(iova - VAR_1->offset_within_address_space); trace_vfio_listener_region_add_ram(iova, end, VAR_2); llsize = int128_sub(llend, int128_make64(iova)); VAR_3 = vfio_dma_map(container, iova, int128_get64(llsize),
VAR_2, VAR_1->readonly); if (VAR_3) { error_report("vfio_dma_map(%p, 0x%"HWADDR_PRIx", "
"0x%"HWADDR_PRIx", %p) = %d (%m)",
container, iova, int128_get64(llsize), VAR_2, VAR_3); goto fail; } return; fail:
if (!container->initialized) { if (!container->error) { container->error = VAR_3; } } else { hw_error("vfio: DMA mapping failed, unable to continue"); } }