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(®ion->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;
> }
>
>