Re: [PATCH v3 2/2] Drivers: hv: Run VMBus kexec cleanup from syscore shutdown
From: Shradha Gupta
Date: Fri Oct 09 2026 - 02:51:34 EST
On Thu, Oct 08, 2026 at 09:53:05AM +0200, Mike Rapoport wrote:
> On Thu, Oct 01, 2026 at 06:22:02AM -0700, Shradha Gupta wrote:
> > ARM64 Hyper-V guests do not run the VMBus kexec cleanup before
> > secondary CPUs are stopped. Consequently, the old VMBus connection
> > and SynIC state remain active when the kexec kernel starts.
> >
> > Run the VMBus kexec handler from the existing VMBus syscore shutdown
> > callback. syscore_shutdown() runs after device shutdown and before
> > machine shutdown, while all CPUs needed by the SynIC CPU hotplug
> > teardown are still available. Guard the callback with
> > kexec_is_in_progress() so normal restart, halt, and poweroff paths are
> > unchanged.
> >
> > Use the same path on x86 and remove the architecture-specific handler
> > pointer and the weak setup/remove interfaces. VMBus teardown now
> > precedes hv_stimer_global_cleanup() on x86.
> >
> > The new x86 ordering relies on commit be0cfab740e5 ("clocksource:
> > hyper-v: Remove support for stimer interrupts in message mode"), which
> > removed the synthetic timer's dependency on VMBus message delivery.
> > Older kernels that retain message-mode stimer interrupts must preserve
> > the existing x86 ordering and therefore require an ARM64-specific
> > backport.
> >
> > Fixes: 9bbb888824e3 ("arm64: hyperv: Initialize hypervisor on boot")
> > Link: https://lore.kernel.org/all/20260814093133.3191250-1-shradhagupta@xxxxxxxxxxxxxxxxxxx/
> > Suggested-by: Catalin Marinas <catalin.marinas@xxxxxxx>
> > Suggested-by: Michael Kelley <mhklinux@xxxxxxxxxxx>
> > Signed-off-by: Shradha Gupta <shradhagupta@xxxxxxxxxxxxxxxxxxx>
> > ---
> > arch/x86/kernel/cpu/mshyperv.c | 17 +----------------
> > drivers/hv/hv_common.c | 10 ----------
> > drivers/hv/vmbus_drv.c | 22 ++++++++++++++--------
> > include/asm-generic/mshyperv.h | 2 --
>
> It seems you missed Documentation/virt/hyperv/overview.rst ;)
>
Thanks Mike, I'll address this in the next version. :)
> > 4 files changed, 15 insertions(+), 36 deletions(-)
> >
> > diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
> > index b4af7c0a70ac..263f7e7acac0 100644
> > --- a/arch/x86/kernel/cpu/mshyperv.c
> > +++ b/arch/x86/kernel/cpu/mshyperv.c
> > @@ -148,7 +148,6 @@ EXPORT_SYMBOL_GPL(hv_set_msr);
> > static void (*mshv_handler)(void);
> > static void (*vmbus_handler)(void);
> > static void (*hv_stimer0_handler)(void);
> > -static void (*hv_kexec_handler)(void);
> > static void (*hv_crash_handler)(struct pt_regs *regs);
> >
> > DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_callback)
> > @@ -215,16 +214,6 @@ void hv_remove_stimer0_handler(void)
> > hv_stimer0_handler = NULL;
> > }
> >
> > -void hv_setup_kexec_handler(void (*handler)(void))
> > -{
> > - hv_kexec_handler = handler;
> > -}
> > -
> > -void hv_remove_kexec_handler(void)
> > -{
> > - hv_kexec_handler = NULL;
> > -}
> > -
> > void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs))
> > {
> > hv_crash_handler = handler;
> > @@ -238,13 +227,9 @@ void hv_remove_crash_handler(void)
> > #ifdef CONFIG_KEXEC_CORE
> > static void hv_machine_shutdown(void)
> > {
> > - if (kexec_in_progress) {
> > + if (kexec_in_progress)
> > hv_stimer_global_cleanup();
> >
> > - if (hv_kexec_handler)
> > - hv_kexec_handler();
> > - }
> > -
> > /*
> > * Call hv_cpu_die() on all the CPUs, otherwise later the hypervisor
> > * corrupts the old VP Assist Pages and can crash the kexec kernel.
> > diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
> > index 31256cb22b39..bb290a5eaf1d 100644
> > --- a/drivers/hv/hv_common.c
> > +++ b/drivers/hv/hv_common.c
> > @@ -681,16 +681,6 @@ void __weak hv_setup_mshv_handler(void (*handler)(void))
> > }
> > EXPORT_SYMBOL_GPL(hv_setup_mshv_handler);
> >
> > -void __weak hv_setup_kexec_handler(void (*handler)(void))
> > -{
> > -}
> > -EXPORT_SYMBOL_GPL(hv_setup_kexec_handler);
> > -
> > -void __weak hv_remove_kexec_handler(void)
> > -{
> > -}
> > -EXPORT_SYMBOL_GPL(hv_remove_kexec_handler);
> > -
> > void __weak hv_setup_crash_handler(void (*handler)(struct pt_regs *regs))
> > {
> > }
> > diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
> > index 5ebdbe24b5a1..3532ea779d34 100644
> > --- a/drivers/hv/vmbus_drv.c
> > +++ b/drivers/hv/vmbus_drv.c
> > @@ -33,6 +33,7 @@
> > #include <linux/sysfb.h>
> > #include <linux/efi.h>
> > #include <linux/kernel.h>
> > +#include <linux/kexec.h>
> > #include <linux/syscore_ops.h>
> > #include <linux/dma-map-ops.h>
> > #include <linux/pci.h>
> > @@ -2904,6 +2905,12 @@ static void hv_kexec_handler(void)
> > cpuhp_remove_state(hyperv_cpuhp_online);
> > };
> >
> > +static void hv_vmbus_syscore_shutdown(void *data)
> > +{
> > + if (kexec_is_in_progress())
> > + hv_kexec_handler();
> > +}
> > +
> > static void hv_crash_handler(struct pt_regs *regs)
> > {
> > int cpu;
> > @@ -2958,14 +2965,15 @@ static void hv_synic_resume(void *data)
> > */
> > }
> >
> > -/* The callbacks run only on CPU0, with irqs_disabled. */
> > -static const struct syscore_ops hv_synic_syscore_ops = {
> > +/* The suspend and resume callbacks run only on CPU0, with irqs_disabled. */
> > +static const struct syscore_ops hv_vmbus_syscore_ops = {
> > .suspend = hv_synic_suspend,
> > .resume = hv_synic_resume,
> > + .shutdown = hv_vmbus_syscore_shutdown,
> > };
> >
> > -static struct syscore hv_synic_syscore = {
> > - .ops = &hv_synic_syscore_ops,
> > +static struct syscore hv_vmbus_syscore = {
> > + .ops = &hv_vmbus_syscore_ops,
> > };
> >
> > static int __init hv_acpi_init(void)
> > @@ -3014,10 +3022,9 @@ static int __init hv_acpi_init(void)
> > if (ret)
> > goto cleanup;
> >
> > - hv_setup_kexec_handler(hv_kexec_handler);
> > hv_setup_crash_handler(hv_crash_handler);
> >
> > - register_syscore(&hv_synic_syscore);
> > + register_syscore(&hv_vmbus_syscore);
> >
> > return 0;
> >
> > @@ -3039,9 +3046,8 @@ static void __exit vmbus_exit(void)
> > */
> > return;
> >
> > - unregister_syscore(&hv_synic_syscore);
> > + unregister_syscore(&hv_vmbus_syscore);
> >
> > - hv_remove_kexec_handler();
> > hv_remove_crash_handler();
> > vmbus_connection.conn_state = DISCONNECTED;
> > hv_stimer_global_cleanup();
> > diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
> > index bf601d67cecb..98fe5c0f54ea 100644
> > --- a/include/asm-generic/mshyperv.h
> > +++ b/include/asm-generic/mshyperv.h
> > @@ -183,8 +183,6 @@ void hv_remove_vmbus_handler(void);
> > void hv_setup_stimer0_handler(void (*handler)(void));
> > void hv_remove_stimer0_handler(void);
> >
> > -void hv_setup_kexec_handler(void (*handler)(void));
> > -void hv_remove_kexec_handler(void);
> > void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs));
> > void hv_remove_crash_handler(void);
> > void hv_setup_mshv_handler(void (*handler)(void));
> > --
> > 2.43.0
>
> --
> Sincerely yours,
> Mike.