barrier: add compiler barrier and use it in MMIO

spdk_compiler_barrier() prevents the compiler from moving pointer
dereferences across the barrier.

Use this in the MMIO helper functions to ensure that the compiler can't
reorder operations around e.g. hardware register access.

Specifically, this fixes the compiler optimizing out writes to
g_thread_mmio_ctrlr in the NVMe hotplug handling code.

Change-Id: I6b9cec48da0e6d8d75825c28b12ece5251110080
Signed-off-by: Daniel Verkamp <daniel.verkamp@intel.com>
This commit is contained in:
Daniel Verkamp 2017-02-06 17:37:18 -07:00
parent 4baf5962e9
commit 4a1d47ebea
2 changed files with 11 additions and 0 deletions

View File

@ -42,6 +42,9 @@
extern "C" { extern "C" {
#endif #endif
/** Compiler memory barrier */
#define spdk_compiler_barrier() __asm volatile("" ::: "memory")
/** Write memory barrier */ /** Write memory barrier */
#define spdk_wmb() __asm volatile("sfence" ::: "memory") #define spdk_wmb() __asm volatile("sfence" ::: "memory")

View File

@ -44,6 +44,8 @@ extern "C" {
#include <inttypes.h> #include <inttypes.h>
#include "spdk/barrier.h"
#ifdef __x86_64__ #ifdef __x86_64__
#define SPDK_MMIO_64BIT 1 /* Can do atomic 64-bit memory read/write (over PCIe) */ #define SPDK_MMIO_64BIT 1 /* Can do atomic 64-bit memory read/write (over PCIe) */
#else #else
@ -53,12 +55,14 @@ extern "C" {
static inline uint32_t static inline uint32_t
spdk_mmio_read_4(const volatile uint32_t *addr) spdk_mmio_read_4(const volatile uint32_t *addr)
{ {
spdk_compiler_barrier();
return *addr; return *addr;
} }
static inline void static inline void
spdk_mmio_write_4(volatile uint32_t *addr, uint32_t val) spdk_mmio_write_4(volatile uint32_t *addr, uint32_t val)
{ {
spdk_compiler_barrier();
*addr = val; *addr = val;
} }
@ -68,6 +72,8 @@ spdk_mmio_read_8(volatile uint64_t *addr)
uint64_t val; uint64_t val;
volatile uint32_t *addr32 = (volatile uint32_t *)addr; volatile uint32_t *addr32 = (volatile uint32_t *)addr;
spdk_compiler_barrier();
if (SPDK_MMIO_64BIT) { if (SPDK_MMIO_64BIT) {
val = *addr; val = *addr;
} else { } else {
@ -88,6 +94,8 @@ spdk_mmio_write_8(volatile uint64_t *addr, uint64_t val)
{ {
volatile uint32_t *addr32 = (volatile uint32_t *)addr; volatile uint32_t *addr32 = (volatile uint32_t *)addr;
spdk_compiler_barrier();
if (SPDK_MMIO_64BIT) { if (SPDK_MMIO_64BIT) {
*addr = val; *addr = val;
} else { } else {