On Fri, Jul 03, 2026 at 12:05:18AM +0800, Yu Zhang wrote:

> @@ -401,10 +402,74 @@ static void hv_iommu_flush_iotlb_all(struct 
> iommu_domain *domain)
>       hv_flush_device_domain(to_hv_iommu_domain(domain));
>  }
>  
> +/*
> + * Calculate the minimal power-of-two aligned range that covers [start, end]
> + * (end is inclusive). Returns a single (page_number, page_mask_shift)
> + * descriptor that may over-flush when the range is not naturally aligned.
> + */
> +static void hv_iommu_calc_flush_range(unsigned long start, unsigned long end,
> +                                    union hv_iommu_flush_va *va)
> +{
> +     unsigned long start_pfn = HVPFN_DOWN(start);
> +     unsigned long last_pfn = HVPFN_UP(end + 1) - 1;

Pedantically end can be ULONG_MAX, you shouldn't be adding to it since
it will overflow.

> +     unsigned long mask_shift, aligned_pfn;
> +
> +     if (start_pfn == last_pfn) {
> +             mask_shift = 0;
> +     } else {
> +             /*
> +              * Find the highest bit position where start_pfn and last_pfn
> +              * differ.  A range aligned to one above that bit is the
> +              * smallest power-of-two region that covers both endpoints.
> +              */
> +             mask_shift = __fls(start_pfn ^ last_pfn) + 1;
> +     }
> +
> +     aligned_pfn = ALIGN_DOWN(start_pfn, 1UL << mask_shift);

I think the whole thing is simpler if it stays using bytes until the end:

        sz_lg2 = __fls(gather->start ^ gather->end);
        if (sz_lg2 < HV_PAGE_SHIFT)
                cmd.sz_lg2 = HV_PAGE_SHIFT;

        page_number = (gather->start & ~(1UL << sz_lg2)) >> HV_PAGE_SHIFT;
        page_mask_shift = sz_lg2 - HV_PAGE_SIFT;

No overflows that way either

Jason

Reply via email to