From: Nuno Das Neves <[email protected]> Sent: Monday, July 28,
2025 10:03 AM
>
> On 7/17/2025 9:55 PM, [email protected] wrote:
> <snip>
> > diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c
> > index 2b4080e51f97..d9b569b204d2 100644
> > --- a/drivers/hv/hv_balloon.c
> > +++ b/drivers/hv/hv_balloon.c
> > @@ -1577,21 +1577,21 @@ static int hv_free_page_report(struct
> > page_reporting_dev_info *pr_dev_info,
> > {
> > unsigned long flags;
> > struct hv_memory_hint *hint;
> > - int i, order;
> > + int i, order, batch_size;
> > u64 status;
> > struct scatterlist *sg;
> >
> > - WARN_ON_ONCE(nents > HV_MEMORY_HINT_MAX_GPA_PAGE_RANGES);
> > WARN_ON_ONCE(sgl->length < (HV_HYP_PAGE_SIZE << page_reporting_order));
> > local_irq_save(flags);
> > - hint = *this_cpu_ptr(hyperv_pcpu_input_arg);
> > +
> > + batch_size = hv_setup_in_array(&hint, sizeof(*hint),
> > sizeof(hint->ranges[0]));
> > if (!hint) {
> > local_irq_restore(flags);
> > return -ENOSPC;
> > }
> > + WARN_ON_ONCE(nents > batch_size);
> >
>
> I don't think WARN_ON_ONCE is sufficient here... this looks like a bug in the
> current
> code. The loop below will go out of bounds of the input page if nents is too
> large.
>
> Ideally this function would be refactored to batch the operation so that this
> isn't a
> problem.
Yes, I kept the existing functionality, which is slightly flawed. But there's
not a
real problem, because "nents" is always PAGE_REPORTING_CAPACITY (which is
32) or smaller. See page_reporting_cycle(). Furthermore, the HV balloon driver
function enable_page_reporting() has a BUILD_BUG_ON to ensure everything fits.
Adding a batching loop around the hypercall here in hv_free_page_report() seems
like overkill unless PAGE_REPORTING_CAPACITY is changed to something larger.
Hyper-V has room for the value to be as large as 128.
The virtio balloon driver does a similar check, though at runtime, and
virtio_balloon_probe() fails if its capacity isn't at least
PAGE_REPORTING_CAPACITY.
The Hyper-V balloon driver could do the same. Tidying this up seems to me
to be a separate patch that's outside the scope of this series.
Michael
>
> Nuno
> > hint->heat_type = HV_EXTMEM_HEAT_HINT_COLD_DISCARD;
> > - hint->reserved = 0;
> > for_each_sg(sgl, sg, nents, i) {
> > union hv_gpa_page_range *range;
> >
> <snip>