[PATCH 4/7] mshv: Move pinned region setup to mshv_regions.c
From: Stanislav Kinsburskii
Date: Mon Mar 30 2026 - 16:09:21 EST
Move mshv_prepare_pinned_region() from mshv_root_main.c to
mshv_regions.c and rename it to mshv_map_pinned_region(). This
co-locates the pinned region logic with the rest of the memory region
operations.
Make mshv_region_pin(), mshv_region_map(), mshv_region_share(),
mshv_region_unshare(), and mshv_region_invalidate() static, as they are
no longer called outside of mshv_regions.c.
Also fix a bug in the error handling where a mshv_region_map() failure
on a non-encrypted partition would be silently ignored, returning
success instead of propagating the error code.
Signed-off-by: Stanislav Kinsburskii <skinsburskii@xxxxxxxxxxxxxxxxxxx>
---
drivers/hv/mshv_regions.c | 79 ++++++++++++++++++++++++++++++++++++++++---
drivers/hv/mshv_root.h | 6 +--
drivers/hv/mshv_root_main.c | 70 +-------------------------------------
3 files changed, 76 insertions(+), 79 deletions(-)
diff --git a/drivers/hv/mshv_regions.c b/drivers/hv/mshv_regions.c
index 1bb1bfe177e2..133ec7771812 100644
--- a/drivers/hv/mshv_regions.c
+++ b/drivers/hv/mshv_regions.c
@@ -287,7 +287,7 @@ static int mshv_region_chunk_share(struct mshv_mem_region *region,
flags, true);
}
-int mshv_region_share(struct mshv_mem_region *region)
+static int mshv_region_share(struct mshv_mem_region *region)
{
u32 flags = HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_SHARED;
@@ -313,7 +313,7 @@ static int mshv_region_chunk_unshare(struct mshv_mem_region *region,
flags, false);
}
-int mshv_region_unshare(struct mshv_mem_region *region)
+static int mshv_region_unshare(struct mshv_mem_region *region)
{
u32 flags = HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_EXCLUSIVE;
@@ -353,7 +353,7 @@ static int mshv_region_remap_pfns(struct mshv_mem_region *region,
mshv_region_chunk_remap);
}
-int mshv_region_map(struct mshv_mem_region *region)
+static int mshv_region_map(struct mshv_mem_region *region)
{
u32 map_flags = region->hv_map_flags;
@@ -377,12 +377,12 @@ static void mshv_region_invalidate_pfns(struct mshv_mem_region *region,
}
}
-void mshv_region_invalidate(struct mshv_mem_region *region)
+static void mshv_region_invalidate(struct mshv_mem_region *region)
{
mshv_region_invalidate_pfns(region, 0, region->nr_pfns);
}
-int mshv_region_pin(struct mshv_mem_region *region)
+static int mshv_region_pin(struct mshv_mem_region *region)
{
u64 done_count, nr_pfns, i;
unsigned long *pfns;
@@ -731,3 +731,72 @@ bool mshv_region_movable_init(struct mshv_mem_region *region)
return true;
}
+
+/**
+ * mshv_map_pinned_region - Pin and map memory regions
+ * @region: Pointer to the memory region structure
+ *
+ * This function processes memory regions that are explicitly marked as pinned.
+ * Pinned regions are preallocated, mapped upfront, and do not rely on fault-based
+ * population. The function ensures the region is properly populated, handles
+ * encryption requirements for SNP partitions if applicable, maps the region,
+ * and performs necessary sharing or eviction operations based on the mapping
+ * result.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int mshv_map_pinned_region(struct mshv_mem_region *region)
+{
+ struct mshv_partition *partition = region->partition;
+ int ret;
+
+ ret = mshv_region_pin(region);
+ if (ret) {
+ pt_err(partition, "Failed to pin memory region: %d\n",
+ ret);
+ goto err_out;
+ }
+
+ /*
+ * For an SNP partition it is a requirement that for every memory region
+ * that we are going to map for this partition we should make sure that
+ * host access to that region is released. This is ensured by doing an
+ * additional hypercall which will update the SLAT to release host
+ * access to guest memory regions.
+ */
+ if (mshv_partition_encrypted(partition)) {
+ ret = mshv_region_unshare(region);
+ if (ret) {
+ pt_err(partition,
+ "Failed to unshare memory region (guest_pfn: %llu): %d\n",
+ region->start_gfn, ret);
+ goto invalidate_region;
+ }
+ }
+
+ ret = mshv_region_map(region);
+ if (!ret)
+ return 0;
+
+ if (mshv_partition_encrypted(partition)) {
+ int shrc;
+
+ shrc = mshv_region_share(region);
+ if (!shrc)
+ goto invalidate_region;
+
+ pt_err(partition,
+ "Failed to share memory region (guest_pfn: %llu): %d\n",
+ region->start_gfn, shrc);
+ /*
+ * Don't unpin if marking shared failed because pages are no
+ * longer mapped in the host, ie root, anymore.
+ */
+ goto err_out;
+ }
+
+invalidate_region:
+ mshv_region_invalidate(region);
+err_out:
+ return ret;
+}
diff --git a/drivers/hv/mshv_root.h b/drivers/hv/mshv_root.h
index f1d4bee97a3f..d2e65a137bf4 100644
--- a/drivers/hv/mshv_root.h
+++ b/drivers/hv/mshv_root.h
@@ -368,15 +368,11 @@ extern u8 * __percpu *hv_synic_eventring_tail;
struct mshv_mem_region *mshv_region_create(u64 guest_pfn, u64 nr_pages,
u64 uaddr, u32 flags);
-int mshv_region_share(struct mshv_mem_region *region);
-int mshv_region_unshare(struct mshv_mem_region *region);
-int mshv_region_map(struct mshv_mem_region *region);
-void mshv_region_invalidate(struct mshv_mem_region *region);
-int mshv_region_pin(struct mshv_mem_region *region);
void mshv_region_put(struct mshv_mem_region *region);
int mshv_region_get(struct mshv_mem_region *region);
bool mshv_region_handle_gfn_fault(struct mshv_mem_region *region, u64 gfn);
void mshv_region_movable_fini(struct mshv_mem_region *region);
bool mshv_region_movable_init(struct mshv_mem_region *region);
+int mshv_map_pinned_region(struct mshv_mem_region *region);
#endif /* _MSHV_ROOT_H_ */
diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c
index 685e4b562186..c393b5144e0b 100644
--- a/drivers/hv/mshv_root_main.c
+++ b/drivers/hv/mshv_root_main.c
@@ -1254,74 +1254,6 @@ static int mshv_partition_create_region(struct mshv_partition *partition,
return 0;
}
-/**
- * mshv_prepare_pinned_region - Pin and map memory regions
- * @region: Pointer to the memory region structure
- *
- * This function processes memory regions that are explicitly marked as pinned.
- * Pinned regions are preallocated, mapped upfront, and do not rely on fault-based
- * population. The function ensures the region is properly populated, handles
- * encryption requirements for SNP partitions if applicable, maps the region,
- * and performs necessary sharing or eviction operations based on the mapping
- * result.
- *
- * Return: 0 on success, negative error code on failure.
- */
-static int mshv_prepare_pinned_region(struct mshv_mem_region *region)
-{
- struct mshv_partition *partition = region->partition;
- int ret;
-
- ret = mshv_region_pin(region);
- if (ret) {
- pt_err(partition, "Failed to pin memory region: %d\n",
- ret);
- goto err_out;
- }
-
- /*
- * For an SNP partition it is a requirement that for every memory region
- * that we are going to map for this partition we should make sure that
- * host access to that region is released. This is ensured by doing an
- * additional hypercall which will update the SLAT to release host
- * access to guest memory regions.
- */
- if (mshv_partition_encrypted(partition)) {
- ret = mshv_region_unshare(region);
- if (ret) {
- pt_err(partition,
- "Failed to unshare memory region (guest_pfn: %llu): %d\n",
- region->start_gfn, ret);
- goto invalidate_region;
- }
- }
-
- ret = mshv_region_map(region);
- if (ret && mshv_partition_encrypted(partition)) {
- int shrc;
-
- shrc = mshv_region_share(region);
- if (!shrc)
- goto invalidate_region;
-
- pt_err(partition,
- "Failed to share memory region (guest_pfn: %llu): %d\n",
- region->start_gfn, shrc);
- /*
- * Don't unpin if marking shared failed because pages are no
- * longer mapped in the host, ie root, anymore.
- */
- goto err_out;
- }
-
- return 0;
-
-invalidate_region:
- mshv_region_invalidate(region);
-err_out:
- return ret;
-}
-
/*
* This maps two things: guest RAM and for pci passthru mmio space.
*
@@ -1364,7 +1296,7 @@ mshv_map_user_memory(struct mshv_partition *partition,
switch (region->mreg_type) {
case MSHV_REGION_TYPE_MEM_PINNED:
- ret = mshv_prepare_pinned_region(region);
+ ret = mshv_map_pinned_region(region);
break;
case MSHV_REGION_TYPE_MEM_MOVABLE:
/*