Convert hv_call_deposit_pages() into a wrapper supporting arbitrary number
of pages, and use it in the memory deposit code paths.

Signed-off-by: Stanislav Kinsburskii <[email protected]>
---
 drivers/hv/hv_proc.c |   50 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 49 insertions(+), 1 deletion(-)

diff --git a/drivers/hv/hv_proc.c b/drivers/hv/hv_proc.c
index 5f4fd9c3231c..0f84a70def30 100644
--- a/drivers/hv/hv_proc.c
+++ b/drivers/hv/hv_proc.c
@@ -16,7 +16,7 @@
 #define HV_DEPOSIT_MAX (HV_HYP_PAGE_SIZE / sizeof(u64) - 1)
 
 /* Deposits exact number of pages. Must be called with interrupts enabled.  */
-int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages)
+static int __hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages)
 {
        struct page **pages, *page;
        int *counts;
@@ -108,6 +108,54 @@ int hv_call_deposit_pages(int node, u64 partition_id, u32 
num_pages)
        kfree(counts);
        return ret;
 }
+
+/**
+ * hv_call_deposit_pages - Deposit memory pages to a partition
+ * @node        : NUMA node from which to allocate pages
+ * @partition_id: Target partition ID to deposit pages to
+ * @num_pages   : Number of pages to deposit
+ *
+ * Deposits memory pages to the specified partition. The deposit is
+ * performed in chunks of HV_DEPOSIT_MAX pages to handle large requests
+ * efficiently.
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages)
+{
+       u32 done;
+       int ret = 0;
+
+       /*
+        * Do a double deposit for L1VH. This reserves enough memory for
+        * Hypervisor Hot Restart (HHR).
+        *
+        * During HHR, every data structure must be recreated in the new
+        * ("proto") hypervisor. Memory is required by the proto hypervisor
+        * to do this work.
+        *
+        * For regular L1 partitions, more memory can be requested from the
+        * root during HHR by sending an asynchronous message. But this is
+        * not supported for L1VHs. A guest must not be allowed to block
+        * HHR by refusing to deposit more memory.
+        *
+        * So for L1VH a deposit is always required for both current needs
+        * and future HHR work.
+        */
+       if (hv_l1vh_partition())
+               num_pages *= 2;
+
+       for (done = 0; done < num_pages; done += HV_DEPOSIT_MAX) {
+               u32 to_deposit = min(num_pages - done, HV_DEPOSIT_MAX);
+
+               ret = __hv_call_deposit_pages(node, partition_id,
+                                             to_deposit);
+               if (ret)
+                       break;
+       }
+
+       return ret;
+}
 EXPORT_SYMBOL_GPL(hv_call_deposit_pages);
 
 int hv_deposit_memory_node(int node, u64 partition_id,



Reply via email to