[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID:
<175874947750.157998.7004962396456082421.stgit@skinsburskii-cloud-desktop.internal.cloudapp.net>
Date: Wed, 24 Sep 2025 21:31:17 +0000
From: Stanislav Kinsburskii <skinsburskii@...ux.microsoft.com>
To: kys@...rosoft.com, haiyangz@...rosoft.com, wei.liu@...nel.org,
decui@...rosoft.com
Cc: linux-hyperv@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: [PATCH 2/3] Drivers: hv: Centralize guest memory region destruction
in helper
This is a precursor and cleanup patch.
- Introduce mshv_partition_destroy_region() to encapsulate memory region
cleanup, including:
- Removing the region from the partition's list
- Regaining access for encrypted partitions
- Unmapping only mapped pages for efficiency
- Evicting and freeing the region
- Update mshv_unmap_user_memory() to call mshv_partition_destroy_region()
instead of duplicating cleanup logic.
- Update destroy_partition() to use mshv_partition_destroy_region() for
all regions, removing the previous inlined cleanup loop.
These changes eliminate code duplication, ensure consistent cleanup, and
improve maintainability for both unmap and partition destruction paths.
Signed-off-by: Stanislav Kinsburskii <skinsburskii@...ux.microsoft.com>
---
drivers/hv/mshv_root_main.c | 83 ++++++++++++++++++++++++++-----------------
1 file changed, 51 insertions(+), 32 deletions(-)
diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c
index 5ed6bce334417..c0f6023e459c2 100644
--- a/drivers/hv/mshv_root_main.c
+++ b/drivers/hv/mshv_root_main.c
@@ -1386,13 +1386,59 @@ mshv_map_user_memory(struct mshv_partition *partition,
return ret;
}
+static void mshv_partition_destroy_region(struct mshv_mem_region *region)
+{
+ struct mshv_partition *partition = region->partition;
+ u64 page_offset, page_count;
+ u32 unmap_flags = 0;
+ int ret;
+
+ hlist_del(®ion->hnode);
+
+ if (mshv_partition_encrypted(partition)) {
+ ret = mshv_partition_region_share(region);
+ if (ret) {
+ pt_err(partition,
+ "Failed to regain access to memory, unpinning user pages will fail and crash the host error: %d\n",
+ ret);
+ return;
+ }
+ }
+
+ if (region->flags.large_pages)
+ unmap_flags |= HV_UNMAP_GPA_LARGE_PAGE;
+
+ /*
+ * Unmap only the mapped pages to optimize performance,
+ * especially for large memory regions.
+ */
+ for (page_offset = 0; page_offset < region->nr_pages; page_offset += page_count) {
+ page_count = 1;
+ if (!region->pages[page_offset])
+ continue;
+
+ for (; page_count < region->nr_pages - page_offset; page_count++) {
+ if (!region->pages[page_offset + page_count])
+ break;
+ }
+
+ /* ignore unmap failures and continue as process may be exiting */
+ hv_call_unmap_gpa_pages(partition->pt_id,
+ region->start_gfn + page_offset,
+ page_count, unmap_flags);
+ }
+
+ mshv_region_evict(region);
+
+ vfree(region);
+}
+
/* Called for unmapping both the guest ram and the mmio space */
static long
mshv_unmap_user_memory(struct mshv_partition *partition,
struct mshv_user_mem_region mem)
{
struct mshv_mem_region *region;
- u32 unmap_flags = 0;
if (!(mem.flags & BIT(MSHV_SET_MEM_BIT_UNMAP)))
return -EINVAL;
@@ -1407,18 +1453,7 @@ mshv_unmap_user_memory(struct mshv_partition *partition,
region->nr_pages != HVPFN_DOWN(mem.size))
return -EINVAL;
- hlist_del(®ion->hnode);
-
- if (region->flags.large_pages)
- unmap_flags |= HV_UNMAP_GPA_LARGE_PAGE;
-
- /* ignore unmap failures and continue as process may be exiting */
- hv_call_unmap_gpa_pages(partition->pt_id, region->start_gfn,
- region->nr_pages, unmap_flags);
-
- mshv_region_evict(region);
-
- vfree(region);
+ mshv_partition_destroy_region(region);
return 0;
}
@@ -1754,8 +1789,8 @@ static void destroy_partition(struct mshv_partition *partition)
{
struct mshv_vp *vp;
struct mshv_mem_region *region;
- int i, ret;
struct hlist_node *n;
+ int i;
if (refcount_read(&partition->pt_ref_count)) {
pt_err(partition,
@@ -1815,25 +1850,9 @@ static void destroy_partition(struct mshv_partition *partition)
remove_partition(partition);
- /* Remove regions, regain access to the memory and unpin the pages */
hlist_for_each_entry_safe(region, n, &partition->pt_mem_regions,
- hnode) {
- hlist_del(®ion->hnode);
-
- if (mshv_partition_encrypted(partition)) {
- ret = mshv_partition_region_share(region);
- if (ret) {
- pt_err(partition,
- "Failed to regain access to memory, unpinning user pages will fail and crash the host error: %d\n",
- ret);
- return;
- }
- }
-
- mshv_region_evict(region);
-
- vfree(region);
- }
+ hnode)
+ mshv_partition_destroy_region(region);
/* Withdraw and free all pages we deposited */
hv_call_withdraw_memory(U64_MAX, NUMA_NO_NODE, partition->pt_id);
Powered by blists - more mailing lists