Re: [PATCH v3 2/2] Drivers: hv: Run VMBus kexec cleanup from syscore shutdown

From: Mike Rapoport

Date: Thu Oct 08 2026 - 03:53:38 EST


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 ;)

> 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.