From: Stanislav Kinsburskii <[email protected]> Sent: Tuesday, 
March 3, 2026 4:24 PM
> 
> Deposit enough pages upfront to avoid partition initialization failures due
> to low memory. This also speeds up partition initialization.
> 
> Move page depositing from the hypercall wrapper to the partition
> initialization code. The required number of pages is empirical. This logic
> fits better in the partition initialization code than in the hypercall
> wrapper.
> 
> A partition with nested capability requires 40x more pages (20 MB) to
> accommodate the nested MSHV hypervisor. This may be improved in the future.
> 
> Signed-off-by: Stanislav Kinsburskii <[email protected]>
> ---
>  drivers/hv/mshv_root.h         |    1 +
>  drivers/hv/mshv_root_hv_call.c |    6 ------
>  drivers/hv/mshv_root_main.c    |   23 +++++++++++++++++++++--
>  3 files changed, 22 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/hv/mshv_root.h b/drivers/hv/mshv_root.h
> index 947dfb76bb19..40cf7bdbd62f 100644
> --- a/drivers/hv/mshv_root.h
> +++ b/drivers/hv/mshv_root.h
> @@ -106,6 +106,7 @@ struct mshv_partition {
> 
>       struct hlist_node pt_hnode;
>       u64 pt_id;
> +     u64 pt_flags;
>       refcount_t pt_ref_count;
>       struct mutex pt_mutex;
> 
> diff --git a/drivers/hv/mshv_root_hv_call.c b/drivers/hv/mshv_root_hv_call.c
> index bdcb8de7fb47..b8d199f95299 100644
> --- a/drivers/hv/mshv_root_hv_call.c
> +++ b/drivers/hv/mshv_root_hv_call.c
> @@ -15,7 +15,6 @@
>  #include "mshv_root.h"
> 
>  /* Determined empirically */

I think the above comment applies to HV_INIT_PARTITION_DEPOSIT_PAGES
(not to HV_UMAP_GPA_PAGES) and should be removed.

> -#define HV_INIT_PARTITION_DEPOSIT_PAGES 208
>  #define HV_UMAP_GPA_PAGES            512
> 
>  #define HV_PAGE_COUNT_2M_ALIGNED(pg_count) (!((pg_count) & (0x200 - 1)))
> @@ -139,11 +138,6 @@ int hv_call_initialize_partition(u64 partition_id)
> 
>       input.partition_id = partition_id;
> 
> -     ret = hv_call_deposit_pages(NUMA_NO_NODE, partition_id,
> -                                 HV_INIT_PARTITION_DEPOSIT_PAGES);
> -     if (ret)
> -             return ret;
> -
>       do {
>               status = hv_do_fast_hypercall8(HVCALL_INITIALIZE_PARTITION,
>                                              *(u64 *)&input);
> diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c
> index d753f41d3b57..fbfc50de332c 100644
> --- a/drivers/hv/mshv_root_main.c
> +++ b/drivers/hv/mshv_root_main.c
> @@ -35,6 +35,10 @@
>  #include "mshv.h"
>  #include "mshv_root.h"
> 
> +/* The deposit values below are empirical and may need to be adjusted. */
> +#define MSHV_PARTITION_DEPOSIT_PAGES         (SZ_512K >> PAGE_SHIFT)
> +#define MSHV_PARTITION_DEPOSIT_PAGES_NESTED  (20 * SZ_1M >> PAGE_SHIFT)

Nit: The placement of these #defines *above* the MODULE_* notations seems
a bit odd to me. 

> +
>  MODULE_AUTHOR("Microsoft");
>  MODULE_LICENSE("GPL");
>  MODULE_DESCRIPTION("Microsoft Hyper-V root partition VMM interface 
> /dev/mshv");
> @@ -1587,6 +1591,15 @@ mshv_partition_ioctl_set_msi_routing(struct
> mshv_partition *partition,
>       return ret;
>  }
> 
> +static u64
> +mshv_partition_deposit_pages(struct mshv_partition *partition)

Nit: This function name makes it seem like it will "deposit pages".  Maybe
mshv_partition_get_deposit_cnt(), or something similar, would be better?

> +{
> +     if (partition->pt_flags &
> +         HV_PARTITION_CREATION_FLAG_NESTED_VIRTUALIZATION_CAPABLE)
> +             return MSHV_PARTITION_DEPOSIT_PAGES_NESTED;
> +     return MSHV_PARTITION_DEPOSIT_PAGES;
> +}
> +
>  static long
>  mshv_partition_ioctl_initialize(struct mshv_partition *partition)
>  {
> @@ -1595,6 +1608,11 @@ mshv_partition_ioctl_initialize(struct mshv_partition 
> *partition)
>       if (partition->pt_initialized)
>               return 0;
> 
> +     ret = hv_call_deposit_pages(NUMA_NO_NODE, partition->pt_id,
> +                                 mshv_partition_deposit_pages(partition));
> +     if (ret)
> +             goto withdraw_mem;
> +
>       ret = hv_call_initialize_partition(partition->pt_id);
>       if (ret)
>               goto withdraw_mem;
> @@ -1610,8 +1628,8 @@ mshv_partition_ioctl_initialize(struct mshv_partition 
> *partition)
>  finalize_partition:
>       hv_call_finalize_partition(partition->pt_id);
>  withdraw_mem:
> -     hv_call_withdraw_memory(U64_MAX, NUMA_NO_NODE, partition->pt_id);
> -
> +     hv_call_withdraw_memory(MSHV_PARTITION_DEPOSIT_PAGES,
> +                             NUMA_NO_NODE, partition->pt_id);

What's the strategy here for withdrawing memory after a failure? As I noted in
Patch 1 of the series, there's no way to know how many pages were deposited.
Might have been zero, or significantly more than MSHV_PARTITION_DEPOSIT_PAGES.
And in Patches 3 and 4 of the series, there's no attempt to withdraw pages if
hv_call_deposit_pages() fails, which seems inconsistent.

>       return ret;
>  }
> 
> @@ -2032,6 +2050,7 @@ mshv_ioctl_create_partition(void __user *user_arg, 
> struct device *module_dev)
>               return -ENOMEM;
> 
>       partition->pt_module_dev = module_dev;
> +     partition->pt_flags = creation_flags;
>       partition->isolation_type = isolation_properties.isolation_type;
> 
>       refcount_set(&partition->pt_ref_count, 1);
> 
> 


Reply via email to