1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * SHA-256 accelerated using the sparc64 sha256 opcodes
4  *
5  * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
6  * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
7  * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
8  * SHA224 Support Copyright 2007 Intel Corporation <jonathan.lynch@intel.com>
9  */
10 
11 #define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
12 
13 #include <asm/elf.h>
14 #include <asm/opcodes.h>
15 #include <asm/pstate.h>
16 #include <crypto/internal/sha2.h>
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 
20 static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_sha256_opcodes);
21 
22 asmlinkage void sha256_sparc64_transform(u32 state[SHA256_STATE_WORDS],
23 					 const u8 *data, size_t nblocks);
24 
25 void sha256_blocks_arch(u32 state[SHA256_STATE_WORDS],
26 			const u8 *data, size_t nblocks)
27 {
28 	if (static_branch_likely(&have_sha256_opcodes))
29 		sha256_sparc64_transform(state, data, nblocks);
30 	else
31 		sha256_blocks_generic(state, data, nblocks);
32 }
33 EXPORT_SYMBOL_GPL(sha256_blocks_arch);
34 
35 bool sha256_is_arch_optimized(void)
36 {
37 	return static_key_enabled(&have_sha256_opcodes);
38 }
39 EXPORT_SYMBOL_GPL(sha256_is_arch_optimized);
40 
41 static int __init sha256_sparc64_mod_init(void)
42 {
43 	unsigned long cfr;
44 
45 	if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
46 		return 0;
47 
48 	__asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
49 	if (!(cfr & CFR_SHA256))
50 		return 0;
51 
52 	static_branch_enable(&have_sha256_opcodes);
53 	pr_info("Using sparc64 sha256 opcode optimized SHA-256/SHA-224 implementation\n");
54 	return 0;
55 }
56 subsys_initcall(sha256_sparc64_mod_init);
57 
58 static void __exit sha256_sparc64_mod_exit(void)
59 {
60 }
61 module_exit(sha256_sparc64_mod_exit);
62 
63 MODULE_LICENSE("GPL");
64 MODULE_DESCRIPTION("SHA-256 accelerated using the sparc64 sha256 opcodes");
65