diff options
| author | Jork Loeser <jloeser@linux.microsoft.com> | 2026-04-07 18:36:40 -0700 |
|---|---|---|
| committer | Wei Liu <wei.liu@kernel.org> | 2026-04-22 06:23:25 +0000 |
| commit | 5170a82e89211d876af17bf3d94a511fb2bb4921 (patch) | |
| tree | b136f2665a59adadb4c6f5fb13849de1bcd313a1 /drivers/hv | |
| parent | f7ce370b525a02127527b0f54ee877413705a709 (diff) | |
| download | linux-next-5170a82e89211d876af17bf3d94a511fb2bb4921.tar.gz linux-next-5170a82e89211d876af17bf3d94a511fb2bb4921.zip | |
x86/hyperv: Skip LP/VP creation on kexec
After a kexec the logical processors and virtual processors already
exist in the hypervisor because they were created by the previous
kernel. Attempting to add them again causes either a BUG_ON or
corrupted VP state leading to MCEs in the new kernel.
Add hv_lp_exists() to probe whether an LP is already present by
calling HVCALL_GET_LOGICAL_PROCESSOR_RUN_TIME. When it succeeds the
LP exists and we skip the add-LP and create-VP loops entirely.
Also add hv_call_notify_all_processors_started() which informs the
hypervisor that all processors are online. This is required after
adding LPs (fresh boot) and is a no-op on kexec since we skip that
path.
Co-developed-by: Anirudh Rayabharam <anrayabh@linux.microsoft.com>
Signed-off-by: Anirudh Rayabharam <anrayabh@linux.microsoft.com>
Co-developed-by: Stanislav Kinsburskii <stanislav.kinsburskii@gmail.com>
Signed-off-by: Stanislav Kinsburskii <stanislav.kinsburskii@gmail.com>
Co-developed-by: Mukesh Rathor <mrathor@linux.microsoft.com>
Signed-off-by: Mukesh Rathor <mrathor@linux.microsoft.com>
Signed-off-by: Jork Loeser <jloeser@linux.microsoft.com>
Reviewed-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
Signed-off-by: Wei Liu <wei.liu@kernel.org>
Diffstat (limited to 'drivers/hv')
| -rw-r--r-- | drivers/hv/hv_proc.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/drivers/hv/hv_proc.c b/drivers/hv/hv_proc.c index 3cb4b2a3035c..57b2c64197cb 100644 --- a/drivers/hv/hv_proc.c +++ b/drivers/hv/hv_proc.c @@ -239,3 +239,50 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags) return ret; } EXPORT_SYMBOL_GPL(hv_call_create_vp); + +int hv_call_notify_all_processors_started(void) +{ + struct hv_input_notify_partition_event *input; + u64 status; + unsigned long irq_flags; + int ret = 0; + + local_irq_save(irq_flags); + input = *this_cpu_ptr(hyperv_pcpu_input_arg); + memset(input, 0, sizeof(*input)); + input->event = HV_PARTITION_ALL_LOGICAL_PROCESSORS_STARTED; + status = hv_do_hypercall(HVCALL_NOTIFY_PARTITION_EVENT, + input, NULL); + local_irq_restore(irq_flags); + + if (!hv_result_success(status)) { + hv_status_err(status, "\n"); + ret = hv_result_to_errno(status); + } + return ret; +} + +bool hv_lp_exists(u32 lp_index) +{ + struct hv_input_get_logical_processor_run_time *input; + struct hv_output_get_logical_processor_run_time *output; + unsigned long flags; + u64 status; + + local_irq_save(flags); + input = *this_cpu_ptr(hyperv_pcpu_input_arg); + output = *this_cpu_ptr(hyperv_pcpu_output_arg); + + input->lp_index = lp_index; + status = hv_do_hypercall(HVCALL_GET_LOGICAL_PROCESSOR_RUN_TIME, + input, output); + local_irq_restore(flags); + + if (!hv_result_success(status) && + hv_result(status) != HV_STATUS_INVALID_LP_INDEX) { + hv_status_err(status, "\n"); + BUG(); + } + + return hv_result_success(status); +} |
