[PATCH v2 09/15] Drivers: hv: mshv_vtl: Move hv_vtl_configure_reg_page() to x86

Naman Jain
2026-04-23T12:43:56Z

Move hv_vtl_configure_reg_page() from drivers/hv/mshv_vtl_main.c to
arch/x86/hyperv/hv_vtl.c. The register page overlay is an x86-specific
feature that uses HV_X64_REGISTER_REG_PAGE, so its configuration belongs
in architecture-specific code.

Move struct mshv_vtl_per_cpu and union hv_synic_overlay_page_msr to
include/asm-generic/mshyperv.h so they are visible to both arch and
driver code.

Change the return type from void to bool so the caller can determine
whether the register page was successfully configured and set
mshv_has_reg_page accordingly.

Signed-off-by: Naman Jain <namjain@linux.microsoft.com>
---
arch/x86/hyperv/hv_vtl.c | 32 ++++++++++++++++++++++
drivers/hv/mshv_vtl_main.c | 49 +++-------------------------------
include/asm-generic/mshyperv.h | 17 ++++++++++++
3 files changed, 53 insertions(+), 45 deletions(-)

diff --git a/arch/x86/hyperv/hv_vtl.c b/arch/x86/hyperv/hv_vtl.c
index 09d81f9b853c..f3ffb6a7cb2d 100644
--- a/arch/x86/hyperv/hv_vtl.c
+++ b/arch/x86/hyperv/hv_vtl.c
@@ -20,6 +20,7 @@
#include <uapi/asm/mtrr.h>
#include <asm/debugreg.h>
#include <linux/export.h>
+#include <linux/hyperv.h>
#include <../kernel/smpboot.h>
#include "../../kernel/fpu/legacy.h"

@@ -259,6 +260,37 @@ int __init hv_vtl_early_init(void)
return 0;
}

+static const union hv_input_vtl input_vtl_zero;
+
+bool hv_vtl_configure_reg_page(struct mshv_vtl_per_cpu *per_cpu)
+{
+ struct hv_register_assoc reg_assoc = {};
+ union hv_synic_overlay_page_msr overlay = {};
+ struct page *reg_page;
+
+ reg_page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_RETRY_MAYFAIL);
+ if (!reg_page) {
+ WARN(1, "failed to allocate register page\n");
+ return false;
+ }
+
+ overlay.enabled = 1;
+ overlay.pfn = page_to_hvpfn(reg_page);
+ reg_assoc.name = HV_X64_REGISTER_REG_PAGE;
+ reg_assoc.value.reg64 = overlay.as_uint64;
+
+ if (hv_call_set_vp_registers(HV_VP_INDEX_SELF, HV_PARTITION_ID_SELF,
+ 1, input_vtl_zero, &reg_assoc)) {
+ WARN(1, "failed to setup register page\n");
+ __free_page(reg_page);
+ return false;
+ }
+
+ per_cpu->reg_page = reg_page;
+ return true;
+}
+EXPORT_SYMBOL_GPL(hv_vtl_configure_reg_page);
+
DEFINE_STATIC_CALL_NULL(__mshv_vtl_return_hypercall, void (*)(void));

void mshv_vtl_return_call_init(u64 vtl_return_offset)
diff --git a/drivers/hv/mshv_vtl_main.c b/drivers/hv/mshv_vtl_main.c
index 91517b45d526..c79d24317b8e 100644
--- a/drivers/hv/mshv_vtl_main.c
+++ b/drivers/hv/mshv_vtl_main.c
@@ -78,21 +78,6 @@ struct mshv_vtl {
u64 id;
};

-struct mshv_vtl_per_cpu {
- struct mshv_vtl_run *run;
- struct page *reg_page;
-};
-
-/* SYNIC_OVERLAY_PAGE_MSR - internal, identical to hv_synic_simp */
-union hv_synic_overlay_page_msr {
- u64 as_uint64;
- struct {
- u64 enabled: 1;
- u64 reserved: 11;
- u64 pfn: 52;
- } __packed;
-};
-
static struct mutex mshv_vtl_poll_file_lock;
static union hv_register_vsm_page_offsets mshv_vsm_page_offsets;
static union hv_register_vsm_capabilities mshv_vsm_capabilities;
@@ -201,34 +186,6 @@ static struct page *mshv_vtl_cpu_reg_page(int cpu)
return *per_cpu_ptr(&mshv_vtl_per_cpu.reg_page, cpu);
}

-static void mshv_vtl_configure_reg_page(struct mshv_vtl_per_cpu *per_cpu)
-{
- struct hv_register_assoc reg_assoc = {};
- union hv_synic_overlay_page_msr overlay = {};
- struct page *reg_page;
-
- reg_page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_RETRY_MAYFAIL);
- if (!reg_page) {
- WARN(1, "failed to allocate register page\n");
- return;
- }
-
- overlay.enabled = 1;
- overlay.pfn = page_to_hvpfn(reg_page);
- reg_assoc.name = HV_X64_REGISTER_REG_PAGE;
- reg_assoc.value.reg64 = overlay.as_uint64;
-
- if (hv_call_set_vp_registers(HV_VP_INDEX_SELF, HV_PARTITION_ID_SELF,
- 1, input_vtl_zero, &reg_assoc)) {
- WARN(1, "failed to setup register page\n");
- __free_page(reg_page);
- return;
- }
-
- per_cpu->reg_page = reg_page;
- mshv_has_reg_page = true;
-}
-
static void mshv_vtl_synic_enable_regs(unsigned int cpu)
{
union hv_synic_sint sint;
@@ -329,8 +286,10 @@ static int mshv_vtl_alloc_context(unsigned int cpu)
if (!per_cpu->run)
return -ENOMEM;

- if (mshv_vsm_capabilities.intercept_page_available)
- mshv_vtl_configure_reg_page(per_cpu);
+ if (mshv_vsm_capabilities.intercept_page_available) {
+ if (hv_vtl_configure_reg_page(per_cpu))
+ mshv_has_reg_page = true;
+ }

mshv_vtl_synic_enable_regs(cpu);

diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
index ef0b9466808c..9e86178c182e 100644
--- a/include/asm-generic/mshyperv.h
+++ b/include/asm-generic/mshyperv.h
@@ -420,12 +420,29 @@ static inline int hv_call_set_vp_registers(u32 vp_index, u64 partition_id,
}
#endif /* CONFIG_MSHV_ROOT || CONFIG_MSHV_VTL */

+struct mshv_vtl_per_cpu {
+ struct mshv_vtl_run *run;
+ struct page *reg_page;
+};
+
#if IS_ENABLED(CONFIG_HYPERV_VTL_MODE)
+/* SYNIC_OVERLAY_PAGE_MSR - internal, identical to hv_synic_simp */
+union hv_synic_overlay_page_msr {
+ u64 as_uint64;
+ struct {
+ u64 enabled: 1;
+ u64 reserved: 11;
+ u64 pfn: 52;
+ } __packed;
+};
+
u8 __init get_vtl(void);
void mshv_vtl_return_call(struct mshv_vtl_cpu_context *vtl0);
+bool hv_vtl_configure_reg_page(struct mshv_vtl_per_cpu *per_cpu);
#else
static inline u8 get_vtl(void) { return 0; }
static inline void mshv_vtl_return_call(struct mshv_vtl_cpu_context *vtl0) {}
+static inline bool hv_vtl_configure_reg_page(struct mshv_vtl_per_cpu *per_cpu) { return false; }
#endif

#endif
--
2.43.0