diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2018-06-16 04:52:35 +0200 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2018-06-17 19:36:37 +0200 |
commit | 3f62999e8e27a7f315ef9346f34885d76334575a (patch) | |
tree | 72d1997606568842bb14603238ffe17b4aaadf02 /src/crypto/simd.h | |
parent | 8186537ff6272a5533e4dcf4b1b428d9328bed44 (diff) |
simd: encapsulate fpu amortization into nice functions
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'src/crypto/simd.h')
-rw-r--r-- | src/crypto/simd.h | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/src/crypto/simd.h b/src/crypto/simd.h new file mode 100644 index 0000000..21e3c55 --- /dev/null +++ b/src/crypto/simd.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2015-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. + */ + +#ifndef _WG_SIMD_H +#define _WG_SIMD_H + +#if defined(CONFIG_X86_64) +#include <linux/version.h> +#include <asm/fpu/api.h> +#include <asm/simd.h> +#elif IS_ENABLED(CONFIG_KERNEL_MODE_NEON) +#include <asm/neon.h> +#include <asm/simd.h> +#endif + +static inline bool simd_get(void) +{ + bool have_simd = false; +#if defined(CONFIG_X86_64) && !defined(CONFIG_UML) && !defined(CONFIG_PREEMPT_RT_BASE) + have_simd = irq_fpu_usable(); + if (have_simd) + kernel_fpu_begin(); +#elif IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && !defined(CONFIG_PREEMPT_RT_BASE) +#if defined(CONFIG_ARM64) + have_simd = true; /* ARM64 supports NEON in any context. */ +#elif defined(CONFIG_ARM) + have_simd = may_use_simd(); /* ARM doesn't support NEON in interrupt context. */ +#endif + if (have_simd) + kernel_neon_begin(); +#endif + return have_simd; +} + +static inline void simd_put(bool was_on) +{ +#if defined(CONFIG_X86_64) && !defined(CONFIG_UML) && !defined(CONFIG_PREEMPT_RT_BASE) + if (was_on) + kernel_fpu_end(); +#elif IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && !defined(CONFIG_PREEMPT_RT_BASE) + if (was_on) + kernel_neon_end(); +#endif +} + +static inline bool simd_relax(bool was_on) +{ + if (was_on && need_resched()) { + simd_put(true); + return simd_get(); + } + return was_on; +} + +#endif /* _WG_SIMD_H */ |