• Juergen Gross's avatar
    xen: make xen_qlock_wait() nestable · a8565319
    Juergen Gross authored
    xen_qlock_wait() isn't safe for nested calls due to interrupts. A call
    of xen_qlock_kick() might be ignored in case a deeper nesting level
    was active right before the call of xen_poll_irq():
    
    CPU 1:                                   CPU 2:
    spin_lock(lock1)
                                             spin_lock(lock1)
                                             -> xen_qlock_wait()
                                                -> xen_clear_irq_pending()
                                                Interrupt happens
    spin_unlock(lock1)
    -> xen_qlock_kick(CPU 2)
    spin_lock_irqsave(lock2)
                                             spin_lock_irqsave(lock2)
                                             -> xen_qlock_wait()
                                                -> xen_clear_irq_pending()
                                                   clears kick for lock1
                                                -> xen_poll_irq()
    spin_unlock_irq_restore(lock2)
    -> xen_qlock_kick(CPU 2)
                                                wakes up
                                             spin_unlock_irq_restore(lock2)
                                             IRET
                                               resumes in xen_qlock_wait()
                                               -> xen_poll_irq()
                                               never wakes up
    
    The solution is to disable interrupts in xen_qlock_wait() and not to
    poll for the irq in case xen_qlock_wait() is called in nmi context.
    
    Cc: stable@vger.kernel.org
    Cc: Waiman.Long@hp.com
    Cc: peterz@infradead.org
    Signed-off-by: default avatarJuergen Gross <jgross@suse.com>
    Reviewed-by: default avatarJan Beulich <jbeulich@suse.com>
    Signed-off-by: default avatarJuergen Gross <jgross@suse.com>
    a8565319
spinlock.c 3.47 KB