On 3/3/26 16:23, Stanislav Kinsburskii wrote:
Deposit enough pages up front to avoid guest address space region creation
failures due to low memory. This also speeds up guest creation.

Does this imply that some hypercall fails and has no return of
insufficient memory?

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)

I don't think it is accurate to say slat pages, because in case of
overdeposit, they may be used for non-slat purposes according to my
understanding.

+{
+       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);
+       slat_pages = region_in_gbs * MSHV_1G_DEPOSIT_PAGES;
+
+       return slat_pages;
+}
+

Again, unconditionally depositing for each region is not good because
that is empirical, and hyp will reuse the leftover ram.

/*
   * 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);
+free_region:
        vfree(region);
        return ret;
  }




Reply via email to