]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'x86-spinlocks-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 4 Sep 2013 18:55:10 +0000 (11:55 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 4 Sep 2013 18:55:10 +0000 (11:55 -0700)
Pull x86 spinlock changes from Ingo Molnar:
 "The biggest change here are paravirtualized ticket spinlocks (PV
  spinlocks), which bring a nice speedup on various benchmarks.

  The KVM host side will come to you via the KVM tree"

* 'x86-spinlocks-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/kvm/guest: Fix sparse warning: "symbol 'klock_waiting' was not declared as static"
  kvm: Paravirtual ticketlocks support for linux guests running on KVM hypervisor
  kvm guest: Add configuration support to enable debug information for KVM Guests
  kvm uapi: Add KICK_CPU and PV_UNHALT definition to uapi
  xen, pvticketlock: Allow interrupts to be enabled while blocking
  x86, ticketlock: Add slowpath logic
  jump_label: Split jumplabel ratelimit
  x86, pvticketlock: When paravirtualizing ticket locks, increment by 2
  x86, pvticketlock: Use callee-save for lock_spinning
  xen, pvticketlocks: Add xen_nopvspin parameter to disable xen pv ticketlocks
  xen, pvticketlock: Xen implementation for PV ticket locks
  xen: Defer spinlock setup until boot CPU setup
  x86, ticketlock: Collapse a layer of functions
  x86, ticketlock: Don't inline _spin_unlock when using paravirt spinlocks
  x86, spinlock: Replace pv spinlocks with pv ticketlocks

1  2 
arch/x86/Kconfig
arch/x86/include/asm/kvm_para.h
arch/x86/include/asm/paravirt_types.h
arch/x86/include/asm/spinlock.h
arch/x86/kernel/kvm.c
arch/x86/xen/smp.c
include/linux/perf_event.h

diff --combined arch/x86/Kconfig
index 30322b0427d1003c2bbeeb99b8b6a02188eed31a,b1fb846e6dacb97dbdb1dbb667d83b49258d514f..5c0ed72c02a2b01dc0f4440dbf3ae7d7d827bb56
@@@ -16,7 -16,6 +16,7 @@@ config X86_6
        def_bool y
        depends on 64BIT
        select X86_DEV_DMA_OPS
 +      select ARCH_USE_CMPXCHG_LOCKREF
  
  ### Arch settings
  config X86
@@@ -82,6 -81,7 +82,6 @@@
        select HAVE_USER_RETURN_NOTIFIER
        select ARCH_BINFMT_ELF_RANDOMIZE_PIE
        select HAVE_ARCH_JUMP_LABEL
 -      select HAVE_TEXT_POKE_SMP
        select HAVE_GENERIC_HARDIRQS
        select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
        select SPARSE_IRQ
@@@ -632,6 -632,7 +632,7 @@@ config PARAVIRT_DEBU
  config PARAVIRT_SPINLOCKS
        bool "Paravirtualization layer for spinlocks"
        depends on PARAVIRT && SMP
+       select UNINLINE_SPIN_UNLOCK
        ---help---
          Paravirtualized spinlocks allow a pvops backend to replace the
          spinlock implementation with something virtualization-friendly
@@@ -656,6 -657,15 +657,15 @@@ config KVM_GUES
          underlying device model, the host provides the guest with
          timing infrastructure such as time of day, and system time
  
+ config KVM_DEBUG_FS
+       bool "Enable debug information for KVM Guests in debugfs"
+       depends on KVM_GUEST && DEBUG_FS
+       default n
+       ---help---
+         This option enables collection of various statistics for KVM guest.
+         Statistics are displayed in debugfs filesystem. Enabling this option
+         may incur significant overhead.
  source "arch/x86/lguest/Kconfig"
  
  config PARAVIRT_TIME_ACCOUNTING
@@@ -1344,12 -1354,8 +1354,12 @@@ config ARCH_SELECT_MEMORY_MODE
        depends on ARCH_SPARSEMEM_ENABLE
  
  config ARCH_MEMORY_PROBE
 -      def_bool y
 +      bool "Enable sysfs memory/probe interface"
        depends on X86_64 && MEMORY_HOTPLUG
 +      help
 +        This option enables a sysfs memory/probe interface for testing.
 +        See Documentation/memory-hotplug.txt for more information.
 +        If you are unsure how to answer this question, answer N.
  
  config ARCH_PROC_KCORE_TEXT
        def_bool y
@@@ -1631,9 -1637,9 +1641,9 @@@ config KEXE
  
          It is an ongoing process to be certain the hardware in a machine
          is properly shutdown, so do not be surprised if this code does not
 -        initially work for you.  It may help to enable device hotplugging
 -        support.  As of this writing the exact hardware interface is
 -        strongly in flux, so no good recommendation can be made.
 +        initially work for you.  As of this writing the exact hardware
 +        interface is strongly in flux, so no good recommendation can be
 +        made.
  
  config CRASH_DUMP
        bool "kernel crash dumps"
@@@ -1720,10 -1726,9 +1730,10 @@@ config X86_NEED_RELOC
        depends on X86_32 && RELOCATABLE
  
  config PHYSICAL_ALIGN
 -      hex "Alignment value to which kernel should be aligned" if X86_32
 +      hex "Alignment value to which kernel should be aligned"
        default "0x1000000"
 -      range 0x2000 0x1000000
 +      range 0x2000 0x1000000 if X86_32
 +      range 0x200000 0x1000000 if X86_64
        ---help---
          This value puts the alignment restrictions on physical address
          where kernel is loaded and run from. Kernel is compiled for an
          end result is that kernel runs from a physical address meeting
          above alignment restrictions.
  
 +        On 32-bit this value must be a multiple of 0x2000. On 64-bit
 +        this value must be a multiple of 0x200000.
 +
          Don't change this unless you know what you are doing.
  
  config HOTPLUG_CPU
@@@ -2278,32 -2280,6 +2288,32 @@@ config RAPIDI
  
  source "drivers/rapidio/Kconfig"
  
 +config X86_SYSFB
 +      bool "Mark VGA/VBE/EFI FB as generic system framebuffer"
 +      help
 +        Firmwares often provide initial graphics framebuffers so the BIOS,
 +        bootloader or kernel can show basic video-output during boot for
 +        user-guidance and debugging. Historically, x86 used the VESA BIOS
 +        Extensions and EFI-framebuffers for this, which are mostly limited
 +        to x86.
 +        This option, if enabled, marks VGA/VBE/EFI framebuffers as generic
 +        framebuffers so the new generic system-framebuffer drivers can be
 +        used on x86. If the framebuffer is not compatible with the generic
 +        modes, it is adverticed as fallback platform framebuffer so legacy
 +        drivers like efifb, vesafb and uvesafb can pick it up.
 +        If this option is not selected, all system framebuffers are always
 +        marked as fallback platform framebuffers as usual.
 +
 +        Note: Legacy fbdev drivers, including vesafb, efifb, uvesafb, will
 +        not be able to pick up generic system framebuffers if this option
 +        is selected. You are highly encouraged to enable simplefb as
 +        replacement if you select this option. simplefb can correctly deal
 +        with generic system framebuffers. But you should still keep vesafb
 +        and others enabled as fallback if a system framebuffer is
 +        incompatible with simplefb.
 +
 +        If unsure, say Y.
 +
  endmenu
  
  
@@@ -2366,6 -2342,10 +2376,6 @@@ config HAVE_ATOMIC_IOMA
        def_bool y
        depends on X86_32
  
 -config HAVE_TEXT_POKE_SMP
 -      bool
 -      select STOP_MACHINE if SMP
 -
  config X86_DEV_DMA_OPS
        bool
        depends on X86_64 || STA2X11
index 0644129a5333fd218e0d8a3273eb6ccb3d3b7179,427afcbf3d5534ab703df79bf559e7933d47fb4d..1df115909758862d8e664d86594a4d02e2c72f8c
@@@ -85,20 -85,26 +85,20 @@@ static inline long kvm_hypercall4(unsig
        return ret;
  }
  
 -static inline bool kvm_para_available(void)
 +static inline uint32_t kvm_cpuid_base(void)
  {
 -      unsigned int eax, ebx, ecx, edx;
 -      char signature[13];
 -
        if (boot_cpu_data.cpuid_level < 0)
 -              return false;   /* So we don't blow up on old processors */
 +              return 0;       /* So we don't blow up on old processors */
  
 -      if (cpu_has_hypervisor) {
 -              cpuid(KVM_CPUID_SIGNATURE, &eax, &ebx, &ecx, &edx);
 -              memcpy(signature + 0, &ebx, 4);
 -              memcpy(signature + 4, &ecx, 4);
 -              memcpy(signature + 8, &edx, 4);
 -              signature[12] = 0;
 +      if (cpu_has_hypervisor)
 +              return hypervisor_cpuid_base("KVMKVMKVM\0\0\0", 0);
  
 -              if (strcmp(signature, "KVMKVMKVM") == 0)
 -                      return true;
 -      }
 +      return 0;
 +}
  
 -      return false;
 +static inline bool kvm_para_available(void)
 +{
 +      return kvm_cpuid_base() != 0;
  }
  
  static inline unsigned int kvm_arch_para_features(void)
@@@ -112,10 -118,20 +112,20 @@@ void kvm_async_pf_task_wait(u32 token)
  void kvm_async_pf_task_wake(u32 token);
  u32 kvm_read_and_reset_pf_reason(void);
  extern void kvm_disable_steal_time(void);
- #else
- #define kvm_guest_init() do { } while (0)
+ #ifdef CONFIG_PARAVIRT_SPINLOCKS
+ void __init kvm_spinlock_init(void);
+ #else /* !CONFIG_PARAVIRT_SPINLOCKS */
+ static inline void kvm_spinlock_init(void)
+ {
+ }
+ #endif /* CONFIG_PARAVIRT_SPINLOCKS */
+ #else /* CONFIG_KVM_GUEST */
+ #define kvm_guest_init() do {} while (0)
  #define kvm_async_pf_task_wait(T) do {} while(0)
  #define kvm_async_pf_task_wake(T) do {} while(0)
  static inline u32 kvm_read_and_reset_pf_reason(void)
  {
        return 0;
index 0617ff241e8f82fdba2ea87f1a83e3a424c91c86,04ac40e192eb441e30333a54531d9998de8779a5..aab8f671b523f7801608c880225558d425889061
@@@ -327,13 -327,15 +327,15 @@@ struct pv_mmu_ops 
  };
  
  struct arch_spinlock;
+ #ifdef CONFIG_SMP
+ #include <asm/spinlock_types.h>
+ #else
+ typedef u16 __ticket_t;
+ #endif
  struct pv_lock_ops {
-       int (*spin_is_locked)(struct arch_spinlock *lock);
-       int (*spin_is_contended)(struct arch_spinlock *lock);
-       void (*spin_lock)(struct arch_spinlock *lock);
-       void (*spin_lock_flags)(struct arch_spinlock *lock, unsigned long flags);
-       int (*spin_trylock)(struct arch_spinlock *lock);
-       void (*spin_unlock)(struct arch_spinlock *lock);
+       struct paravirt_callee_save lock_spinning;
+       void (*unlock_kick)(struct arch_spinlock *lock, __ticket_t ticket);
  };
  
  /* This contains all the paravirt structures: we get a convenient
@@@ -387,8 -389,7 +389,8 @@@ extern struct pv_lock_ops pv_lock_ops
  
  /* Simple instruction patching code. */
  #define DEF_NATIVE(ops, name, code)                                   \
 -      extern const char start_##ops##_##name[], end_##ops##_##name[]; \
 +      extern const char start_##ops##_##name[] __visible,             \
 +                        end_##ops##_##name[] __visible;               \
        asm("start_" #ops "_" #name ": " code "; end_" #ops "_" #name ":")
  
  unsigned paravirt_patch_nop(void);
index e0e668422c7533ffc2d3b7f08f156f1ea951e33b,d68883dd133c28f8ab6b25ebe3b02ae647940726..bf156ded74b56006a76cc02b8917984117af8afd
@@@ -1,11 -1,14 +1,14 @@@
  #ifndef _ASM_X86_SPINLOCK_H
  #define _ASM_X86_SPINLOCK_H
  
+ #include <linux/jump_label.h>
  #include <linux/atomic.h>
  #include <asm/page.h>
  #include <asm/processor.h>
  #include <linux/compiler.h>
  #include <asm/paravirt.h>
+ #include <asm/bitops.h>
  /*
   * Your basic SMP spinlocks, allowing only a single CPU anywhere
   *
  # define UNLOCK_LOCK_PREFIX
  #endif
  
+ /* How long a lock should spin before we consider blocking */
+ #define SPIN_THRESHOLD        (1 << 15)
+ extern struct static_key paravirt_ticketlocks_enabled;
+ static __always_inline bool static_key_false(struct static_key *key);
+ #ifdef CONFIG_PARAVIRT_SPINLOCKS
+ static inline void __ticket_enter_slowpath(arch_spinlock_t *lock)
+ {
+       set_bit(0, (volatile unsigned long *)&lock->tickets.tail);
+ }
+ #else  /* !CONFIG_PARAVIRT_SPINLOCKS */
+ static __always_inline void __ticket_lock_spinning(arch_spinlock_t *lock,
+                                                       __ticket_t ticket)
+ {
+ }
+ static inline void __ticket_unlock_kick(arch_spinlock_t *lock,
+                                                       __ticket_t ticket)
+ {
+ }
+ #endif /* CONFIG_PARAVIRT_SPINLOCKS */
 +static __always_inline int arch_spin_value_unlocked(arch_spinlock_t lock)
 +{
 +      return lock.tickets.head == lock.tickets.tail;
 +}
 +
  /*
   * Ticket locks are conceptually two parts, one indicating the current head of
   * the queue, and the other indicating the current tail. The lock is acquired
   * in the high part, because a wide xadd increment of the low part would carry
   * up and contaminate the high part.
   */
- static __always_inline void __ticket_spin_lock(arch_spinlock_t *lock)
+ static __always_inline void arch_spin_lock(arch_spinlock_t *lock)
  {
-       register struct __raw_tickets inc = { .tail = 1 };
+       register struct __raw_tickets inc = { .tail = TICKET_LOCK_INC };
  
        inc = xadd(&lock->tickets, inc);
+       if (likely(inc.head == inc.tail))
+               goto out;
  
+       inc.tail &= ~TICKET_SLOWPATH_FLAG;
        for (;;) {
-               if (inc.head == inc.tail)
-                       break;
-               cpu_relax();
-               inc.head = ACCESS_ONCE(lock->tickets.head);
+               unsigned count = SPIN_THRESHOLD;
+               do {
+                       if (ACCESS_ONCE(lock->tickets.head) == inc.tail)
+                               goto out;
+                       cpu_relax();
+               } while (--count);
+               __ticket_lock_spinning(lock, inc.tail);
        }
      barrier();              /* make sure nothing creeps before the lock is taken */
out:  barrier();      /* make sure nothing creeps before the lock is taken */
  }
  
- static __always_inline int __ticket_spin_trylock(arch_spinlock_t *lock)
+ static __always_inline int arch_spin_trylock(arch_spinlock_t *lock)
  {
        arch_spinlock_t old, new;
  
        old.tickets = ACCESS_ONCE(lock->tickets);
-       if (old.tickets.head != old.tickets.tail)
+       if (old.tickets.head != (old.tickets.tail & ~TICKET_SLOWPATH_FLAG))
                return 0;
  
-       new.head_tail = old.head_tail + (1 << TICKET_SHIFT);
+       new.head_tail = old.head_tail + (TICKET_LOCK_INC << TICKET_SHIFT);
  
        /* cmpxchg is a full barrier, so nothing can move before it */
        return cmpxchg(&lock->head_tail, old.head_tail, new.head_tail) == old.head_tail;
  }
  
- static __always_inline void __ticket_spin_unlock(arch_spinlock_t *lock)
+ static inline void __ticket_unlock_slowpath(arch_spinlock_t *lock,
+                                           arch_spinlock_t old)
  {
-       __add(&lock->tickets.head, 1, UNLOCK_LOCK_PREFIX);
+       arch_spinlock_t new;
+       BUILD_BUG_ON(((__ticket_t)NR_CPUS) != NR_CPUS);
+       /* Perform the unlock on the "before" copy */
+       old.tickets.head += TICKET_LOCK_INC;
+       /* Clear the slowpath flag */
+       new.head_tail = old.head_tail & ~(TICKET_SLOWPATH_FLAG << TICKET_SHIFT);
+       /*
+        * If the lock is uncontended, clear the flag - use cmpxchg in
+        * case it changes behind our back though.
+        */
+       if (new.tickets.head != new.tickets.tail ||
+           cmpxchg(&lock->head_tail, old.head_tail,
+                                       new.head_tail) != old.head_tail) {
+               /*
+                * Lock still has someone queued for it, so wake up an
+                * appropriate waiter.
+                */
+               __ticket_unlock_kick(lock, old.tickets.head);
+       }
  }
  
- static inline int __ticket_spin_is_locked(arch_spinlock_t *lock)
+ static __always_inline void arch_spin_unlock(arch_spinlock_t *lock)
  {
-       struct __raw_tickets tmp = ACCESS_ONCE(lock->tickets);
+       if (TICKET_SLOWPATH_FLAG &&
+           static_key_false(&paravirt_ticketlocks_enabled)) {
+               arch_spinlock_t prev;
  
-       return tmp.tail != tmp.head;
- }
+               prev = *lock;
+               add_smp(&lock->tickets.head, TICKET_LOCK_INC);
  
- static inline int __ticket_spin_is_contended(arch_spinlock_t *lock)
- {
-       struct __raw_tickets tmp = ACCESS_ONCE(lock->tickets);
+               /* add_smp() is a full mb() */
  
-       return (__ticket_t)(tmp.tail - tmp.head) > 1;
+               if (unlikely(lock->tickets.tail & TICKET_SLOWPATH_FLAG))
+                       __ticket_unlock_slowpath(lock, prev);
+       } else
+               __add(&lock->tickets.head, TICKET_LOCK_INC, UNLOCK_LOCK_PREFIX);
  }
  
- #ifndef CONFIG_PARAVIRT_SPINLOCKS
  static inline int arch_spin_is_locked(arch_spinlock_t *lock)
  {
-       return __ticket_spin_is_locked(lock);
- }
- static inline int arch_spin_is_contended(arch_spinlock_t *lock)
- {
-       return __ticket_spin_is_contended(lock);
- }
- #define arch_spin_is_contended        arch_spin_is_contended
+       struct __raw_tickets tmp = ACCESS_ONCE(lock->tickets);
  
- static __always_inline void arch_spin_lock(arch_spinlock_t *lock)
- {
-       __ticket_spin_lock(lock);
+       return tmp.tail != tmp.head;
  }
  
- static __always_inline int arch_spin_trylock(arch_spinlock_t *lock)
+ static inline int arch_spin_is_contended(arch_spinlock_t *lock)
  {
-       return __ticket_spin_trylock(lock);
- }
+       struct __raw_tickets tmp = ACCESS_ONCE(lock->tickets);
  
- static __always_inline void arch_spin_unlock(arch_spinlock_t *lock)
- {
-       __ticket_spin_unlock(lock);
+       return (__ticket_t)(tmp.tail - tmp.head) > TICKET_LOCK_INC;
  }
+ #define arch_spin_is_contended        arch_spin_is_contended
  
  static __always_inline void arch_spin_lock_flags(arch_spinlock_t *lock,
                                                  unsigned long flags)
        arch_spin_lock(lock);
  }
  
- #endif        /* CONFIG_PARAVIRT_SPINLOCKS */
  static inline void arch_spin_unlock_wait(arch_spinlock_t *lock)
  {
        while (arch_spin_is_locked(lock))
@@@ -238,4 -279,8 +284,4 @@@ static inline void arch_write_unlock(ar
  #define arch_read_relax(lock) cpu_relax()
  #define arch_write_relax(lock)        cpu_relax()
  
 -/* The {read|write|spin}_lock() on x86 are full memory barriers. */
 -static inline void smp_mb__after_lock(void) { }
 -#define ARCH_HAS_SMP_MB_AFTER_LOCK
 -
  #endif /* _ASM_X86_SPINLOCK_H */
diff --combined arch/x86/kernel/kvm.c
index 7817afdac301ca55d6bf26f99d513aae607242e1,56e2fa4a8b13a203b7a8ec5ddde3d0c058449006..697b93af02ddbc0fb4461b5d853810fa250cd0a1
@@@ -34,6 -34,7 +34,7 @@@
  #include <linux/sched.h>
  #include <linux/slab.h>
  #include <linux/kprobes.h>
+ #include <linux/debugfs.h>
  #include <asm/timer.h>
  #include <asm/cpu.h>
  #include <asm/traps.h>
@@@ -419,6 -420,7 +420,7 @@@ static void __init kvm_smp_prepare_boot
        WARN_ON(kvm_register_clock("primary cpu clock"));
        kvm_guest_cpu_init();
        native_smp_prepare_boot_cpu();
+       kvm_spinlock_init();
  }
  
  static void kvm_guest_cpu_online(void *dummy)
@@@ -498,9 -500,11 +500,9 @@@ void __init kvm_guest_init(void
  #endif
  }
  
 -static bool __init kvm_detect(void)
 +static uint32_t __init kvm_detect(void)
  {
 -      if (!kvm_para_available())
 -              return false;
 -      return true;
 +      return kvm_cpuid_base();
  }
  
  const struct hypervisor_x86 x86_hyper_kvm __refconst = {
@@@ -521,3 -525,263 +523,263 @@@ static __init int activate_jump_labels(
        return 0;
  }
  arch_initcall(activate_jump_labels);
+ #ifdef CONFIG_PARAVIRT_SPINLOCKS
+ /* Kick a cpu by its apicid. Used to wake up a halted vcpu */
+ static void kvm_kick_cpu(int cpu)
+ {
+       int apicid;
+       unsigned long flags = 0;
+       apicid = per_cpu(x86_cpu_to_apicid, cpu);
+       kvm_hypercall2(KVM_HC_KICK_CPU, flags, apicid);
+ }
+ enum kvm_contention_stat {
+       TAKEN_SLOW,
+       TAKEN_SLOW_PICKUP,
+       RELEASED_SLOW,
+       RELEASED_SLOW_KICKED,
+       NR_CONTENTION_STATS
+ };
+ #ifdef CONFIG_KVM_DEBUG_FS
+ #define HISTO_BUCKETS 30
+ static struct kvm_spinlock_stats
+ {
+       u32 contention_stats[NR_CONTENTION_STATS];
+       u32 histo_spin_blocked[HISTO_BUCKETS+1];
+       u64 time_blocked;
+ } spinlock_stats;
+ static u8 zero_stats;
+ static inline void check_zero(void)
+ {
+       u8 ret;
+       u8 old;
+       old = ACCESS_ONCE(zero_stats);
+       if (unlikely(old)) {
+               ret = cmpxchg(&zero_stats, old, 0);
+               /* This ensures only one fellow resets the stat */
+               if (ret == old)
+                       memset(&spinlock_stats, 0, sizeof(spinlock_stats));
+       }
+ }
+ static inline void add_stats(enum kvm_contention_stat var, u32 val)
+ {
+       check_zero();
+       spinlock_stats.contention_stats[var] += val;
+ }
+ static inline u64 spin_time_start(void)
+ {
+       return sched_clock();
+ }
+ static void __spin_time_accum(u64 delta, u32 *array)
+ {
+       unsigned index;
+       index = ilog2(delta);
+       check_zero();
+       if (index < HISTO_BUCKETS)
+               array[index]++;
+       else
+               array[HISTO_BUCKETS]++;
+ }
+ static inline void spin_time_accum_blocked(u64 start)
+ {
+       u32 delta;
+       delta = sched_clock() - start;
+       __spin_time_accum(delta, spinlock_stats.histo_spin_blocked);
+       spinlock_stats.time_blocked += delta;
+ }
+ static struct dentry *d_spin_debug;
+ static struct dentry *d_kvm_debug;
+ struct dentry *kvm_init_debugfs(void)
+ {
+       d_kvm_debug = debugfs_create_dir("kvm", NULL);
+       if (!d_kvm_debug)
+               printk(KERN_WARNING "Could not create 'kvm' debugfs directory\n");
+       return d_kvm_debug;
+ }
+ static int __init kvm_spinlock_debugfs(void)
+ {
+       struct dentry *d_kvm;
+       d_kvm = kvm_init_debugfs();
+       if (d_kvm == NULL)
+               return -ENOMEM;
+       d_spin_debug = debugfs_create_dir("spinlocks", d_kvm);
+       debugfs_create_u8("zero_stats", 0644, d_spin_debug, &zero_stats);
+       debugfs_create_u32("taken_slow", 0444, d_spin_debug,
+                  &spinlock_stats.contention_stats[TAKEN_SLOW]);
+       debugfs_create_u32("taken_slow_pickup", 0444, d_spin_debug,
+                  &spinlock_stats.contention_stats[TAKEN_SLOW_PICKUP]);
+       debugfs_create_u32("released_slow", 0444, d_spin_debug,
+                  &spinlock_stats.contention_stats[RELEASED_SLOW]);
+       debugfs_create_u32("released_slow_kicked", 0444, d_spin_debug,
+                  &spinlock_stats.contention_stats[RELEASED_SLOW_KICKED]);
+       debugfs_create_u64("time_blocked", 0444, d_spin_debug,
+                          &spinlock_stats.time_blocked);
+       debugfs_create_u32_array("histo_blocked", 0444, d_spin_debug,
+                    spinlock_stats.histo_spin_blocked, HISTO_BUCKETS + 1);
+       return 0;
+ }
+ fs_initcall(kvm_spinlock_debugfs);
+ #else  /* !CONFIG_KVM_DEBUG_FS */
+ static inline void add_stats(enum kvm_contention_stat var, u32 val)
+ {
+ }
+ static inline u64 spin_time_start(void)
+ {
+       return 0;
+ }
+ static inline void spin_time_accum_blocked(u64 start)
+ {
+ }
+ #endif  /* CONFIG_KVM_DEBUG_FS */
+ struct kvm_lock_waiting {
+       struct arch_spinlock *lock;
+       __ticket_t want;
+ };
+ /* cpus 'waiting' on a spinlock to become available */
+ static cpumask_t waiting_cpus;
+ /* Track spinlock on which a cpu is waiting */
+ static DEFINE_PER_CPU(struct kvm_lock_waiting, klock_waiting);
+ static void kvm_lock_spinning(struct arch_spinlock *lock, __ticket_t want)
+ {
+       struct kvm_lock_waiting *w;
+       int cpu;
+       u64 start;
+       unsigned long flags;
+       if (in_nmi())
+               return;
+       w = &__get_cpu_var(klock_waiting);
+       cpu = smp_processor_id();
+       start = spin_time_start();
+       /*
+        * Make sure an interrupt handler can't upset things in a
+        * partially setup state.
+        */
+       local_irq_save(flags);
+       /*
+        * The ordering protocol on this is that the "lock" pointer
+        * may only be set non-NULL if the "want" ticket is correct.
+        * If we're updating "want", we must first clear "lock".
+        */
+       w->lock = NULL;
+       smp_wmb();
+       w->want = want;
+       smp_wmb();
+       w->lock = lock;
+       add_stats(TAKEN_SLOW, 1);
+       /*
+        * This uses set_bit, which is atomic but we should not rely on its
+        * reordering gurantees. So barrier is needed after this call.
+        */
+       cpumask_set_cpu(cpu, &waiting_cpus);
+       barrier();
+       /*
+        * Mark entry to slowpath before doing the pickup test to make
+        * sure we don't deadlock with an unlocker.
+        */
+       __ticket_enter_slowpath(lock);
+       /*
+        * check again make sure it didn't become free while
+        * we weren't looking.
+        */
+       if (ACCESS_ONCE(lock->tickets.head) == want) {
+               add_stats(TAKEN_SLOW_PICKUP, 1);
+               goto out;
+       }
+       /*
+        * halt until it's our turn and kicked. Note that we do safe halt
+        * for irq enabled case to avoid hang when lock info is overwritten
+        * in irq spinlock slowpath and no spurious interrupt occur to save us.
+        */
+       if (arch_irqs_disabled_flags(flags))
+               halt();
+       else
+               safe_halt();
+ out:
+       cpumask_clear_cpu(cpu, &waiting_cpus);
+       w->lock = NULL;
+       local_irq_restore(flags);
+       spin_time_accum_blocked(start);
+ }
+ PV_CALLEE_SAVE_REGS_THUNK(kvm_lock_spinning);
+ /* Kick vcpu waiting on @lock->head to reach value @ticket */
+ static void kvm_unlock_kick(struct arch_spinlock *lock, __ticket_t ticket)
+ {
+       int cpu;
+       add_stats(RELEASED_SLOW, 1);
+       for_each_cpu(cpu, &waiting_cpus) {
+               const struct kvm_lock_waiting *w = &per_cpu(klock_waiting, cpu);
+               if (ACCESS_ONCE(w->lock) == lock &&
+                   ACCESS_ONCE(w->want) == ticket) {
+                       add_stats(RELEASED_SLOW_KICKED, 1);
+                       kvm_kick_cpu(cpu);
+                       break;
+               }
+       }
+ }
+ /*
+  * Setup pv_lock_ops to exploit KVM_FEATURE_PV_UNHALT if present.
+  */
+ void __init kvm_spinlock_init(void)
+ {
+       if (!kvm_para_available())
+               return;
+       /* Does host kernel support KVM_FEATURE_PV_UNHALT? */
+       if (!kvm_para_has_feature(KVM_FEATURE_PV_UNHALT))
+               return;
+       printk(KERN_INFO "KVM setup paravirtual spinlock\n");
+       static_key_slow_inc(&paravirt_ticketlocks_enabled);
+       pv_lock_ops.lock_spinning = PV_CALLEE_SAVE(kvm_lock_spinning);
+       pv_lock_ops.unlock_kick = kvm_unlock_kick;
+ }
+ #endif        /* CONFIG_PARAVIRT_SPINLOCKS */
diff --combined arch/x86/xen/smp.c
index b81c88e51daa3d412a147f2088c1f51be1649d26,3b52d8075e47b6572accbc0b6dd741d9d403de2f..597655bd72b0b091dad022616c547d90c50d08e0
@@@ -279,6 -279,7 +279,7 @@@ static void __init xen_smp_prepare_boot
  
        xen_filter_cpu_maps();
        xen_setup_vcpu_info_placement();
+       xen_init_spinlocks();
  }
  
  static void __init xen_smp_prepare_cpus(unsigned int max_cpus)
@@@ -680,7 -681,6 +681,6 @@@ void __init xen_smp_init(void
  {
        smp_ops = xen_smp_ops;
        xen_fill_possible_map();
-       xen_init_spinlocks();
  }
  
  static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus)
  static int xen_hvm_cpu_up(unsigned int cpu, struct task_struct *tidle)
  {
        int rc;
 -      rc = native_cpu_up(cpu, tidle);
 -      WARN_ON (xen_smp_intr_init(cpu));
 +      /*
 +       * xen_smp_intr_init() needs to run before native_cpu_up()
 +       * so that IPI vectors are set up on the booting CPU before
 +       * it is marked online in native_cpu_up().
 +      */
 +      rc = xen_smp_intr_init(cpu);
 +      WARN_ON(rc);
 +      if (!rc)
 +              rc =  native_cpu_up(cpu, tidle);
        return rc;
  }
  
index 4019d82c3d03355f3ee3bfe1d592fa4a02838e63,226be8da3f8596dd666bf6be590a9f9e3230ba5f..866e85c5eb94517fc87ca1d49bc9acbde74dcc74
@@@ -48,6 -48,7 +48,7 @@@ struct perf_guest_info_callbacks 
  #include <linux/cpu.h>
  #include <linux/irq_work.h>
  #include <linux/static_key.h>
+ #include <linux/jump_label_ratelimit.h>
  #include <linux/atomic.h>
  #include <linux/sysfs.h>
  #include <linux/perf_regs.h>
@@@ -63,6 -64,30 +64,6 @@@ struct perf_raw_record 
        void                            *data;
  };
  
 -/*
 - * single taken branch record layout:
 - *
 - *      from: source instruction (may not always be a branch insn)
 - *        to: branch target
 - *   mispred: branch target was mispredicted
 - * predicted: branch target was predicted
 - *
 - * support for mispred, predicted is optional. In case it
 - * is not supported mispred = predicted = 0.
 - *
 - *     in_tx: running in a hardware transaction
 - *     abort: aborting a hardware transaction
 - */
 -struct perf_branch_entry {
 -      __u64   from;
 -      __u64   to;
 -      __u64   mispred:1,  /* target mispredicted */
 -              predicted:1,/* target predicted */
 -              in_tx:1,    /* in transaction */
 -              abort:1,    /* transaction abort */
 -              reserved:60;
 -};
 -
  /*
   * branch stack layout:
   *  nr: number of taken branches stored in entries[]