On Fri, Aug 29, 2025 at 8:44 AM Nuno Das Neves <nunodasne...@linux.microsoft.com> wrote: > > From: Purna Pavan Chandra Aekkaladevi <paekkalad...@linux.microsoft.com> > > Some versions of the hypervisor do not support HV_STATUS_AREA_PARENT and > return HV_STATUS_INVALID_PARAMETER for the second stats page mapping > request. > > This results a failure in module init. Instead of failing, gracefully > fall back to populating stats_pages[HV_STATS_AREA_PARENT] with the > already-mapped stats_pages[HV_STATS_AREA_SELF]. > > Signed-off-by: Purna Pavan Chandra Aekkaladevi > <paekkalad...@linux.microsoft.com> > Signed-off-by: Nuno Das Neves <nunodasne...@linux.microsoft.com> > --- > drivers/hv/mshv_root_hv_call.c | 43 ++++++++++++++++++++++++++++++---- > drivers/hv/mshv_root_main.c | 3 +++ > 2 files changed, 42 insertions(+), 4 deletions(-) > Reviewed-by: Tianyu Lan <ti...@microsoft.com>
> diff --git a/drivers/hv/mshv_root_hv_call.c b/drivers/hv/mshv_root_hv_call.c > index c9c274f29c3c..1c38576a673c 100644 > --- a/drivers/hv/mshv_root_hv_call.c > +++ b/drivers/hv/mshv_root_hv_call.c > @@ -724,6 +724,24 @@ hv_call_notify_port_ring_empty(u32 sint_index) > return hv_result_to_errno(status); > } > > +static int > +hv_stats_get_area_type(enum hv_stats_object_type type, > + const union hv_stats_object_identity *identity) > +{ > + switch (type) { > + case HV_STATS_OBJECT_HYPERVISOR: > + return identity->hv.stats_area_type; > + case HV_STATS_OBJECT_LOGICAL_PROCESSOR: > + return identity->lp.stats_area_type; > + case HV_STATS_OBJECT_PARTITION: > + return identity->partition.stats_area_type; > + case HV_STATS_OBJECT_VP: > + return identity->vp.stats_area_type; > + } > + > + return -EINVAL; > +} > + > int hv_call_map_stat_page(enum hv_stats_object_type type, > const union hv_stats_object_identity *identity, > void **addr) > @@ -732,7 +750,7 @@ int hv_call_map_stat_page(enum hv_stats_object_type type, > struct hv_input_map_stats_page *input; > struct hv_output_map_stats_page *output; > u64 status, pfn; > - int ret = 0; > + int hv_status, ret = 0; > > do { > local_irq_save(flags); > @@ -747,11 +765,28 @@ int hv_call_map_stat_page(enum hv_stats_object_type > type, > pfn = output->map_location; > > local_irq_restore(flags); > - if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) { > - ret = hv_result_to_errno(status); > + > + hv_status = hv_result(status); > + if (hv_status != HV_STATUS_INSUFFICIENT_MEMORY) { > if (hv_result_success(status)) > break; > - return ret; > + > + /* > + * Some versions of the hypervisor do not support the > + * PARENT stats area. In this case return "success" > but > + * set the page to NULL. The caller checks for this > + * case instead just uses the SELF area. > + */ > + if (hv_stats_get_area_type(type, identity) == > HV_STATS_AREA_PARENT && > + hv_status == HV_STATUS_INVALID_PARAMETER) { > + pr_debug_once("%s: PARENT area type is > unsupported\n", > + __func__); > + *addr = NULL; > + return 0; > + } > + > + hv_status_debug(status, "\n"); > + return hv_result_to_errno(status); > } > > ret = hv_call_deposit_pages(NUMA_NO_NODE, > diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c > index bbdefe8a2e9c..56ababab57ce 100644 > --- a/drivers/hv/mshv_root_main.c > +++ b/drivers/hv/mshv_root_main.c > @@ -929,6 +929,9 @@ static int mshv_vp_stats_map(u64 partition_id, u32 > vp_index, > if (err) > goto unmap_self; > > + if (!stats_pages[HV_STATS_AREA_PARENT]) > + stats_pages[HV_STATS_AREA_PARENT] = > stats_pages[HV_STATS_AREA_SELF]; > + > return 0; > > unmap_self: > -- > 2.34.1 > > -- Thanks Tianyu Lan