Skip to content

Commit

Permalink
Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/mst/vhost

Pull virtio barrier rework+fixes from Michael Tsirkin:
 "This adds a new kind of barrier, and reworks virtio and xen to use it.

  Plus some fixes here and there"

* tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost: (44 commits)
  checkpatch: add virt barriers
  checkpatch: check for __smp outside barrier.h
  checkpatch.pl: add missing memory barriers
  virtio: make find_vqs() checkpatch.pl-friendly
  virtio_balloon: fix race between migration and ballooning
  virtio_balloon: fix race by fill and leak
  s390: more efficient smp barriers
  s390: use generic memory barriers
  xen/events: use virt_xxx barriers
  xen/io: use virt_xxx barriers
  xenbus: use virt_xxx barriers
  virtio_ring: use virt_store_mb
  sh: move xchg_cmpxchg to a header by itself
  sh: support 1 and 2 byte xchg
  virtio_ring: update weak barriers to use virt_xxx
  Revert "virtio_ring: Update weak barriers to use dma_wmb/rmb"
  asm-generic: implement virt_xxx memory barriers
  x86: define __smp_xxx
  xtensa: define __smp_xxx
  tile: define __smp_xxx
  ...
  • Loading branch information
Linus Torvalds committed Jan 19, 2016
2 parents d05d82f + 43e361f commit a200dcb
Show file tree
Hide file tree
Showing 44 changed files with 401 additions and 319 deletions.
28 changes: 23 additions & 5 deletions Documentation/memory-barriers.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1655,17 +1655,18 @@ macro is a good place to start looking.
SMP memory barriers are reduced to compiler barriers on uniprocessor compiled
systems because it is assumed that a CPU will appear to be self-consistent,
and will order overlapping accesses correctly with respect to itself.
However, see the subsection on "Virtual Machine Guests" below.

[!] Note that SMP memory barriers _must_ be used to control the ordering of
references to shared memory on SMP systems, though the use of locking instead
is sufficient.

Mandatory barriers should not be used to control SMP effects, since mandatory
barriers unnecessarily impose overhead on UP systems. They may, however, be
used to control MMIO effects on accesses through relaxed memory I/O windows.
These are required even on non-SMP systems as they affect the order in which
memory operations appear to a device by prohibiting both the compiler and the
CPU from reordering them.
barriers impose unnecessary overhead on both SMP and UP systems. They may,
however, be used to control MMIO effects on accesses through relaxed memory I/O
windows. These barriers are required even on non-SMP systems as they affect
the order in which memory operations appear to a device by prohibiting both the
compiler and the CPU from reordering them.


There are some more advanced barrier functions:
Expand Down Expand Up @@ -2948,6 +2949,23 @@ The Alpha defines the Linux kernel's memory barrier model.

See the subsection on "Cache Coherency" above.

VIRTUAL MACHINE GUESTS
-------------------

Guests running within virtual machines might be affected by SMP effects even if
the guest itself is compiled without SMP support. This is an artifact of
interfacing with an SMP host while running an UP kernel. Using mandatory
barriers for this use-case would be possible but is often suboptimal.

To handle this case optimally, low-level virt_mb() etc macros are available.
These have the same effect as smp_mb() etc when SMP is enabled, but generate
identical code for SMP and non-SMP systems. For example, virtual machine guests
should use virt_mb() rather than smp_mb() when synchronizing against a
(possibly SMP) host.

These are equivalent to smp_mb() etc counterparts in all other respects,
in particular, they do not control MMIO effects: to control
MMIO effects, use mandatory barriers.

============
EXAMPLE USES
Expand Down
35 changes: 4 additions & 31 deletions arch/arm/include/asm/barrier.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,38 +60,11 @@ extern void arm_heavy_mb(void);
#define dma_wmb() barrier()
#endif

#ifndef CONFIG_SMP
#define smp_mb() barrier()
#define smp_rmb() barrier()
#define smp_wmb() barrier()
#else
#define smp_mb() dmb(ish)
#define smp_rmb() smp_mb()
#define smp_wmb() dmb(ishst)
#endif

#define smp_store_release(p, v) \
do { \
compiletime_assert_atomic_type(*p); \
smp_mb(); \
WRITE_ONCE(*p, v); \
} while (0)

#define smp_load_acquire(p) \
({ \
typeof(*p) ___p1 = READ_ONCE(*p); \
compiletime_assert_atomic_type(*p); \
smp_mb(); \
___p1; \
})

#define read_barrier_depends() do { } while(0)
#define smp_read_barrier_depends() do { } while(0)

#define smp_store_mb(var, value) do { WRITE_ONCE(var, value); smp_mb(); } while (0)
#define __smp_mb() dmb(ish)
#define __smp_rmb() __smp_mb()
#define __smp_wmb() dmb(ishst)

#define smp_mb__before_atomic() smp_mb()
#define smp_mb__after_atomic() smp_mb()
#include <asm-generic/barrier.h>

#endif /* !__ASSEMBLY__ */
#endif /* __ASM_BARRIER_H */
19 changes: 6 additions & 13 deletions arch/arm64/include/asm/barrier.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@
#define dma_rmb() dmb(oshld)
#define dma_wmb() dmb(oshst)

#define smp_mb() dmb(ish)
#define smp_rmb() dmb(ishld)
#define smp_wmb() dmb(ishst)
#define __smp_mb() dmb(ish)
#define __smp_rmb() dmb(ishld)
#define __smp_wmb() dmb(ishst)

#define smp_store_release(p, v) \
#define __smp_store_release(p, v) \
do { \
compiletime_assert_atomic_type(*p); \
switch (sizeof(*p)) { \
Expand All @@ -62,7 +62,7 @@ do { \
} \
} while (0)

#define smp_load_acquire(p) \
#define __smp_load_acquire(p) \
({ \
union { typeof(*p) __val; char __c[1]; } __u; \
compiletime_assert_atomic_type(*p); \
Expand Down Expand Up @@ -91,14 +91,7 @@ do { \
__u.__val; \
})

#define read_barrier_depends() do { } while(0)
#define smp_read_barrier_depends() do { } while(0)

#define smp_store_mb(var, value) do { WRITE_ONCE(var, value); smp_mb(); } while (0)
#define nop() asm volatile("nop");

#define smp_mb__before_atomic() smp_mb()
#define smp_mb__after_atomic() smp_mb()
#include <asm-generic/barrier.h>

#endif /* __ASSEMBLY__ */

Expand Down
4 changes: 2 additions & 2 deletions arch/blackfin/include/asm/barrier.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@

#endif /* !CONFIG_SMP */

#define smp_mb__before_atomic() barrier()
#define smp_mb__after_atomic() barrier()
#define __smp_mb__before_atomic() barrier()
#define __smp_mb__after_atomic() barrier()

#include <asm-generic/barrier.h>

Expand Down
24 changes: 7 additions & 17 deletions arch/ia64/include/asm/barrier.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,47 +42,37 @@
#define dma_rmb() mb()
#define dma_wmb() mb()

#ifdef CONFIG_SMP
# define smp_mb() mb()
#else
# define smp_mb() barrier()
#endif
# define __smp_mb() mb()

#define smp_rmb() smp_mb()
#define smp_wmb() smp_mb()

#define read_barrier_depends() do { } while (0)
#define smp_read_barrier_depends() do { } while (0)

#define smp_mb__before_atomic() barrier()
#define smp_mb__after_atomic() barrier()
#define __smp_mb__before_atomic() barrier()
#define __smp_mb__after_atomic() barrier()

/*
* IA64 GCC turns volatile stores into st.rel and volatile loads into ld.acq no
* need for asm trickery!
*/

#define smp_store_release(p, v) \
#define __smp_store_release(p, v) \
do { \
compiletime_assert_atomic_type(*p); \
barrier(); \
WRITE_ONCE(*p, v); \
} while (0)

#define smp_load_acquire(p) \
#define __smp_load_acquire(p) \
({ \
typeof(*p) ___p1 = READ_ONCE(*p); \
compiletime_assert_atomic_type(*p); \
barrier(); \
___p1; \
})

#define smp_store_mb(var, value) do { WRITE_ONCE(var, value); smp_mb(); } while (0)

/*
* The group barrier in front of the rsm & ssm are necessary to ensure
* that none of the previous instructions in the same group are
* affected by the rsm/ssm.
*/

#include <asm-generic/barrier.h>

#endif /* _ASM_IA64_BARRIER_H */
6 changes: 3 additions & 3 deletions arch/ia64/kernel/iosapic.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ set_rte (unsigned int gsi, unsigned int irq, unsigned int dest, int mask)
}

static void
nop (struct irq_data *data)
iosapic_nop (struct irq_data *data)
{
/* do nothing... */
}
Expand Down Expand Up @@ -415,7 +415,7 @@ iosapic_unmask_level_irq (struct irq_data *data)
#define iosapic_shutdown_level_irq mask_irq
#define iosapic_enable_level_irq unmask_irq
#define iosapic_disable_level_irq mask_irq
#define iosapic_ack_level_irq nop
#define iosapic_ack_level_irq iosapic_nop

static struct irq_chip irq_type_iosapic_level = {
.name = "IO-SAPIC-level",
Expand Down Expand Up @@ -453,7 +453,7 @@ iosapic_ack_edge_irq (struct irq_data *data)
}

#define iosapic_enable_edge_irq unmask_irq
#define iosapic_disable_edge_irq nop
#define iosapic_disable_edge_irq iosapic_nop

static struct irq_chip irq_type_iosapic_edge = {
.name = "IO-SAPIC-edge",
Expand Down
55 changes: 16 additions & 39 deletions arch/metag/include/asm/barrier.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,6 @@ static inline void wr_fence(void)
#define rmb() barrier()
#define wmb() mb()

#define dma_rmb() rmb()
#define dma_wmb() wmb()

#ifndef CONFIG_SMP
#define fence() do { } while (0)
#define smp_mb() barrier()
#define smp_rmb() barrier()
#define smp_wmb() barrier()
#else

#ifdef CONFIG_METAG_SMP_WRITE_REORDERING
/*
* Write to the atomic memory unlock system event register (command 0). This is
Expand All @@ -63,45 +53,32 @@ static inline void wr_fence(void)
* incoherence). It is therefore ineffective if used after and on the same
* thread as a write.
*/
static inline void fence(void)
static inline void metag_fence(void)
{
volatile int *flushptr = (volatile int *) LINSYSEVENT_WR_ATOMIC_UNLOCK;
barrier();
*flushptr = 0;
barrier();
}
#define smp_mb() fence()
#define smp_rmb() fence()
#define smp_wmb() barrier()
#define __smp_mb() metag_fence()
#define __smp_rmb() metag_fence()
#define __smp_wmb() barrier()
#else
#define fence() do { } while (0)
#define smp_mb() barrier()
#define smp_rmb() barrier()
#define smp_wmb() barrier()
#endif
#define metag_fence() do { } while (0)
#define __smp_mb() barrier()
#define __smp_rmb() barrier()
#define __smp_wmb() barrier()
#endif

#define read_barrier_depends() do { } while (0)
#define smp_read_barrier_depends() do { } while (0)

#define smp_store_mb(var, value) do { WRITE_ONCE(var, value); smp_mb(); } while (0)

#define smp_store_release(p, v) \
do { \
compiletime_assert_atomic_type(*p); \
smp_mb(); \
WRITE_ONCE(*p, v); \
} while (0)
#ifdef CONFIG_SMP
#define fence() metag_fence()
#else
#define fence() do { } while (0)
#endif

#define smp_load_acquire(p) \
({ \
typeof(*p) ___p1 = READ_ONCE(*p); \
compiletime_assert_atomic_type(*p); \
smp_mb(); \
___p1; \
})
#define __smp_mb__before_atomic() barrier()
#define __smp_mb__after_atomic() barrier()

#define smp_mb__before_atomic() barrier()
#define smp_mb__after_atomic() barrier()
#include <asm-generic/barrier.h>

#endif /* _ASM_METAG_BARRIER_H */
51 changes: 16 additions & 35 deletions arch/mips/include/asm/barrier.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@

#include <asm/addrspace.h>

#define read_barrier_depends() do { } while(0)
#define smp_read_barrier_depends() do { } while(0)

#ifdef CONFIG_CPU_HAS_SYNC
#define __sync() \
__asm__ __volatile__( \
Expand Down Expand Up @@ -87,23 +84,21 @@

#define wmb() fast_wmb()
#define rmb() fast_rmb()
#define dma_wmb() fast_wmb()
#define dma_rmb() fast_rmb()

#if defined(CONFIG_WEAK_ORDERING) && defined(CONFIG_SMP)
#if defined(CONFIG_WEAK_ORDERING)
# ifdef CONFIG_CPU_CAVIUM_OCTEON
# define smp_mb() __sync()
# define smp_rmb() barrier()
# define smp_wmb() __syncw()
# define __smp_mb() __sync()
# define __smp_rmb() barrier()
# define __smp_wmb() __syncw()
# else
# define smp_mb() __asm__ __volatile__("sync" : : :"memory")
# define smp_rmb() __asm__ __volatile__("sync" : : :"memory")
# define smp_wmb() __asm__ __volatile__("sync" : : :"memory")
# define __smp_mb() __asm__ __volatile__("sync" : : :"memory")
# define __smp_rmb() __asm__ __volatile__("sync" : : :"memory")
# define __smp_wmb() __asm__ __volatile__("sync" : : :"memory")
# endif
#else
#define smp_mb() barrier()
#define smp_rmb() barrier()
#define smp_wmb() barrier()
#define __smp_mb() barrier()
#define __smp_rmb() barrier()
#define __smp_wmb() barrier()
#endif

#if defined(CONFIG_WEAK_REORDERING_BEYOND_LLSC) && defined(CONFIG_SMP)
Expand All @@ -112,39 +107,25 @@
#define __WEAK_LLSC_MB " \n"
#endif

#define smp_store_mb(var, value) \
do { WRITE_ONCE(var, value); smp_mb(); } while (0)

#define smp_llsc_mb() __asm__ __volatile__(__WEAK_LLSC_MB : : :"memory")

#ifdef CONFIG_CPU_CAVIUM_OCTEON
#define smp_mb__before_llsc() smp_wmb()
#define __smp_mb__before_llsc() __smp_wmb()
/* Cause previous writes to become visible on all CPUs as soon as possible */
#define nudge_writes() __asm__ __volatile__(".set push\n\t" \
".set arch=octeon\n\t" \
"syncw\n\t" \
".set pop" : : : "memory")
#else
#define smp_mb__before_llsc() smp_llsc_mb()
#define __smp_mb__before_llsc() smp_llsc_mb()
#define nudge_writes() mb()
#endif

#define smp_store_release(p, v) \
do { \
compiletime_assert_atomic_type(*p); \
smp_mb(); \
WRITE_ONCE(*p, v); \
} while (0)

#define smp_load_acquire(p) \
({ \
typeof(*p) ___p1 = READ_ONCE(*p); \
compiletime_assert_atomic_type(*p); \
smp_mb(); \
___p1; \
})

#define smp_mb__before_atomic() smp_mb__before_llsc()
#define smp_mb__after_atomic() smp_llsc_mb()
#define __smp_mb__before_atomic() __smp_mb__before_llsc()
#define __smp_mb__after_atomic() smp_llsc_mb()

#include <asm-generic/barrier.h>

#endif /* __ASM_BARRIER_H */
Loading

0 comments on commit a200dcb

Please sign in to comment.