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

xen: fix RMW when unmasking events

xen_irq_enable_direct and xen_sysexit were using "andw $0x00ff,
XEN_vcpu_info_pending(vcpu)" to unmask events and test for pending ones
in one instuction.

Unfortunately, the pending flag must be modified with a locked operation
since it can be set by another CPU, and the unlocked form of this
operation was causing the pending flag to get lost, allowing the processor
to return to usermode with pending events and ultimately deadlock.

The simple fix would be to make it a locked operation, but that's rather
costly and unnecessary. The fix here is to split the mask-clearing and
pending-testing into two instructions; the interrupt window between
them is of no concern because either way pending or new events will
be processed.

This should fix lingering bugs in using direct vcpu structure access too.

[ Stable: needed in 2.6.24.x ]

Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Cc: Stable <stable@kernel.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>

authored by

Jeremy Fitzhardinge and committed by
Ingo Molnar
04c44a08 5abbcf29

+8 -3
+1 -1
arch/x86/xen/enlighten.c
··· 95 95 * 96 96 * 0: not available, 1: available 97 97 */ 98 - static int have_vcpu_info_placement = 0; 98 + static int have_vcpu_info_placement = 1; 99 99 100 100 static void __init xen_vcpu_setup(int cpu) 101 101 {
+7 -2
arch/x86/xen/xen-asm.S
··· 33 33 events, then enter the hypervisor to get them handled. 34 34 */ 35 35 ENTRY(xen_irq_enable_direct) 36 - /* Clear mask and test pending */ 37 - andw $0x00ff, PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_pending 36 + /* Unmask events */ 37 + movb $0, PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_mask 38 + 38 39 /* Preempt here doesn't matter because that will deal with 39 40 any pending interrupts. The pending check may end up being 40 41 run on the wrong CPU, but that doesn't hurt. */ 42 + 43 + /* Test for pending */ 44 + testb $0xff, PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_pending 41 45 jz 1f 46 + 42 47 2: call check_events 43 48 1: 44 49 ENDPATCH(xen_irq_enable_direct)