Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a200dcb3 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
  ...
parents d05d82f7 43e361f2
Loading
Loading
Loading
Loading
+23 −5
Original line number Diff line number Diff line
@@ -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:
@@ -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
+4 −31
Original line number Diff line number Diff line
@@ -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 */
+6 −13
Original line number Diff line number Diff line
@@ -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)) {						\
@@ -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);				\
@@ -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__ */

+2 −2
Original line number Diff line number Diff line
@@ -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>

+7 −17
Original line number Diff line number Diff line
@@ -42,34 +42,24 @@
#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);				\
@@ -77,12 +67,12 @@ do { \
	___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 */
Loading