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