aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/arch/x86/xen/smp_pv.c
diff options
context:
space:
mode:
authorJuergen Gross <jgross@suse.com>2022-11-25 07:32:47 +0100
committerJuergen Gross <jgross@suse.com>2023-02-13 06:53:19 +0100
commit336f560a8917fd60bcdb71b97263257611411453 (patch)
treeba662f8f2eee6e9dc22f99f1dde34ab7e32dfe7e /arch/x86/xen/smp_pv.c
parentdrivers/xen/hypervisor: Expose Xen SIF flags to userspace (diff)
downloadwireguard-linux-336f560a8917fd60bcdb71b97263257611411453.tar.xz
wireguard-linux-336f560a8917fd60bcdb71b97263257611411453.zip
x86/xen: don't let xen_pv_play_dead() return
A function called via the paravirt play_dead() hook should not return to the caller. xen_pv_play_dead() has a problem in this regard, as it currently will return in case an offlined cpu is brought to life again. This can be changed only by doing basically a longjmp() to cpu_bringup_and_idle(), as the hypercall for bringing down the cpu will just return when the cpu is coming up again. Just re-initializing the cpu isn't possible, as the Xen hypervisor will deny that operation. So introduce xen_cpu_bringup_again() resetting the stack and calling cpu_bringup_and_idle(), which can be called after HYPERVISOR_vcpu_op() in xen_pv_play_dead(). Signed-off-by: Juergen Gross <jgross@suse.com> Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lore.kernel.org/r/20221125063248.30256-2-jgross@suse.com Signed-off-by: Juergen Gross <jgross@suse.com>
Diffstat (limited to 'arch/x86/xen/smp_pv.c')
-rw-r--r--arch/x86/xen/smp_pv.c13
1 files changed, 2 insertions, 11 deletions
diff --git a/arch/x86/xen/smp_pv.c b/arch/x86/xen/smp_pv.c
index 6175f2c5c822..a97b0505a483 100644
--- a/arch/x86/xen/smp_pv.c
+++ b/arch/x86/xen/smp_pv.c
@@ -385,17 +385,8 @@ static void xen_pv_play_dead(void) /* used only with HOTPLUG_CPU */
{
play_dead_common();
HYPERVISOR_vcpu_op(VCPUOP_down, xen_vcpu_nr(smp_processor_id()), NULL);
- cpu_bringup();
- /*
- * commit 4b0c0f294 (tick: Cleanup NOHZ per cpu data on cpu down)
- * clears certain data that the cpu_idle loop (which called us
- * and that we return from) expects. The only way to get that
- * data back is to call:
- */
- tick_nohz_idle_enter();
- tick_nohz_idle_stop_tick_protected();
-
- cpuhp_online_idle(CPUHP_AP_ONLINE_IDLE);
+ xen_cpu_bringup_again((unsigned long)task_pt_regs(current));
+ BUG();
}
#else /* !CONFIG_HOTPLUG_CPU */