Re: [PATCH 5/6] mshv: clean up SynIC state on kexec for L1VH

Stanislav Kinsburskii
2026-03-30T21:52:18Z

On Fri, Mar 27, 2026 at 01:19:16PM -0700, Jork Loeser wrote:
> Register the mshv reboot notifier for all parent partitions, not just
> root. Previously the notifier was gated on hv_root_partition(), so on
> L1VH (where hv_root_partition() is false) SINT0, SINT5, and SIRBP were
> never cleaned up before kexec. The kexec'd kernel then inherited stale
> unmasked SINTs and an enabled SIRBP pointing to freed memory.
>
> The L1VH SIRBP also needs special handling: unlike the root partition
> where the hypervisor provides the SIRBP page, L1VH must allocate its
> own page and program the GPA into the MSR. Add this allocation to
> mshv_synic_init() and the corresponding free to mshv_synic_cleanup().
>
> Remove the unnecessary mshv_root_partition_init/exit wrappers and
> register the reboot notifier directly in mshv_parent_partition_init().
> Make mshv_reboot_nb static since it no longer needs external linkage.
>

Reviewed-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>

> Signed-off-by: Jork Loeser <jloeser@linux.microsoft.com>
> ---
> drivers/hv/mshv_root_main.c | 21 ++++-----------------
> drivers/hv/mshv_synic.c | 37 ++++++++++++++++++++++++++++++-------
> 2 files changed, 34 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c
> index e6509c980763..281f530b68a9 100644
> --- a/drivers/hv/mshv_root_main.c
> +++ b/drivers/hv/mshv_root_main.c
> @@ -2256,20 +2256,10 @@ static int mshv_reboot_notify(struct notifier_block *nb,
> return 0;
> }
>
> -struct notifier_block mshv_reboot_nb = {
> +static struct notifier_block mshv_reboot_nb = {
> .notifier_call = mshv_reboot_notify,
> };
>
> -static void mshv_root_partition_exit(void)
> -{
> - unregister_reboot_notifier(&mshv_reboot_nb);
> -}
> -
> -static int __init mshv_root_partition_init(struct device *dev)
> -{
> - return register_reboot_notifier(&mshv_reboot_nb);
> -}
> -
> static int __init mshv_init_vmm_caps(struct device *dev)
> {
> int ret;
> @@ -2339,8 +2329,7 @@ static int __init mshv_parent_partition_init(void)
> if (ret)
> goto remove_cpu_state;
>
> - if (hv_root_partition())
> - ret = mshv_root_partition_init(dev);
> + ret = register_reboot_notifier(&mshv_reboot_nb);
> if (ret)
> goto remove_cpu_state;
>
> @@ -2368,8 +2357,7 @@ static int __init mshv_parent_partition_init(void)
> deinit_root_scheduler:
> root_scheduler_deinit();
> exit_partition:
> - if (hv_root_partition())
> - mshv_root_partition_exit();
> + unregister_reboot_notifier(&mshv_reboot_nb);
> remove_cpu_state:
> cpuhp_remove_state(mshv_cpuhp_online);
> free_synic_pages:
> @@ -2387,8 +2375,7 @@ static void __exit mshv_parent_partition_exit(void)
> misc_deregister(&mshv_dev);
> mshv_irqfd_wq_cleanup();
> root_scheduler_deinit();
> - if (hv_root_partition())
> - mshv_root_partition_exit();
> + unregister_reboot_notifier(&mshv_reboot_nb);
> cpuhp_remove_state(mshv_cpuhp_online);
> free_percpu(mshv_root.synic_pages);
> }
> diff --git a/drivers/hv/mshv_synic.c b/drivers/hv/mshv_synic.c
> index 8a7d76a10dc3..32f91a714c97 100644
> --- a/drivers/hv/mshv_synic.c
> +++ b/drivers/hv/mshv_synic.c
> @@ -495,13 +495,29 @@ int mshv_synic_init(unsigned int cpu)
>
> /* Setup the Synic's event ring page */
> sirbp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIRBP);
> - sirbp.sirbp_enabled = true;
> - *event_ring_page = memremap(sirbp.base_sirbp_gpa << PAGE_SHIFT,
> - PAGE_SIZE, MEMREMAP_WB);
>
> - if (!(*event_ring_page))
> - goto cleanup_siefp;
> + if (hv_root_partition()) {
> + *event_ring_page = memremap(sirbp.base_sirbp_gpa << PAGE_SHIFT,
> + PAGE_SIZE, MEMREMAP_WB);
> +
> + if (!(*event_ring_page))
> + goto cleanup_siefp;
> + } else {
> + /*
> + * On L1VH the hypervisor does not provide a SIRBP page.
> + * Allocate one and program its GPA into the MSR.
> + */
> + *event_ring_page = (struct hv_synic_event_ring_page *)
> + get_zeroed_page(GFP_KERNEL);
> +
> + if (!(*event_ring_page))
> + goto cleanup_siefp;
>
> + sirbp.base_sirbp_gpa = virt_to_phys(*event_ring_page)
> + >> PAGE_SHIFT;
> + }
> +
> + sirbp.sirbp_enabled = true;
> hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64);
>
> #ifdef HYPERVISOR_CALLBACK_VECTOR
> @@ -581,8 +597,15 @@ int mshv_synic_cleanup(unsigned int cpu)
> /* Disable SYNIC event ring page owned by MSHV */
> sirbp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIRBP);
> sirbp.sirbp_enabled = false;
> - hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64);
> - memunmap(*event_ring_page);
> +
> + if (hv_root_partition()) {
> + hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64);
> + memunmap(*event_ring_page);
> + } else {
> + sirbp.base_sirbp_gpa = 0;
> + hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64);
> + free_page((unsigned long)*event_ring_page);
> + }
>
> /*
> * Release our mappings of the message and event flags pages.
> --
> 2.43.0
>