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

locking/pvqspinlock, x86: Enable PV qspinlock for Xen

This patch adds the necessary Xen specific code to allow Xen to
support the CPU halting and kicking operations needed by the queue
spinlock PV code.

Signed-off-by: David Vrabel <david.vrabel@citrix.com>
Signed-off-by: Waiman Long <Waiman.Long@hp.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Daniel J Blueman <daniel@numascale.com>
Cc: Douglas Hatch <doug.hatch@hp.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Paolo Bonzini <paolo.bonzini@gmail.com>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Raghavendra K T <raghavendra.kt@linux.vnet.ibm.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Scott J Norton <scott.norton@hp.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: virtualization@lists.linux-foundation.org
Cc: xen-devel@lists.xenproject.org
Link: http://lkml.kernel.org/r/1429901803-29771-12-git-send-email-Waiman.Long@hp.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>

authored by

David Vrabel and committed by
Ingo Molnar
e95e6f17 bf0c7c34

+61 -5
+60 -4
arch/x86/xen/spinlock.c
··· 17 17 #include "xen-ops.h" 18 18 #include "debugfs.h" 19 19 20 + static DEFINE_PER_CPU(int, lock_kicker_irq) = -1; 21 + static DEFINE_PER_CPU(char *, irq_name); 22 + static bool xen_pvspin = true; 23 + 24 + #ifdef CONFIG_QUEUED_SPINLOCK 25 + 26 + #include <asm/qspinlock.h> 27 + 28 + static void xen_qlock_kick(int cpu) 29 + { 30 + xen_send_IPI_one(cpu, XEN_SPIN_UNLOCK_VECTOR); 31 + } 32 + 33 + /* 34 + * Halt the current CPU & release it back to the host 35 + */ 36 + static void xen_qlock_wait(u8 *byte, u8 val) 37 + { 38 + int irq = __this_cpu_read(lock_kicker_irq); 39 + 40 + /* If kicker interrupts not initialized yet, just spin */ 41 + if (irq == -1) 42 + return; 43 + 44 + /* clear pending */ 45 + xen_clear_irq_pending(irq); 46 + barrier(); 47 + 48 + /* 49 + * We check the byte value after clearing pending IRQ to make sure 50 + * that we won't miss a wakeup event because of the clearing. 51 + * 52 + * The sync_clear_bit() call in xen_clear_irq_pending() is atomic. 53 + * So it is effectively a memory barrier for x86. 54 + */ 55 + if (READ_ONCE(*byte) != val) 56 + return; 57 + 58 + /* 59 + * If an interrupt happens here, it will leave the wakeup irq 60 + * pending, which will cause xen_poll_irq() to return 61 + * immediately. 62 + */ 63 + 64 + /* Block until irq becomes pending (or perhaps a spurious wakeup) */ 65 + xen_poll_irq(irq); 66 + } 67 + 68 + #else /* CONFIG_QUEUED_SPINLOCK */ 69 + 20 70 enum xen_contention_stat { 21 71 TAKEN_SLOW, 22 72 TAKEN_SLOW_PICKUP, ··· 150 100 __ticket_t want; 151 101 }; 152 102 153 - static DEFINE_PER_CPU(int, lock_kicker_irq) = -1; 154 - static DEFINE_PER_CPU(char *, irq_name); 155 103 static DEFINE_PER_CPU(struct xen_lock_waiting, lock_waiting); 156 104 static cpumask_t waiting_cpus; 157 105 158 - static bool xen_pvspin = true; 159 106 __visible void xen_lock_spinning(struct arch_spinlock *lock, __ticket_t want) 160 107 { 161 108 int irq = __this_cpu_read(lock_kicker_irq); ··· 264 217 } 265 218 } 266 219 } 220 + #endif /* CONFIG_QUEUED_SPINLOCK */ 267 221 268 222 static irqreturn_t dummy_handler(int irq, void *dev_id) 269 223 { ··· 328 280 return; 329 281 } 330 282 printk(KERN_DEBUG "xen: PV spinlocks enabled\n"); 283 + #ifdef CONFIG_QUEUED_SPINLOCK 284 + __pv_init_lock_hash(); 285 + pv_lock_ops.queued_spin_lock_slowpath = __pv_queued_spin_lock_slowpath; 286 + pv_lock_ops.queued_spin_unlock = PV_CALLEE_SAVE(__pv_queued_spin_unlock); 287 + pv_lock_ops.wait = xen_qlock_wait; 288 + pv_lock_ops.kick = xen_qlock_kick; 289 + #else 331 290 pv_lock_ops.lock_spinning = PV_CALLEE_SAVE(xen_lock_spinning); 332 291 pv_lock_ops.unlock_kick = xen_unlock_kick; 292 + #endif 333 293 } 334 294 335 295 /* ··· 366 310 } 367 311 early_param("xen_nopvspin", xen_parse_nopvspin); 368 312 369 - #ifdef CONFIG_XEN_DEBUG_FS 313 + #if defined(CONFIG_XEN_DEBUG_FS) && !defined(CONFIG_QUEUED_SPINLOCK) 370 314 371 315 static struct dentry *d_spin_debug; 372 316
+1 -1
kernel/Kconfig.locks
··· 240 240 241 241 config QUEUED_SPINLOCK 242 242 def_bool y if ARCH_USE_QUEUED_SPINLOCK 243 - depends on SMP && (!PARAVIRT_SPINLOCKS || !XEN) 243 + depends on SMP 244 244 245 245 config ARCH_USE_QUEUE_RWLOCK 246 246 bool