aboutsummaryrefslogtreecommitdiffstats
path: root/include/os
diff options
context:
space:
mode:
authorRomain Dolbeau <[email protected]>2020-01-23 20:01:24 +0100
committerBrian Behlendorf <[email protected]>2020-01-23 11:01:24 -0800
commit35b07497c60701465a87aab48fc890a0bc502561 (patch)
treeded14fd0cfd7c3dd985617ae1d576d4e26c165a2 /include/os
parent1a69856034304e74b32fb372e89967e91989cafd (diff)
Add AltiVec RAID-Z
Implements the RAID-Z function using AltiVec SIMD. This is basically the NEON code translated to AltiVec. Note that the 'fletcher' algorithm requires 64-bits operations, and the initial implementations of AltiVec (PPC74xx a.k.a. G4, PPC970 a.k.a. G5) only has up to 32-bits operations, so no 'fletcher'. Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Romain Dolbeau <[email protected]> Closes #9539
Diffstat (limited to 'include/os')
-rw-r--r--include/os/linux/kernel/linux/Makefile.am1
-rw-r--r--include/os/linux/kernel/linux/simd.h3
-rw-r--r--include/os/linux/kernel/linux/simd_powerpc.h109
3 files changed, 113 insertions, 0 deletions
diff --git a/include/os/linux/kernel/linux/Makefile.am b/include/os/linux/kernel/linux/Makefile.am
index 06ce7c7aa..6b9b2a30c 100644
--- a/include/os/linux/kernel/linux/Makefile.am
+++ b/include/os/linux/kernel/linux/Makefile.am
@@ -10,6 +10,7 @@ KERNEL_H = \
$(top_srcdir)/include/os/linux/kernel/linux/simd.h \
$(top_srcdir)/include/os/linux/kernel/linux/simd_x86.h \
$(top_srcdir)/include/os/linux/kernel/linux/simd_aarch64.h \
+ $(top_srcdir)/include/os/linux/kernel/linux/simd_powerpc.h \
$(top_srcdir)/include/os/linux/kernel/linux/mod_compat.h \
$(top_srcdir)/include/os/linux/kernel/linux/page_compat.h \
$(top_srcdir)/include/os/linux/kernel/linux/compiler_compat.h
diff --git a/include/os/linux/kernel/linux/simd.h b/include/os/linux/kernel/linux/simd.h
index ce317d52e..4cde248e2 100644
--- a/include/os/linux/kernel/linux/simd.h
+++ b/include/os/linux/kernel/linux/simd.h
@@ -30,6 +30,9 @@
#elif defined(__aarch64__)
#include <linux/simd_aarch64.h>
+
+#elif defined(__powerpc__)
+#include <linux/simd_powerpc.h>
#else
#define kfpu_allowed() 0
diff --git a/include/os/linux/kernel/linux/simd_powerpc.h b/include/os/linux/kernel/linux/simd_powerpc.h
new file mode 100644
index 000000000..108cef22f
--- /dev/null
+++ b/include/os/linux/kernel/linux/simd_powerpc.h
@@ -0,0 +1,109 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (C) 2019 Romain Dolbeau
+ */
+
+/*
+ * USER API:
+ *
+ * Kernel fpu methods:
+ * kfpu_allowed()
+ * kfpu_begin()
+ * kfpu_end()
+ * kfpu_init()
+ * kfpu_fini()
+ *
+ * SIMD support:
+ *
+ * Following functions should be called to determine whether CPU feature
+ * is supported. All functions are usable in kernel and user space.
+ * If a SIMD algorithm is using more than one instruction set
+ * all relevant feature test functions should be called.
+ *
+ * Supported features:
+ * zfs_altivec_available()
+ */
+
+#ifndef _LINUX_SIMD_POWERPC_H
+#define _LINUX_SIMD_POWERPC_H
+
+/* only for __powerpc__ */
+#if defined(__powerpc__)
+
+#include <linux/preempt.h>
+#include <linux/export.h>
+#include <linux/sched.h>
+#include <asm/switch_to.h>
+#include <sys/types.h>
+#include <linux/version.h>
+
+#define kfpu_allowed() 1
+#define kfpu_begin() \
+ { \
+ preempt_disable(); \
+ enable_kernel_altivec(); \
+ }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
+#define kfpu_end() \
+ { \
+ disable_kernel_altivec(); \
+ preempt_enable(); \
+ }
+#else
+/* seems that before 4.5 no-one bothered disabling ... */
+#define kfpu_end() preempt_enable()
+#endif
+#define kfpu_init() 0
+#define kfpu_fini() ((void) 0)
+
+/*
+ * Check if AltiVec instruction set is available
+ */
+static inline boolean_t
+zfs_altivec_available(void)
+{
+ boolean_t res;
+ /* suggested by macallan at netbsd dot org */
+#if defined(__powerpc64__)
+ u64 msr;
+#else
+ u32 msr;
+#endif
+ kfpu_begin();
+ __asm volatile("mfmsr %0" : "=r"(msr));
+ /*
+ * 64 bits -> need to check bit 38
+ * Power ISA Version 3.0B
+ * p944
+ * 32 bits -> Need to check bit 6
+ * AltiVec Technology Programming Environments Manual
+ * p49 (2-9)
+ * They are the same, as ppc counts 'backward' ...
+ */
+ res = (msr & 0x2000000) != 0;
+ kfpu_end();
+ return (res);
+}
+#endif /* defined(__powerpc) */
+
+#endif /* _LINUX_SIMD_POWERPC_H */