1
0
Fork 0
mirror of https://github.com/hermitcore/libhermit.git synced 2025-03-30 00:00:15 +01:00
libhermit/usr/rdma-core/util/mmio.c
2017-10-06 15:13:04 +02:00

83 lines
2.1 KiB
C

/* GPLv2 or OpenIB.org BSD (MIT) See COPYING file */
#include <util/mmio.h>
#include <util/udma_barrier.h>
#include <config.h>
#include <pthread.h>
#include <stdbool.h>
#if SIZEOF_LONG != 8
static pthread_spinlock_t mmio_spinlock;
static __attribute__((constructor)) void lock_constructor(void)
{
pthread_spin_init(&mmio_spinlock, PTHREAD_PROCESS_PRIVATE);
}
/* When the arch does not have a 64 bit store we provide an emulation that
does two stores in address ascending order while holding a global
spinlock. */
static void pthread_mmio_write64_be(void *addr, __be64 val)
{
__be32 first_dword = htobe32(be64toh(val) >> 32);
__be32 second_dword = htobe32(be64toh(val));
/* The WC spinlock, by definition, provides global ordering for all UC
and WC stores within the critical region. */
mmio_wc_spinlock(&mmio_spinlock);
mmio_write32_be(addr, first_dword);
mmio_write32_be(addr + 4, second_dword);
mmio_wc_spinunlock(&mmio_spinlock);
}
#if defined(__i386__)
#include <xmmintrin.h>
#include <cpuid.h>
/* For ia32 we have historically emitted movlps SSE instructions to do the 64
bit operations. */
static void __attribute__((target("sse")))
sse_mmio_write64_be(void *addr, __be64 val)
{
__m128 tmp = {};
tmp = _mm_loadl_pi(tmp, (__force __m64 *)&val);
_mm_storel_pi((__m64 *)addr,tmp);
}
static bool have_sse(void)
{
unsigned int ax,bx,cx,dx;
if (!__get_cpuid(1,&ax,&bx,&cx,&dx))
return false;
return dx & bit_SSE;
}
#endif /* defined(__i386__) */
typedef void (*write64_fn_t)(void *, __be64);
/* This uses the STT_GNU_IFUNC extension to have the dynamic linker select the
best above implementations at runtime. */
#if HAVE_FUNC_ATTRIBUTE_IFUNC
void mmio_write64_be(void *addr, __be64 val)
__attribute__((ifunc("resolve_mmio_write64_be")));
static write64_fn_t resolve_mmio_write64_be(void);
#else
__asm__(".type mmio_write64_be, %gnu_indirect_function");
write64_fn_t resolve_mmio_write64_be(void) __asm__("mmio_write64_be");
#endif
write64_fn_t resolve_mmio_write64_be(void)
{
#if defined(__i386__)
if (have_sse())
return &sse_mmio_write64_be;
#endif
return &pthread_mmio_write64_be;
}
#endif /* SIZEOF_LONG != 8 */