summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSage Weil <sage@inktank.com>2013-09-03 08:38:31 -0700
committerSage Weil <sage@inktank.com>2013-09-04 16:05:00 -0700
commitcfb07f14515586a0c50ffb9ec90c3a5606327f06 (patch)
tree4b20481544ec52e8c7b5183a135817517ece86d0
parent83a4848e27b127b11df90c12dd2f52d03c023005 (diff)
downloadceph-cfb07f14515586a0c50ffb9ec90c3a5606327f06.tar.gz
arch: add NEON cpu feature detection
Signed-off-by: Sage Weil <sage@inktank.com> Reviewed-by: Dan Mick <dan.mick@inktank.com>
-rw-r--r--configure.ac3
-rw-r--r--src/Makefile.am11
-rw-r--r--src/arch/neon.c51
-rw-r--r--src/arch/neon.h16
-rw-r--r--src/arch/probe.cc2
-rw-r--r--src/test/test_arch.c19
6 files changed, 102 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index cfe9e841e17..d042d3d2821 100644
--- a/configure.ac
+++ b/configure.ac
@@ -106,6 +106,9 @@ AC_DEFUN([AC_CHECK_CC_FLAG],
AC_CHECK_CC_FLAG([-Wtype-limits], [WARN_TYPE_LIMITS])
AC_CHECK_CC_FLAG([-Wignored-qualifiers], [WARN_IGNORED_QUALIFIERS])
+# Checks for architecture stuff
+AM_CONDITIONAL([ENABLE_FPU_NEON], [case $target_cpu in arm*) true;; *) false;; esac])
+
# Checks for libraries.
ACX_PTHREAD
AC_CHECK_LIB([uuid], [uuid_parse], [true], AC_MSG_FAILURE([libuuid not found]))
diff --git a/src/Makefile.am b/src/Makefile.am
index 3bdec278c6f..7d87c7b5f60 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -775,6 +775,10 @@ unittest_addrs_CXXFLAGS = ${AM_CXXFLAGS} ${UNITTEST_CXXFLAGS}
unittest_addrs_LDADD = $(LIBGLOBAL_LDA) ${UNITTEST_LDADD}
check_PROGRAMS += unittest_addrs
+unittest_arch_SOURCES = test/test_arch.c arch/intel.c arch/neon.c arch/probe.cc
+unittest_arch_CXXFLAGS = ${AM_CFLAGS}
+check_PROGRAMS += unittest_arch
+
unittest_sharedptr_registry_SOURCES = test/common/test_sharedptr_registry.cc
unittest_sharedptr_registry_CXXFLAGS = ${AM_CXXFLAGS} ${UNITTEST_CXXFLAGS}
unittest_sharedptr_registry_LDADD = libcommon.la ${LIBGLOBAL_LDA} ${UNITTEST_LDADD}
@@ -1340,6 +1344,11 @@ AM_CXXFLAGS = \
-Wnon-virtual-dtor \
-Wno-invalid-offsetof
+if ENABLE_FPU_NEON
+AM_CFLAGS += -mfpu=neon
+AM_CXXFLAGS += -mfpu=neon
+endif
+
if !CLANG
AM_CXXFLAGS += -Wstrict-null-sentinel
endif
@@ -1521,6 +1530,7 @@ libcommon_files = \
./ceph_ver.c \
arch/probe.cc \
arch/intel.c \
+ arch/neon.c \
auth/AuthAuthorizeHandler.cc \
auth/AuthClientHandler.cc \
auth/AuthSessionHandler.cc \
@@ -1772,6 +1782,7 @@ noinst_HEADERS = \
rados_sync.h \
arch/probe.h \
arch/intel.h \
+ arch/neon.h \
auth/cephx/CephxAuthorizeHandler.h\
auth/cephx/CephxKeyServer.h\
auth/cephx/CephxProtocol.h\
diff --git a/src/arch/neon.c b/src/arch/neon.c
new file mode 100644
index 00000000000..32c1f621ef7
--- /dev/null
+++ b/src/arch/neon.c
@@ -0,0 +1,51 @@
+#include "arch/probe.h"
+
+/* flags we export */
+int ceph_arch_neon = 0;
+
+#include <stdio.h>
+
+#if __linux__
+
+#include <elf.h>
+#include <link.h> // ElfW macro
+
+#if __arm__
+#include <asm/hwcap.h>
+#endif // __arm__
+
+static unsigned long get_auxval(unsigned long type)
+{
+ unsigned long result = 0;
+ FILE *f = fopen("/proc/self/auxv", "r");
+ if (f) {
+ ElfW(auxv_t) entry;
+ while (fread(&entry, sizeof(entry), 1, f)) {
+ if (entry.a_type == type) {
+ result = entry.a_un.a_val;
+ break;
+ }
+ }
+ fclose(f);
+ }
+ return result;
+}
+
+static unsigned long get_hwcap(void)
+{
+ return get_auxval(AT_HWCAP);
+}
+
+#endif // __linux__
+
+int ceph_arch_neon_probe(void)
+{
+#if __arm__ && __linux__
+ ceph_arch_neon = (get_hwcap() & HWCAP_NEON) == HWCAP_NEON;
+#else
+ if (0)
+ get_hwcap(); // make compiler shut up
+#endif
+ return 0;
+}
+
diff --git a/src/arch/neon.h b/src/arch/neon.h
new file mode 100644
index 00000000000..0c8aacf5e87
--- /dev/null
+++ b/src/arch/neon.h
@@ -0,0 +1,16 @@
+#ifndef CEPH_ARCH_NEON_H
+#define CEPH_ARCH_NEON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int ceph_arch_neon; /* true if we have ARM NEON abilities */
+
+extern int ceph_arch_neon_probe(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/arch/probe.cc b/src/arch/probe.cc
index 9f8bc9d2d0f..8648e54d945 100644
--- a/src/arch/probe.cc
+++ b/src/arch/probe.cc
@@ -4,6 +4,7 @@
#include "arch/probe.h"
#include "arch/intel.h"
+#include "arch/neon.h"
int ceph_arch_probe(void)
{
@@ -11,6 +12,7 @@ int ceph_arch_probe(void)
return 1;
ceph_arch_intel_probe();
+ ceph_arch_neon_probe();
ceph_arch_probed = 1;
return 1;
diff --git a/src/test/test_arch.c b/src/test/test_arch.c
new file mode 100644
index 00000000000..549221e60f9
--- /dev/null
+++ b/src/test/test_arch.c
@@ -0,0 +1,19 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "arch/probe.h"
+#include "arch/intel.h"
+#include "arch/neon.h"
+
+int main(int argc, char **argv)
+{
+ ceph_arch_probe();
+ assert(ceph_arch_probed);
+
+ printf("ceph_arch_intel_sse42 = %d\n", ceph_arch_intel_sse42);
+ printf("ceph_arch_neon = %d\n", ceph_arch_neon);
+
+ return 0;
+}