> -----Original Message-----
> From: Ankit Agrawal <[email protected]>
> Sent: 30 January 2026 04:07
> To: Ankit Agrawal <[email protected]>; Vikram Sethi <[email protected]>;
> Jason Gunthorpe <[email protected]>; Shameer Kolothum Thodi
> <[email protected]>; [email protected]; [email protected]
> Cc: Aniket Agashe <[email protected]>; Neo Jia <[email protected]>; Kirti
> Wankhede <[email protected]>; Tarun Gupta (SW-GPU)
> <[email protected]>; Zhi Wang <[email protected]>; Matt Ochs
> <[email protected]>; Krishnakant Jaju <[email protected]>; qemu-
> [email protected]
> Subject: [PATCH v1 1/2] hw/vfio: sort and validate sparse mmap regions by
> offset
> 
> From: Ankit Agrawal <[email protected]>
> 
> Sort sparse mmap regions by offset during region setup to ensure
> predictable mapping order, avoid overlaps and a proper handling
> of the gaps between sub-regions.
> 
> Add validation to detect overlapping sparse regions early during
> setup before any mapping operations begin.
> 
> The sorting is performed on the subregions ranges during
> vfio_setup_region_sparse_mmaps(). This also ensures that subsequent
> mapping code can rely on subregions being in ascending offset order.
> 
> This is preparatory work for alignment adjustments needed to support
> hugepfnmap on systems where device memory (e.g., Grace-based systems)
> may have non-power-of-2 sizes.
> 
> cc: Alex Williamson <[email protected]>
> Signed-off-by: Ankit Agrawal <[email protected]>
> ---
>  hw/vfio/region.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 44 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/vfio/region.c b/hw/vfio/region.c
> index ab39d77574..7622ae5683 100644
> --- a/hw/vfio/region.c
> +++ b/hw/vfio/region.c
> @@ -149,6 +149,19 @@ static const MemoryRegionOps vfio_region_ops = {
>      },
>  };
> 
> +static int vfio_mmap_compare_offset(const void *a, const void *b)
> +{
> +    const VFIOMmap *mmap_a = a;
> +    const VFIOMmap *mmap_b = b;
> +
> +    if (mmap_a->offset < mmap_b->offset) {
> +        return -1;
> +    } else if (mmap_a->offset > mmap_b->offset) {
> +        return 1;
> +    }
> +    return 0;
> +}
> +
>  static int vfio_setup_region_sparse_mmaps(VFIORegion *region,
>                                            struct vfio_region_info *info)
>  {
> @@ -182,6 +195,34 @@ static int
> vfio_setup_region_sparse_mmaps(VFIORegion *region,
>      region->nr_mmaps = j;
>      region->mmaps = g_realloc(region->mmaps, j * sizeof(VFIOMmap));
> 
> +    /*
> +     * Sort sparse mmaps by offset to ensure proper handling of gaps
> +     * and predictable mapping order in vfio_region_mmap().
> +     */
> +    if (region->nr_mmaps > 1) {
> +        qsort(region->mmaps, region->nr_mmaps, sizeof(VFIOMmap),
> +              vfio_mmap_compare_offset);
> +
> +        /*
> +         * Validate that sparse regions dont overlap after sorting.
> +         */
> +        for (i = 1; i < region->nr_mmaps; i++) {
> +            off_t prev_end = region->mmaps[i - 1].offset +
> +                             region->mmaps[i - 1].size;
> +            if (prev_end > region->mmaps[i].offset) {
> +                error_report("%s: overlapping sparse mmap regions detected "
> +                             "in region %d: [0x%lx-0x%lx] overlaps with 
> [0x%lx-0x%lx]",
> +                             __func__, region->nr, region->mmaps[i - 
> 1].offset,
> +                             prev_end - 1, region->mmaps[i].offset,
> +                             region->mmaps[i].offset + region->mmaps[i].size 
> - 1);
> +                g_free(region->mmaps);
> +                region->mmaps = NULL;
> +                region->nr_mmaps = 0;
> +                return -EINVAL;
> +            }
> +        }
> +    }
> +
>      return 0;
>  }
> 
> @@ -213,11 +254,13 @@ int vfio_region_setup(Object *obj, VFIODevice
> *vbasedev, VFIORegion *region,
> 
>              ret = vfio_setup_region_sparse_mmaps(region, info);
> 
> -            if (ret) {
> +            if (ret == -ENODEV) {
>                  region->nr_mmaps = 1;
>                  region->mmaps = g_new0(VFIOMmap, region->nr_mmaps);
>                  region->mmaps[0].offset = 0;
>                  region->mmaps[0].size = region->size;
> +            } else {
> +                return ret;
>              }

Is this now returns without the trace_xxx , right?

With that fixed:
Reviewed-by: Shameer Kolothum <[email protected]>

Thanks,
Shameer

>          }
>      }
> --
> 2.34.1


Reply via email to