Messages in this thread |  | | Date | Wed, 8 Jul 2026 20:43:28 +0800 | | From | Yu Zhang <> | | Subject | Re: [PATCH v2 4/4] iommu/hyperv: Add page-selective IOTLB flush support |
| |
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 >
|  |