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 <[email protected]>

> Signed-off-by: Jork Loeser <[email protected]>
> ---
>  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
> 

Reply via email to