On Fri, Jul 03, 2026 at 02:10:18PM -0300, Jason Gunthorpe wrote:
> 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.
> 

Good catch!

> > +   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
> 

Indeed. It is much cleaner. Will rewrite using this logic.

B.R.
Yu
> Jason
> 

Reply via email to