On Fri, Dec 05, 2025 at 10:58:40AM -0800, Nuno Das Neves wrote:
> From: Purna Pavan Chandra Aekkaladevi <[email protected]>
> 
> Older versions of the hypervisor do not support HV_STATS_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].
> 

Reviewed-by: Stanislav Kinsburskii <[email protected]>

> Signed-off-by: Purna Pavan Chandra Aekkaladevi 
> <[email protected]>
> Signed-off-by: Nuno Das Neves <[email protected]>
> Reviewed-by: Stanislav Kinsburskii <[email protected]>
> ---
>  drivers/hv/mshv_root_hv_call.c | 41 ++++++++++++++++++++++++++++++----
>  drivers/hv/mshv_root_main.c    |  3 +++
>  2 files changed, 40 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/hv/mshv_root_hv_call.c b/drivers/hv/mshv_root_hv_call.c
> index 598eaff4ff29..b1770c7b500c 100644
> --- a/drivers/hv/mshv_root_hv_call.c
> +++ b/drivers/hv/mshv_root_hv_call.c
> @@ -855,6 +855,24 @@ static int hv_call_map_stats_page2(enum 
> hv_stats_object_type type,
>       return ret;
>  }
>  
> +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;
> +}
> +
>  static int hv_call_map_stats_page(enum hv_stats_object_type type,
>                                 const union hv_stats_object_identity 
> *identity,
>                                 void **addr)
> @@ -863,7 +881,7 @@ static int hv_call_map_stats_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);
> @@ -878,11 +896,26 @@ static int hv_call_map_stats_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;
> +
> +                     /*
> +                      * Older versions of the hypervisor do not support the
> +                      * PARENT stats area. In this case return "success" but
> +                      * set the page to NULL. The caller should check for
> +                      * this case and instead just use the SELF area.
> +                      */
> +                     if (hv_stats_get_area_type(type, identity) == 
> HV_STATS_AREA_PARENT &&
> +                         hv_status == HV_STATUS_INVALID_PARAMETER) {
> +                             *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 bc15d6f6922f..f59a4ab47685 100644
> --- a/drivers/hv/mshv_root_main.c
> +++ b/drivers/hv/mshv_root_main.c
> @@ -905,6 +905,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
> 

Reply via email to