diff options
author | Romain Dolbeau <[email protected]> | 2020-01-23 20:01:24 +0100 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2020-01-23 11:01:24 -0800 |
commit | 35b07497c60701465a87aab48fc890a0bc502561 (patch) | |
tree | ded14fd0cfd7c3dd985617ae1d576d4e26c165a2 /include | |
parent | 1a69856034304e74b32fb372e89967e91989cafd (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')
-rw-r--r-- | include/os/linux/kernel/linux/Makefile.am | 1 | ||||
-rw-r--r-- | include/os/linux/kernel/linux/simd.h | 3 | ||||
-rw-r--r-- | include/os/linux/kernel/linux/simd_powerpc.h | 109 | ||||
-rw-r--r-- | include/sys/vdev_raidz_impl.h | 5 |
4 files changed, 117 insertions, 1 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 + * <[email protected]> + */ + +/* + * 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 */ diff --git a/include/sys/vdev_raidz_impl.h b/include/sys/vdev_raidz_impl.h index 2e38962cc..81a321ee5 100644 --- a/include/sys/vdev_raidz_impl.h +++ b/include/sys/vdev_raidz_impl.h @@ -90,7 +90,7 @@ typedef boolean_t (*will_work_f)(void); typedef void (*init_impl_f)(void); typedef void (*fini_impl_f)(void); -#define RAIDZ_IMPL_NAME_MAX (16) +#define RAIDZ_IMPL_NAME_MAX (20) typedef struct raidz_impl_ops { init_impl_f init; @@ -152,6 +152,9 @@ extern const raidz_impl_ops_t vdev_raidz_avx512bw_impl; extern const raidz_impl_ops_t vdev_raidz_aarch64_neon_impl; extern const raidz_impl_ops_t vdev_raidz_aarch64_neonx2_impl; #endif +#if defined(__powerpc__) +extern const raidz_impl_ops_t vdev_raidz_powerpc_altivec_impl; +#endif /* * Commonly used raidz_map helpers |