linux/arch/x86
Konrad Rzeszutek Wilk 7f1fc268c4 xen/vcpu/pvhvm: Fix vcpu hotplugging hanging.
If a user did:

	echo 0 > /sys/devices/system/cpu/cpu1/online
	echo 1 > /sys/devices/system/cpu/cpu1/online

we would (this a build with DEBUG enabled) get to:
smpboot: ++++++++++++++++++++=_---CPU UP  1
.. snip..
smpboot: Stack at about ffff880074c0ff44
smpboot: CPU1: has booted.

and hang. The RCU mechanism would kick in an try to IPI the CPU1
but the IPIs (and all other interrupts) would never arrive at the
CPU1. At first glance at least. A bit digging in the hypervisor
trace shows that (using xenanalyze):

[vla] d4v1 vec 243 injecting
   0.043163027 --|x d4v1 intr_window vec 243 src 5(vector) intr f3
]  0.043163639 --|x d4v1 vmentry cycles 1468
]  0.043164913 --|x d4v1 vmexit exit_reason PENDING_INTERRUPT eip ffffffff81673254
   0.043164913 --|x d4v1 inj_virq vec 243  real
  [vla] d4v1 vec 243 injecting
   0.043164913 --|x d4v1 intr_window vec 243 src 5(vector) intr f3
]  0.043165526 --|x d4v1 vmentry cycles 1472
]  0.043166800 --|x d4v1 vmexit exit_reason PENDING_INTERRUPT eip ffffffff81673254
   0.043166800 --|x d4v1 inj_virq vec 243  real
  [vla] d4v1 vec 243 injecting

there is a pending event (subsequent debugging shows it is the IPI
from the VCPU0 when smpboot.c on VCPU1 has done
"set_cpu_online(smp_processor_id(), true)") and the guest VCPU1 is
interrupted with the callback IPI (0xf3 aka 243) which ends up calling
__xen_evtchn_do_upcall.

The __xen_evtchn_do_upcall seems to do *something* but not acknowledge
the pending events. And the moment the guest does a 'cli' (that is the
ffffffff81673254 in the log above) the hypervisor is invoked again to
inject the IPI (0xf3) to tell the guest it has pending interrupts.
This repeats itself forever.

The culprit was the per_cpu(xen_vcpu, cpu) pointer. At the bootup
we set each per_cpu(xen_vcpu, cpu) to point to the
shared_info->vcpu_info[vcpu] but later on use the VCPUOP_register_vcpu_info
to register per-CPU  structures (xen_vcpu_setup).
This is used to allow events for more than 32 VCPUs and for performance
optimizations reasons.

When the user performs the VCPU hotplug we end up calling the
the xen_vcpu_setup once more. We make the hypercall which returns
-EINVAL as it does not allow multiple registration calls (and
already has re-assigned where the events are being set). We pick
the fallback case and set per_cpu(xen_vcpu, cpu) to point to the
shared_info->vcpu_info[vcpu] (which is a good fallback during bootup).
However the hypervisor is still setting events in the register
per-cpu structure (per_cpu(xen_vcpu_info, cpu)).

As such when the events are set by the hypervisor (such as timer one),
and when we iterate in __xen_evtchn_do_upcall we end up reading stale
events from the shared_info->vcpu_info[vcpu] instead of the
per_cpu(xen_vcpu_info, cpu) structures. Hence we never acknowledge the
events that the hypervisor has set and the hypervisor keeps on reminding
us to ack the events which we never do.

The fix is simple. Don't on the second time when xen_vcpu_setup is
called over-write the per_cpu(xen_vcpu, cpu) if it points to
per_cpu(xen_vcpu_info).

Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
CC: stable@vger.kernel.org
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
2013-05-06 11:29:17 -04:00
..
boot x86: Fix rebuild with EFI_STUB enabled 2013-04-05 13:59:23 -07:00
configs x86: Default to ARCH=x86 to avoid overriding CONFIG_64BIT 2012-12-20 14:37:18 -08:00
crypto Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6 2013-02-25 15:56:15 -08:00
ia32 Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal 2013-03-02 08:34:06 -08:00
include x86: remove the x32 syscall bitmask from syscall_get_nr() 2013-04-02 14:38:09 -07:00
kernel Merge branch 'x86/urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2013-03-24 10:10:34 -07:00
kvm KVM: Allow cross page reads and writes from cached translations. 2013-04-07 13:05:35 +03:00
lguest Merge branch 'x86-mm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2013-02-21 18:06:55 -08:00
lib x86-64: Fix the failure case in copy_user_handle_tail() 2013-03-18 11:32:03 -07:00
math-emu
mm x86: Do not try to sync identity map for non-mapped pages 2013-03-07 13:23:28 -08:00
net x86: bpf_jit_comp: add pkt_type support 2013-01-30 22:38:34 -05:00
oprofile oprofile, x86: Fix wrapping bug in op_x86_get_ctrl() 2012-10-15 14:38:24 +02:00
pci xen: drop tracking of IRQ vector 2013-04-16 15:05:45 -04:00
platform Merge branch 'x86-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2013-02-27 16:17:42 -08:00
power perf,x86: fix kernel crash with PEBS/BTS after suspend/resume 2013-03-15 09:26:35 -07:00
realmode Merge remote-tracking branch 'origin/x86/mm' into x86/mm2 2013-02-01 02:28:36 -08:00
syscalls fix compat truncate/ftruncate 2013-02-25 09:24:55 -05:00
tools Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2013-02-05 07:57:09 +11:00
um Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal 2013-02-23 18:50:11 -08:00
vdso timers/x86/hpet: Use HPET_COUNTER to specify the hpet counter in vread_hpet() 2013-02-15 12:13:18 +01:00
video
xen xen/vcpu/pvhvm: Fix vcpu hotplugging hanging. 2013-05-06 11:29:17 -04:00
.gitignore
Kbuild
Kconfig Select VIRT_TO_BUS directly where needed 2013-03-12 11:16:40 -07:00
Kconfig.cpu x86, 386 removal: Document Nx586 as a 386 and thus unsupported 2012-11-29 13:28:39 -08:00
Kconfig.debug x86/tlb: add tlb_flushall_shift knob into debugfs 2012-06-27 19:29:10 -07:00
Makefile Merge branch 'x86-build-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2013-02-19 19:12:03 -08:00
Makefile_32.cpu x86, 386 removal: Remove CONFIG_M386 from Kconfig 2012-11-29 13:23:01 -08:00
Makefile.um