From: Stanislav Kinsburskii <[email protected]> Sent: Tuesday, 
March 3, 2026 4:24 PM
> 
> Deposit enough pages up front to avoid guest address space region creation
> failures due to low memory. This also speeds up guest creation.
> 
> Calculate the required number of pages based on the guest's physical
> address space size, rounded up to 1 GB chunks. Even the smallest guests are
> assumed to need at least 1 GB worth of deposits. This is because every
> guest requires tens of megabytes of deposited pages for hypervisor
> overhead, making smaller deposits impractical.
> 
> Estimating in 1 GB chunks prevents over-depositing for larger guests while
> accepting some over-deposit for smaller ones. This trade-off keeps the
> estimate close to actual needs for larger guests.
> 
> Also withdraw the deposited pages if address space region creation fails.
> 
> Signed-off-by: Stanislav Kinsburskii <[email protected]>
> ---
>  drivers/hv/mshv_root_main.c |   25 +++++++++++++++++++++++--
>  1 file changed, 23 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c
> index 48c842b6938d..cb5b4505f8eb 100644
> --- a/drivers/hv/mshv_root_main.c
> +++ b/drivers/hv/mshv_root_main.c
> @@ -39,6 +39,7 @@
>  #define MSHV_PARTITION_DEPOSIT_PAGES         (SZ_512K >> PAGE_SHIFT)
>  #define MSHV_PARTITION_DEPOSIT_PAGES_NESTED  (20 * SZ_1M >> PAGE_SHIFT)
>  #define MSHV_VP_DEPOSIT_PAGES                        (1 * SZ_1M >> 
> PAGE_SHIFT)
> +#define MSHV_1G_DEPOSIT_PAGES                        (6 * SZ_1M >> 
> PAGE_SHIFT)
> 
>  MODULE_AUTHOR("Microsoft");
>  MODULE_LICENSE("GPL");
> @@ -1324,6 +1325,18 @@ static int mshv_prepare_pinned_region(struct 
> mshv_mem_region *region)
>       return ret;
>  }
> 
> +static u64
> +mshv_region_deposit_slat_pages(struct mshv_mem_region *region)

Same nit about the function name. This one seems like it will "deposit slat 
pages".

> +{
> +     u64 region_in_gbs, slat_pages;
> +
> +     /* SLAT needs 6 MB per 1 GB of address space. */
> +     region_in_gbs = DIV_ROUND_UP(region->nr_pages << HV_HYP_PAGE_SHIFT, 
> SZ_1G);

This local variable "region_in_gbs" is computed in units of bytes.

> +     slat_pages = region_in_gbs * MSHV_1G_DEPOSIT_PAGES;

But here region_in_gbs is used as if it were in units of Gbytes.  So the
slat_pages return value is much larger than intended.

> +
> +     return slat_pages;
> +}
> +
>  /*
>   * This maps two things: guest RAM and for pci passthru mmio space.
>   *
> @@ -1364,6 +1377,11 @@ mshv_map_user_memory(struct mshv_partition *partition,
>       if (ret)
>               return ret;
> 
> +     ret = hv_call_deposit_pages(NUMA_NO_NODE, partition->pt_id,
> +                                 mshv_region_deposit_slat_pages(region));
> +     if (ret)
> +             goto free_region;
> +
>       switch (region->mreg_type) {
>       case MSHV_REGION_TYPE_MEM_PINNED:
>               ret = mshv_prepare_pinned_region(region);
> @@ -1392,7 +1410,7 @@ mshv_map_user_memory(struct mshv_partition *partition,
>                                  region->hv_map_flags, ret);
> 
>       if (ret)
> -             goto errout;
> +             goto withdraw_memory;
> 
>       spin_lock(&partition->pt_mem_regions_lock);
>       hlist_add_head(&region->hnode, &partition->pt_mem_regions);
> @@ -1400,7 +1418,10 @@ mshv_map_user_memory(struct mshv_partition *partition,
> 
>       return 0;
> 
> -errout:
> +withdraw_memory:
> +     hv_call_withdraw_memory(mshv_region_deposit_slat_pages(region),
> +                             NUMA_NO_NODE, partition->pt_id);

Again, for an L1VH partition, the actual number of pages deposited would
be 2x what mshv_region_deposit_slat_pages() returns.

> +free_region:
>       vfree(region);
>       return ret;
>  }
> 
> 


Reply via email to