On Tue, Sep 23, 2025 at 02:46:08PM -0700, Mukesh Rathor wrote:
[...]
> +
> +/*
> + * This is the C entry point from the asm glue code after the devirt 
> hypercall.

devirt -> devirtualization

> + * We enter here in IA32-e long mode, ie, full 64bit mode running on kernel
> + * page tables with our below 4G page identity mapped, but using a temporary
> + * GDT. ds/fs/gs/es are null. ss is not usable. bp is null. stack is not
> + * available. We restore kernel GDT, and rest of the context, and continue
> + * to kexec.
> + */
[...]
> +
> +static noinline __noclone void crash_nmi_callback(struct pt_regs *regs)
> +{
> +     struct hv_input_disable_hyp_ex *input;
> +     u64 status;
> +     int msecs = 1000, ccpu = smp_processor_id();
> +
> +     if (ccpu == 0) {
> +             /* crash_save_cpu() will be done in the kexec path */
> +             cpu_emergency_stop_pt();        /* disable performance trace */
> +             atomic_inc(&crash_cpus_wait);
> +     } else {
> +             crash_save_cpu(regs, ccpu);
> +             cpu_emergency_stop_pt();        /* disable performance trace */
> +             atomic_inc(&crash_cpus_wait);
> +             for (;;)
> +                     cpu_relax();
> +     }
> +
> +     while (atomic_read(&crash_cpus_wait) < num_online_cpus() && msecs--)
> +             mdelay(1);
> +
> +     stop_nmi();
> +     if (!hv_has_crashed)
> +             hv_notify_prepare_hyp();
> +
> +     if (crashing_cpu == -1)
> +             crashing_cpu = ccpu;            /* crash cmd uses this */
> +
> +     hv_hvcrash_ctxt_save();
> +     hv_mark_tss_not_busy();
> +     hv_crash_fixup_kernpt();
> +
> +     input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +     memset(input, 0, sizeof(*input));
> +     input->rip = trampoline_pa;
> +     input->arg = devirt_arg;
> +
> +     status = hv_do_hypercall(HVCALL_DISABLE_HYP_EX, input, NULL);
> +

If I understand this correctly, after this call, upon return from the
hypervisor, Linux will start executing the trampoline code.

> +     hv_panic_timeout_reboot();

Why is this needed? Is it to catch the case when the hypercall fails?


[...]
> +static void __noclone hv_crash_stop_other_cpus(void)
> +{
> +     static bool crash_stop_done;
> +     struct pt_regs lregs;
> +     int ccpu = smp_processor_id();
> +
> +     if (hv_has_crashed)
> +             return;         /* all cpus already in NMI handler path */
> +
> +     if (!kexec_crash_loaded()) {
> +             hv_notify_prepare_hyp();
> +             hv_panic_timeout_reboot();      /* no return */
> +     }
> +
> +     /* If hyp crashes also, we could come here again before cpus_stopped is

hypervisor or hv (given the same term is used in the function)

> +      * set in crash_smp_send_stop(). So use our own check.
> +      */
> +     if (crash_stop_done)
> +             return;
> +     crash_stop_done = true;
> +
> +     /* Linux has crashed: hv is healthy, we can ipi safely */

IPI.

> +
> +err_out:
> +     unregister_nmi_handler(NMI_LOCAL, "hv_crash_nmi");
> +     pr_err("Hyper-V: only linux (but not hyp) kdump support enabled\n");

hypervisor not hyp. This is a message for the user so we should be as
clear as possible.

Wei

> +}
> -- 
> 2.36.1.vfs.0.0
> 

Reply via email to