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 >

