Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+11 -11
+2
arch/x86/xen/smp.h
··· 21 21 void xen_smp_send_call_function_ipi(const struct cpumask *mask); 22 22 void xen_smp_send_call_function_single_ipi(int cpu); 23 23 24 + void xen_cpu_bringup_again(unsigned long stack); 25 + 24 26 struct xen_common_irq { 25 27 int irq; 26 28 char *name;
+2 -11
arch/x86/xen/smp_pv.c
··· 385 385 { 386 386 play_dead_common(); 387 387 HYPERVISOR_vcpu_op(VCPUOP_down, xen_vcpu_nr(smp_processor_id()), NULL); 388 - cpu_bringup(); 389 - /* 390 - * commit 4b0c0f294 (tick: Cleanup NOHZ per cpu data on cpu down) 391 - * clears certain data that the cpu_idle loop (which called us 392 - * and that we return from) expects. The only way to get that 393 - * data back is to call: 394 - */ 395 - tick_nohz_idle_enter(); 396 - tick_nohz_idle_stop_tick_protected(); 397 - 398 - cpuhp_online_idle(CPUHP_AP_ONLINE_IDLE); 388 + xen_cpu_bringup_again((unsigned long)task_pt_regs(current)); 389 + BUG(); 399 390 } 400 391 401 392 #else /* !CONFIG_HOTPLUG_CPU */
+7
arch/x86/xen/xen-head.S
··· 76 76 77 77 call cpu_bringup_and_idle 78 78 SYM_CODE_END(asm_cpu_bringup_and_idle) 79 + 80 + SYM_CODE_START(xen_cpu_bringup_again) 81 + UNWIND_HINT_FUNC 82 + mov %rdi, %rsp 83 + UNWIND_HINT_REGS 84 + call cpu_bringup_and_idle 85 + SYM_CODE_END(xen_cpu_bringup_again) 79 86 .popsection 80 87 #endif 81 88 #endif