in hv_balloon.c [1576:1620]
static int hv_free_page_report(struct page_reporting_dev_info *pr_dev_info,
struct scatterlist *sgl, unsigned int nents)
{
unsigned long flags;
struct hv_memory_hint *hint;
int i;
u64 status;
struct scatterlist *sg;
WARN_ON_ONCE(nents > HV_MEMORY_HINT_MAX_GPA_PAGE_RANGES);
WARN_ON_ONCE(sgl->length < HV_MIN_PAGE_REPORTING_LEN);
local_irq_save(flags);
hint = *(struct hv_memory_hint **)this_cpu_ptr(hyperv_pcpu_input_arg);
if (!hint) {
local_irq_restore(flags);
return -ENOSPC;
}
hint->type = HV_EXT_MEMORY_HEAT_HINT_TYPE_COLD_DISCARD;
hint->reserved = 0;
for_each_sg(sgl, sg, nents, i) {
union hv_gpa_page_range *range;
range = &hint->ranges[i];
range->address_space = 0;
/* page reporting only reports 2MB pages or higher */
range->page.largepage = 1;
range->page.additional_pages =
(sg->length / HV_MIN_PAGE_REPORTING_LEN) - 1;
range->page_size = HV_GPA_PAGE_RANGE_PAGE_SIZE_2MB;
range->base_large_pfn =
page_to_hvpfn(sg_page(sg)) >> HV_MIN_PAGE_REPORTING_ORDER;
}
status = hv_do_rep_hypercall(HV_EXT_CALL_MEMORY_HEAT_HINT, nents, 0,
hint, NULL);
local_irq_restore(flags);
if ((status & HV_HYPERCALL_RESULT_MASK) != HV_STATUS_SUCCESS) {
pr_err("Cold memory discard hypercall failed with status %llx\n",
status);
return -EINVAL;
}
return 0;
}