summaryrefslogtreecommitdiffstats
path: root/src/arch
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/CMakeLists.txt12
-rw-r--r--src/arch/arm.c37
-rw-r--r--src/arch/arm.h18
-rw-r--r--src/arch/intel.c80
-rw-r--r--src/arch/intel.h22
-rw-r--r--src/arch/ppc.c40
-rw-r--r--src/arch/ppc.h24
-rw-r--r--src/arch/probe.cc26
-rw-r--r--src/arch/probe.h16
9 files changed, 275 insertions, 0 deletions
diff --git a/src/arch/CMakeLists.txt b/src/arch/CMakeLists.txt
new file mode 100644
index 00000000..b2386285
--- /dev/null
+++ b/src/arch/CMakeLists.txt
@@ -0,0 +1,12 @@
+set(arch_srcs
+ probe.cc)
+
+if(HAVE_ARM)
+ list(APPEND arch_srcs arm.c)
+elseif(HAVE_INTEL)
+ list(APPEND arch_srcs intel.c)
+elseif(HAVE_POWER8)
+ list(APPEND arch_srcs ppc.c)
+endif()
+
+add_library(arch STATIC ${arch_srcs})
diff --git a/src/arch/arm.c b/src/arch/arm.c
new file mode 100644
index 00000000..02f0107b
--- /dev/null
+++ b/src/arch/arm.c
@@ -0,0 +1,37 @@
+#include "acconfig.h"
+#include "arch/probe.h"
+
+/* flags we export */
+int ceph_arch_neon = 0;
+int ceph_arch_aarch64_crc32 = 0;
+int ceph_arch_aarch64_pmull = 0;
+
+#include <stdio.h>
+
+#if __linux__
+
+#include <elf.h>
+#include <link.h> // ElfW macro
+#include <sys/auxv.h>
+
+#if __arm__ || __aarch64__
+#include <asm/hwcap.h>
+#endif // __arm__
+
+#endif // __linux__
+
+int ceph_arch_arm_probe(void)
+{
+#if __linux__
+ unsigned long hwcap = getauxval(AT_HWCAP);
+#if __arm__
+ ceph_arch_neon = (hwcap & HWCAP_NEON) == HWCAP_NEON;
+#elif __aarch64__
+ ceph_arch_neon = (hwcap & HWCAP_ASIMD) == HWCAP_ASIMD;
+ ceph_arch_aarch64_crc32 = (hwcap & HWCAP_CRC32) == HWCAP_CRC32;
+ ceph_arch_aarch64_pmull = (hwcap & HWCAP_PMULL) == HWCAP_PMULL;
+#endif
+#endif // __linux__
+ return 0;
+}
+
diff --git a/src/arch/arm.h b/src/arch/arm.h
new file mode 100644
index 00000000..dacc450b
--- /dev/null
+++ b/src/arch/arm.h
@@ -0,0 +1,18 @@
+#ifndef CEPH_ARCH_ARM_H
+#define CEPH_ARCH_ARM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int ceph_arch_neon; /* true if we have ARM NEON or ASIMD abilities */
+extern int ceph_arch_aarch64_crc32; /* true if we have AArch64 CRC32/CRC32C abilities */
+extern int ceph_arch_aarch64_pmull; /* true if we have AArch64 PMULL abilities */
+
+extern int ceph_arch_arm_probe(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/arch/intel.c b/src/arch/intel.c
new file mode 100644
index 00000000..5c483dcc
--- /dev/null
+++ b/src/arch/intel.c
@@ -0,0 +1,80 @@
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2013,2014 Inktank Storage, Inc.
+ * Copyright (C) 2014 Cloudwatt <libre.licensing@cloudwatt.com>
+ *
+ * Author: Loic Dachary <loic@dachary.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ */
+#include <stdio.h>
+#include "arch/probe.h"
+
+/* flags we export */
+int ceph_arch_intel_pclmul = 0;
+int ceph_arch_intel_sse42 = 0;
+int ceph_arch_intel_sse41 = 0;
+int ceph_arch_intel_ssse3 = 0;
+int ceph_arch_intel_sse3 = 0;
+int ceph_arch_intel_sse2 = 0;
+int ceph_arch_intel_aesni = 0;
+
+#ifdef __x86_64__
+#include <cpuid.h>
+
+/* http://en.wikipedia.org/wiki/CPUID#EAX.3D1:_Processor_Info_and_Feature_Bits */
+
+#define CPUID_PCLMUL (1 << 1)
+#define CPUID_SSE42 (1 << 20)
+#define CPUID_SSE41 (1 << 19)
+#define CPUID_SSSE3 (1 << 9)
+#define CPUID_SSE3 (1)
+#define CPUID_SSE2 (1 << 26)
+#define CPUID_AESNI (1 << 25)
+
+int ceph_arch_intel_probe(void)
+{
+ /* i know how to check this on x86_64... */
+ unsigned int eax, ebx, ecx = 0, edx = 0;
+ if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx)) {
+ return 1;
+ }
+ if ((ecx & CPUID_PCLMUL) != 0) {
+ ceph_arch_intel_pclmul = 1;
+ }
+ if ((ecx & CPUID_SSE42) != 0) {
+ ceph_arch_intel_sse42 = 1;
+ }
+ if ((ecx & CPUID_SSE41) != 0) {
+ ceph_arch_intel_sse41 = 1;
+ }
+ if ((ecx & CPUID_SSSE3) != 0) {
+ ceph_arch_intel_ssse3 = 1;
+ }
+ if ((ecx & CPUID_SSE3) != 0) {
+ ceph_arch_intel_sse3 = 1;
+ }
+ if ((edx & CPUID_SSE2) != 0) {
+ ceph_arch_intel_sse2 = 1;
+ }
+ if ((ecx & CPUID_AESNI) != 0) {
+ ceph_arch_intel_aesni = 1;
+ }
+
+ return 0;
+}
+
+#else // __x86_64__
+
+int ceph_arch_intel_probe(void)
+{
+ /* no features */
+ return 0;
+}
+
+#endif // __x86_64__
diff --git a/src/arch/intel.h b/src/arch/intel.h
new file mode 100644
index 00000000..3f4ae948
--- /dev/null
+++ b/src/arch/intel.h
@@ -0,0 +1,22 @@
+#ifndef CEPH_ARCH_INTEL_H
+#define CEPH_ARCH_INTEL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int ceph_arch_intel_pclmul; /* true if we have PCLMUL features */
+extern int ceph_arch_intel_sse42; /* true if we have sse 4.2 features */
+extern int ceph_arch_intel_sse41; /* true if we have sse 4.1 features */
+extern int ceph_arch_intel_ssse3; /* true if we have ssse 3 features */
+extern int ceph_arch_intel_sse3; /* true if we have sse 3 features */
+extern int ceph_arch_intel_sse2; /* true if we have sse 2 features */
+extern int ceph_arch_intel_aesni; /* true if we have aesni features */
+
+extern int ceph_arch_intel_probe(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/arch/ppc.c b/src/arch/ppc.c
new file mode 100644
index 00000000..11d3a499
--- /dev/null
+++ b/src/arch/ppc.c
@@ -0,0 +1,40 @@
+/* Copyright (C) 2017 International Business Machines Corp.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include "arch/ppc.h"
+#include "arch/probe.h"
+
+/* flags we export */
+int ceph_arch_ppc_crc32 = 0;
+
+#include <stdio.h>
+
+#ifdef HAVE_PPC64LE
+#include <sys/auxv.h>
+#include <asm/cputable.h>
+#endif /* HAVE_PPC64LE */
+
+#ifndef PPC_FEATURE2_VEC_CRYPTO
+#define PPC_FEATURE2_VEC_CRYPTO 0x02000000
+#endif
+
+#ifndef AT_HWCAP2
+#define AT_HWCAP2 26
+#endif
+
+int ceph_arch_ppc_probe(void)
+{
+ ceph_arch_ppc_crc32 = 0;
+
+#ifdef HAVE_PPC64LE
+ if (getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO) ceph_arch_ppc_crc32 = 1;
+#endif /* HAVE_PPC64LE */
+
+ return 0;
+}
+
diff --git a/src/arch/ppc.h b/src/arch/ppc.h
new file mode 100644
index 00000000..e53d63e3
--- /dev/null
+++ b/src/arch/ppc.h
@@ -0,0 +1,24 @@
+/* Copyright (C) 2017 International Business Machines Corp.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef CEPH_ARCH_PPC_H
+#define CEPH_ARCH_PPC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int ceph_arch_ppc_crc32;
+
+extern int ceph_arch_ppc_probe(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/arch/probe.cc b/src/arch/probe.cc
new file mode 100644
index 00000000..52b913b1
--- /dev/null
+++ b/src/arch/probe.cc
@@ -0,0 +1,26 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "arch/probe.h"
+
+#include "arch/intel.h"
+#include "arch/arm.h"
+#include "arch/ppc.h"
+
+int ceph_arch_probe(void)
+{
+ if (ceph_arch_probed)
+ return 1;
+#if defined(__i386__) || defined(__x86_64__)
+ ceph_arch_intel_probe();
+#elif defined(__arm__) || defined(__aarch64__)
+ ceph_arch_arm_probe();
+#elif defined(__powerpc__) || defined(__ppc__)
+ ceph_arch_ppc_probe();
+#endif
+ ceph_arch_probed = 1;
+ return 1;
+}
+
+// do this once using the magic of c++.
+int ceph_arch_probed = ceph_arch_probe();
diff --git a/src/arch/probe.h b/src/arch/probe.h
new file mode 100644
index 00000000..a789c4e8
--- /dev/null
+++ b/src/arch/probe.h
@@ -0,0 +1,16 @@
+#ifndef CEPH_ARCH_PROBE_H
+#define CEPH_ARCH_PROBE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int ceph_arch_probed; /* non-zero if we've probed features */
+
+extern int ceph_arch_probe(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif