Commit 44a7d444 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6

Pull crypto updates from Herbert Xu:
 "Algorithms:

   - Add AES-NI/AVX/x86_64 implementation of SM4.

  Drivers:

   - Add Arm SMCCC TRNG based driver"

[ And obviously a lot of random fixes and updates  - Linus]

* 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: (84 commits)
  crypto: sha512 - remove imaginary and mystifying clearing of variables
  crypto: aesni - xts_crypt() return if walk.nbytes is 0
  padata: Remove repeated verbose license text
  crypto: ccp - Add support for new CCP/PSP device ID
  crypto: x86/sm4 - add AES-NI/AVX2/x86_64 implementation
  crypto: x86/sm4 - export reusable AESNI/AVX functions
  crypto: rmd320 - remove rmd320 in Makefile
  crypto: skcipher - in_irq() cleanup
  crypto: hisilicon - check _PS0 and _PR0 method
  crypto: hisilicon - change parameter passing of debugfs function
  crypto: hisilicon - support runtime PM for accelerator device
  crypto: hisilicon - add runtime PM ops
  crypto: hisilicon - using 'debugfs_create_file' instead of 'debugfs_create_regset32'
  crypto: tcrypt - add GCM/CCM mode test for SM4 algorithm
  crypto: testmgr - Add GCM/CCM mode test of SM4 algorithm
  crypto: tcrypt - Fix missing return value check
  crypto: hisilicon/sec - modify the hardware endian configuration
  crypto: hisilicon/sec - fix the abnormal exiting process
  crypto: qat - store vf.compatible flag
  crypto: qat - do not export adf_iov_putmsg()
  ...
parents 4ca42564 6ae51ffe
...@@ -112,7 +112,7 @@ static struct kpp_alg curve25519_alg = { ...@@ -112,7 +112,7 @@ static struct kpp_alg curve25519_alg = {
.max_size = curve25519_max_size, .max_size = curve25519_max_size,
}; };
static int __init mod_init(void) static int __init arm_curve25519_init(void)
{ {
if (elf_hwcap & HWCAP_NEON) { if (elf_hwcap & HWCAP_NEON) {
static_branch_enable(&have_neon); static_branch_enable(&have_neon);
...@@ -122,14 +122,14 @@ static int __init mod_init(void) ...@@ -122,14 +122,14 @@ static int __init mod_init(void)
return 0; return 0;
} }
static void __exit mod_exit(void) static void __exit arm_curve25519_exit(void)
{ {
if (IS_REACHABLE(CONFIG_CRYPTO_KPP) && elf_hwcap & HWCAP_NEON) if (IS_REACHABLE(CONFIG_CRYPTO_KPP) && elf_hwcap & HWCAP_NEON)
crypto_unregister_kpp(&curve25519_alg); crypto_unregister_kpp(&curve25519_alg);
} }
module_init(mod_init); module_init(arm_curve25519_init);
module_exit(mod_exit); module_exit(arm_curve25519_exit);
MODULE_ALIAS_CRYPTO("curve25519"); MODULE_ALIAS_CRYPTO("curve25519");
MODULE_ALIAS_CRYPTO("curve25519-neon"); MODULE_ALIAS_CRYPTO("curve25519-neon");
......
...@@ -51,7 +51,7 @@ config CRYPTO_SM4_ARM64_CE ...@@ -51,7 +51,7 @@ config CRYPTO_SM4_ARM64_CE
tristate "SM4 symmetric cipher (ARMv8.2 Crypto Extensions)" tristate "SM4 symmetric cipher (ARMv8.2 Crypto Extensions)"
depends on KERNEL_MODE_NEON depends on KERNEL_MODE_NEON
select CRYPTO_ALGAPI select CRYPTO_ALGAPI
select CRYPTO_SM4 select CRYPTO_LIB_SM4
config CRYPTO_GHASH_ARM64_CE config CRYPTO_GHASH_ARM64_CE
tristate "GHASH/AES-GCM using ARMv8 Crypto Extensions" tristate "GHASH/AES-GCM using ARMv8 Crypto Extensions"
......
...@@ -17,12 +17,20 @@ MODULE_LICENSE("GPL v2"); ...@@ -17,12 +17,20 @@ MODULE_LICENSE("GPL v2");
asmlinkage void sm4_ce_do_crypt(const u32 *rk, void *out, const void *in); asmlinkage void sm4_ce_do_crypt(const u32 *rk, void *out, const void *in);
static int sm4_ce_setkey(struct crypto_tfm *tfm, const u8 *key,
unsigned int key_len)
{
struct sm4_ctx *ctx = crypto_tfm_ctx(tfm);
return sm4_expandkey(ctx, key, key_len);
}
static void sm4_ce_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) static void sm4_ce_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
{ {
const struct crypto_sm4_ctx *ctx = crypto_tfm_ctx(tfm); const struct sm4_ctx *ctx = crypto_tfm_ctx(tfm);
if (!crypto_simd_usable()) { if (!crypto_simd_usable()) {
crypto_sm4_encrypt(tfm, out, in); sm4_crypt_block(ctx->rkey_enc, out, in);
} else { } else {
kernel_neon_begin(); kernel_neon_begin();
sm4_ce_do_crypt(ctx->rkey_enc, out, in); sm4_ce_do_crypt(ctx->rkey_enc, out, in);
...@@ -32,10 +40,10 @@ static void sm4_ce_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) ...@@ -32,10 +40,10 @@ static void sm4_ce_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
static void sm4_ce_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) static void sm4_ce_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
{ {
const struct crypto_sm4_ctx *ctx = crypto_tfm_ctx(tfm); const struct sm4_ctx *ctx = crypto_tfm_ctx(tfm);
if (!crypto_simd_usable()) { if (!crypto_simd_usable()) {
crypto_sm4_decrypt(tfm, out, in); sm4_crypt_block(ctx->rkey_dec, out, in);
} else { } else {
kernel_neon_begin(); kernel_neon_begin();
sm4_ce_do_crypt(ctx->rkey_dec, out, in); sm4_ce_do_crypt(ctx->rkey_dec, out, in);
...@@ -49,12 +57,12 @@ static struct crypto_alg sm4_ce_alg = { ...@@ -49,12 +57,12 @@ static struct crypto_alg sm4_ce_alg = {
.cra_priority = 200, .cra_priority = 200,
.cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = SM4_BLOCK_SIZE, .cra_blocksize = SM4_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct crypto_sm4_ctx), .cra_ctxsize = sizeof(struct sm4_ctx),
.cra_module = THIS_MODULE, .cra_module = THIS_MODULE,
.cra_u.cipher = { .cra_u.cipher = {
.cia_min_keysize = SM4_KEY_SIZE, .cia_min_keysize = SM4_KEY_SIZE,
.cia_max_keysize = SM4_KEY_SIZE, .cia_max_keysize = SM4_KEY_SIZE,
.cia_setkey = crypto_sm4_set_key, .cia_setkey = sm4_ce_setkey,
.cia_encrypt = sm4_ce_encrypt, .cia_encrypt = sm4_ce_encrypt,
.cia_decrypt = sm4_ce_decrypt .cia_decrypt = sm4_ce_decrypt
} }
......
...@@ -88,6 +88,12 @@ nhpoly1305-avx2-y := nh-avx2-x86_64.o nhpoly1305-avx2-glue.o ...@@ -88,6 +88,12 @@ nhpoly1305-avx2-y := nh-avx2-x86_64.o nhpoly1305-avx2-glue.o
obj-$(CONFIG_CRYPTO_CURVE25519_X86) += curve25519-x86_64.o obj-$(CONFIG_CRYPTO_CURVE25519_X86) += curve25519-x86_64.o
obj-$(CONFIG_CRYPTO_SM4_AESNI_AVX_X86_64) += sm4-aesni-avx-x86_64.o
sm4-aesni-avx-x86_64-y := sm4-aesni-avx-asm_64.o sm4_aesni_avx_glue.o
obj-$(CONFIG_CRYPTO_SM4_AESNI_AVX2_X86_64) += sm4-aesni-avx2-x86_64.o
sm4-aesni-avx2-x86_64-y := sm4-aesni-avx2-asm_64.o sm4_aesni_avx2_glue.o
quiet_cmd_perlasm = PERLASM $@ quiet_cmd_perlasm = PERLASM $@
cmd_perlasm = $(PERL) $< > $@ cmd_perlasm = $(PERL) $< > $@
$(obj)/%.S: $(src)/%.pl FORCE $(obj)/%.S: $(src)/%.pl FORCE
......
...@@ -849,6 +849,8 @@ static int xts_crypt(struct skcipher_request *req, bool encrypt) ...@@ -849,6 +849,8 @@ static int xts_crypt(struct skcipher_request *req, bool encrypt)
return -EINVAL; return -EINVAL;
err = skcipher_walk_virt(&walk, req, false); err = skcipher_walk_virt(&walk, req, false);
if (!walk.nbytes)
return err;
if (unlikely(tail > 0 && walk.nbytes < walk.total)) { if (unlikely(tail > 0 && walk.nbytes < walk.total)) {
int blocks = DIV_ROUND_UP(req->cryptlen, AES_BLOCK_SIZE) - 2; int blocks = DIV_ROUND_UP(req->cryptlen, AES_BLOCK_SIZE) - 2;
...@@ -862,7 +864,10 @@ static int xts_crypt(struct skcipher_request *req, bool encrypt) ...@@ -862,7 +864,10 @@ static int xts_crypt(struct skcipher_request *req, bool encrypt)
skcipher_request_set_crypt(&subreq, req->src, req->dst, skcipher_request_set_crypt(&subreq, req->src, req->dst,
blocks * AES_BLOCK_SIZE, req->iv); blocks * AES_BLOCK_SIZE, req->iv);
req = &subreq; req = &subreq;
err = skcipher_walk_virt(&walk, req, false); err = skcipher_walk_virt(&walk, req, false);
if (err)
return err;
} else { } else {
tail = 0; tail = 0;
} }
......
This diff is collapsed.
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifndef ASM_X86_SM4_AVX_H
#define ASM_X86_SM4_AVX_H
#include <linux/types.h>
#include <crypto/sm4.h>
typedef void (*sm4_crypt_func)(const u32 *rk, u8 *dst, const u8 *src, u8 *iv);
int sm4_avx_ecb_encrypt(struct skcipher_request *req);
int sm4_avx_ecb_decrypt(struct skcipher_request *req);
int sm4_cbc_encrypt(struct skcipher_request *req);
int sm4_avx_cbc_decrypt(struct skcipher_request *req,
unsigned int bsize, sm4_crypt_func func);
int sm4_cfb_encrypt(struct skcipher_request *req);
int sm4_avx_cfb_decrypt(struct skcipher_request *req,
unsigned int bsize, sm4_crypt_func func);
int sm4_avx_ctr_crypt(struct skcipher_request *req,
unsigned int bsize, sm4_crypt_func func);
#endif
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* SM4 Cipher Algorithm, AES-NI/AVX2 optimized.
* as specified in
* https://tools.ietf.org/id/draft-ribose-cfrg-sm4-10.html
*
* Copyright (c) 2021, Alibaba Group.
* Copyright (c) 2021 Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
*/
#include <linux/module.h>
#include <linux/crypto.h>
#include <linux/kernel.h>
#include <asm/simd.h>
#include <crypto/internal/simd.h>
#include <crypto/internal/skcipher.h>
#include <crypto/sm4.h>
#include "sm4-avx.h"
#define SM4_CRYPT16_BLOCK_SIZE (SM4_BLOCK_SIZE * 16)
asmlinkage void sm4_aesni_avx2_ctr_enc_blk16(const u32 *rk, u8 *dst,
const u8 *src, u8 *iv);
asmlinkage void sm4_aesni_avx2_cbc_dec_blk16(const u32 *rk, u8 *dst,
const u8 *src, u8 *iv);
asmlinkage void sm4_aesni_avx2_cfb_dec_blk16(const u32 *rk, u8 *dst,
const u8 *src, u8 *iv);
static int sm4_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key,
unsigned int key_len)
{
struct sm4_ctx *ctx = crypto_skcipher_ctx(tfm);
return sm4_expandkey(ctx, key, key_len);
}
static int cbc_decrypt(struct skcipher_request *req)
{
return sm4_avx_cbc_decrypt(req, SM4_CRYPT16_BLOCK_SIZE,
sm4_aesni_avx2_cbc_dec_blk16);
}
static int cfb_decrypt(struct skcipher_request *req)
{
return sm4_avx_cfb_decrypt(req, SM4_CRYPT16_BLOCK_SIZE,
sm4_aesni_avx2_cfb_dec_blk16);
}
static int ctr_crypt(struct skcipher_request *req)
{
return sm4_avx_ctr_crypt(req, SM4_CRYPT16_BLOCK_SIZE,
sm4_aesni_avx2_ctr_enc_blk16);
}
static struct skcipher_alg sm4_aesni_avx2_skciphers[] = {
{
.base = {
.cra_name = "__ecb(sm4)",
.cra_driver_name = "__ecb-sm4-aesni-avx2",
.cra_priority = 500,
.cra_flags = CRYPTO_ALG_INTERNAL,
.cra_blocksize = SM4_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct sm4_ctx),
.cra_module = THIS_MODULE,
},
.min_keysize = SM4_KEY_SIZE,
.max_keysize = SM4_KEY_SIZE,
.walksize = 16 * SM4_BLOCK_SIZE,
.setkey = sm4_skcipher_setkey,
.encrypt = sm4_avx_ecb_encrypt,
.decrypt = sm4_avx_ecb_decrypt,
}, {
.base = {
.cra_name = "__cbc(sm4)",
.cra_driver_name = "__cbc-sm4-aesni-avx2",
.cra_priority = 500,
.cra_flags = CRYPTO_ALG_INTERNAL,
.cra_blocksize = SM4_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct sm4_ctx),
.cra_module = THIS_MODULE,
},
.min_keysize = SM4_KEY_SIZE,
.max_keysize = SM4_KEY_SIZE,
.ivsize = SM4_BLOCK_SIZE,
.walksize = 16 * SM4_BLOCK_SIZE,
.setkey = sm4_skcipher_setkey,
.encrypt = sm4_cbc_encrypt,
.decrypt = cbc_decrypt,
}, {
.base = {
.cra_name = "__cfb(sm4)",
.cra_driver_name = "__cfb-sm4-aesni-avx2",
.cra_priority = 500,
.cra_flags = CRYPTO_ALG_INTERNAL,
.cra_blocksize = 1,
.cra_ctxsize = sizeof(struct sm4_ctx),
.cra_module = THIS_MODULE,
},
.min_keysize = SM4_KEY_SIZE,
.max_keysize = SM4_KEY_SIZE,
.ivsize = SM4_BLOCK_SIZE,
.chunksize = SM4_BLOCK_SIZE,
.walksize = 16 * SM4_BLOCK_SIZE,
.setkey = sm4_skcipher_setkey,
.encrypt = sm4_cfb_encrypt,
.decrypt = cfb_decrypt,
}, {
.base = {
.cra_name = "__ctr(sm4)",
.cra_driver_name = "__ctr-sm4-aesni-avx2",
.cra_priority = 500,
.cra_flags = CRYPTO_ALG_INTERNAL,
.cra_blocksize = 1,
.cra_ctxsize = sizeof(struct sm4_ctx),
.cra_module = THIS_MODULE,
},
.min_keysize = SM4_KEY_SIZE,
.max_keysize = SM4_KEY_SIZE,
.ivsize = SM4_BLOCK_SIZE,
.chunksize = SM4_BLOCK_SIZE,
.walksize = 16 * SM4_BLOCK_SIZE,
.setkey = sm4_skcipher_setkey,
.encrypt = ctr_crypt,
.decrypt = ctr_crypt,
}
};
static struct simd_skcipher_alg *
simd_sm4_aesni_avx2_skciphers[ARRAY_SIZE(sm4_aesni_avx2_skciphers)];
static int __init sm4_init(void)
{
const char *feature_name;
if (!boot_cpu_has(X86_FEATURE_AVX) ||
!boot_cpu_has(X86_FEATURE_AVX2) ||
!boot_cpu_has(X86_FEATURE_AES) ||
!boot_cpu_has(X86_FEATURE_OSXSAVE)) {
pr_info("AVX2 or AES-NI instructions are not detected.\n");
return -ENODEV;
}
if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM,
&feature_name)) {
pr_info("CPU feature '%s' is not supported.\n", feature_name);
return -ENODEV;
}
return simd_register_skciphers_compat(sm4_aesni_avx2_skciphers,
ARRAY_SIZE(sm4_aesni_avx2_skciphers),
simd_sm4_aesni_avx2_skciphers);
}
static void __exit sm4_exit(void)
{
simd_unregister_skciphers(sm4_aesni_avx2_skciphers,
ARRAY_SIZE(sm4_aesni_avx2_skciphers),
simd_sm4_aesni_avx2_skciphers);
}
module_init(sm4_init);
module_exit(sm4_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Tianjia Zhang <tianjia.zhang@linux.alibaba.com>");
MODULE_DESCRIPTION("SM4 Cipher Algorithm, AES-NI/AVX2 optimized");
MODULE_ALIAS_CRYPTO("sm4");
MODULE_ALIAS_CRYPTO("sm4-aesni-avx2");
This diff is collapsed.
...@@ -1547,6 +1547,7 @@ config CRYPTO_SERPENT_AVX2_X86_64 ...@@ -1547,6 +1547,7 @@ config CRYPTO_SERPENT_AVX2_X86_64
config CRYPTO_SM4 config CRYPTO_SM4
tristate "SM4 cipher algorithm" tristate "SM4 cipher algorithm"
select CRYPTO_ALGAPI select CRYPTO_ALGAPI
select CRYPTO_LIB_SM4
help help
SM4 cipher algorithms (OSCCA GB/T 32907-2016). SM4 cipher algorithms (OSCCA GB/T 32907-2016).
...@@ -1569,6 +1570,49 @@ config CRYPTO_SM4 ...@@ -1569,6 +1570,49 @@ config CRYPTO_SM4
If unsure, say N. If unsure, say N.
config CRYPTO_SM4_AESNI_AVX_X86_64
tristate "SM4 cipher algorithm (x86_64/AES-NI/AVX)"
depends on X86 && 64BIT
select CRYPTO_SKCIPHER
select CRYPTO_SIMD
select CRYPTO_ALGAPI
select CRYPTO_LIB_SM4
help
SM4 cipher algorithms (OSCCA GB/T 32907-2016) (x86_64/AES-NI/AVX).
SM4 (GBT.32907-2016) is a cryptographic standard issued by the
Organization of State Commercial Administration of China (OSCCA)
as an authorized cryptographic algorithms for the use within China.
This is SM4 optimized implementation using AES-NI/AVX/x86_64
instruction set for block cipher. Through two affine transforms,
we can use the AES S-Box to simulate the SM4 S-Box to achieve the
effect of instruction acceleration.
If unsure, say N.
config CRYPTO_SM4_AESNI_AVX2_X86_64
tristate "SM4 cipher algorithm (x86_64/AES-NI/AVX2)"
depends on X86 && 64BIT
select CRYPTO_SKCIPHER
select CRYPTO_SIMD
select CRYPTO_ALGAPI
select CRYPTO_LIB_SM4
select CRYPTO_SM4_AESNI_AVX_X86_64
help
SM4 cipher algorithms (OSCCA GB/T 32907-2016) (x86_64/AES-NI/AVX2).
SM4 (GBT.32907-2016) is a cryptographic standard issued by the
Organization of State Commercial Administration of China (OSCCA)
as an authorized cryptographic algorithms for the use within China.
This is SM4 optimized implementation using AES-NI/AVX2/x86_64
instruction set for block cipher. Through two affine transforms,
we can use the AES S-Box to simulate the SM4 S-Box to achieve the
effect of instruction acceleration.
If unsure, say N.
config CRYPTO_TEA config CRYPTO_TEA
tristate "TEA, XTEA and XETA cipher algorithms" tristate "TEA, XTEA and XETA cipher algorithms"
depends on CRYPTO_USER_API_ENABLE_OBSOLETE depends on CRYPTO_USER_API_ENABLE_OBSOLETE
......
...@@ -74,7 +74,6 @@ obj-$(CONFIG_CRYPTO_NULL2) += crypto_null.o ...@@ -74,7 +74,6 @@ obj-$(CONFIG_CRYPTO_NULL2) += crypto_null.o
obj-$(CONFIG_CRYPTO_MD4) += md4.o obj-$(CONFIG_CRYPTO_MD4) += md4.o
obj-$(CONFIG_CRYPTO_MD5) += md5.o obj-$(CONFIG_CRYPTO_MD5) += md5.o
obj-$(CONFIG_CRYPTO_RMD160) += rmd160.o obj-$(CONFIG_CRYPTO_RMD160) += rmd160.o
obj-$(CONFIG_CRYPTO_RMD320) += rmd320.o
obj-$(CONFIG_CRYPTO_SHA1) += sha1_generic.o obj-$(CONFIG_CRYPTO_SHA1) += sha1_generic.o
obj-$(CONFIG_CRYPTO_SHA256) += sha256_generic.o obj-$(CONFIG_CRYPTO_SHA256) += sha256_generic.o
obj-$(CONFIG_CRYPTO_SHA512) += sha512_generic.o obj-$(CONFIG_CRYPTO_SHA512) += sha512_generic.o
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#define _CRYPTO_ECC_H #define _CRYPTO_ECC_H
#include <crypto/ecc_curve.h> #include <crypto/ecc_curve.h>
#include <asm/unaligned.h>
/* One digit is u64 qword. */ /* One digit is u64 qword. */
#define ECC_CURVE_NIST_P192_DIGITS 3 #define ECC_CURVE_NIST_P192_DIGITS 3
...@@ -46,13 +47,13 @@ ...@@ -46,13 +47,13 @@
* @out: Output array * @out: Output array
* @ndigits: Number of digits to copy * @ndigits: Number of digits to copy
*/ */
static inline void ecc_swap_digits(const u64 *in, u64 *out, unsigned int ndigits) static inline void ecc_swap_digits(const void *in, u64 *out, unsigned int ndigits)
{ {
const __be64 *src = (__force __be64 *)in; const __be64 *src = (__force __be64 *)in;
int i; int i;
for (i = 0; i < ndigits; i++) for (i = 0; i < ndigits; i++)
out[i] = be64_to_cpu(src[ndigits - 1 - i]); out[i] = get_unaligned_be64(&src[ndigits - 1 - i]);
} }
/** /**
......
...@@ -143,9 +143,6 @@ sha512_transform(u64 *state, const u8 *input) ...@@ -143,9 +143,6 @@ sha512_transform(u64 *state, const u8 *input)
state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[0] += a; state[1] += b; state[2] += c; state[3] += d;
state[4] += e; state[5] += f; state[6] += g; state[7] += h; state[4] += e; state[5] += f; state[6] += g; state[7] += h;
/* erase our data */
a = b = c = d = e = f = g = h = t1 = t2 = 0;
} }
static void sha512_generic_block_fn(struct sha512_state *sst, u8 const *src, static void sha512_generic_block_fn(struct sha512_state *sst, u8 const *src,
......
...@@ -431,7 +431,7 @@ static int skcipher_copy_iv(struct skcipher_walk *walk) ...@@ -431,7 +431,7 @@ static int skcipher_copy_iv(struct skcipher_walk *walk)
static int skcipher_walk_first(struct skcipher_walk *walk) static int skcipher_walk_first(struct skcipher_walk *walk)
{ {
if (WARN_ON_ONCE(in_irq())) if (WARN_ON_ONCE(in_hardirq()))
return -EDEADLK; return -EDEADLK;
walk->buffer = NULL; walk->buffer = NULL;
......
...@@ -16,191 +16,43 @@ ...@@ -16,191 +16,43 @@
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
static const u32 fk[4] = {
0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc
};
static const u8 sbox[256] = {
0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7,
0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3,
0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a,
0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,
0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95,
0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,
0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba,
0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,
0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b,
0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,
0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2,
0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,
0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52,
0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,
0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5,
0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,
0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55,
0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,
0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60,
0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,
0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f,
0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,
0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f,
0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,
0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd,
0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,
0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e,
0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,
0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20,
0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48
};
static const u32 ck[] = {
0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279
};
static u32 sm4_t_non_lin_sub(u32 x)
{
int i;
u8 *b = (u8 *)&x;
for (i = 0; i < 4; ++i)
b[i] = sbox[b[i]];
return x;
}
static u32 sm4_key_lin_sub(u32 x)
{
return x ^ rol32(x, 13) ^ rol32(x, 23);
}
static u32 sm4_enc_lin_sub(u32 x)
{
return x ^ rol32(x, 2) ^ rol32(x, 10) ^ rol32(x, 18) ^ rol32(x, 24);
}
static u32 sm4_key_sub(u32 x)
{
return sm4_key_lin_sub(sm4_t_non_lin_sub(x));
}
static u32 sm4_enc_sub(u32 x)
{
return sm4_enc_lin_sub(sm4_t_non_lin_sub(x));
}
static u32 sm4_round(const u32 *x, const u32 rk)
{
return x[0] ^ sm4_enc_sub(x[1] ^ x[2] ^ x[3] ^ rk);
}
/** /**
* crypto_sm4_expand_key - Expands the SM4 key as described in GB/T 32907-2016 * sm4_setkey - Set the SM4 key.
* @ctx: The location where the computed key will be stored.
* @in_key: The supplied key.
* @key_len: The length of the supplied key.
*
* Returns 0 on success. The function fails only if an invalid key size (or
* pointer) is supplied.
*/
int crypto_sm4_expand_key(struct crypto_sm4_ctx *ctx, const u8 *in_key,
unsigned int key_len)
{
u32 rk[4], t;
const u32 *key = (u32 *)in_key;
int i;
if (key_len != SM4_KEY_SIZE)
return -EINVAL;
for (i = 0; i < 4; ++i)
rk[i] = get_unaligned_be32(&key[i]) ^ fk[i];
for (i = 0; i < 32; ++i) {
t = rk[0] ^ sm4_key_sub(rk[1] ^ rk[2] ^ rk[3] ^ ck[i]);
ctx->rkey_enc[i] = t;
rk[0] = rk[1];
rk[1] = rk[2];
rk[2] = rk[3];
rk[3] = t;
}
for (i = 0; i < 32; ++i)
ctx->rkey_dec[i] = ctx->rkey_enc[31 - i];
return 0;
}
EXPORT_SYMBOL_GPL(crypto_sm4_expand_key);
/**
* crypto_sm4_set_key - Set the SM4 key.
* @tfm: The %crypto_tfm that is used in the context. * @tfm: The %crypto_tfm that is used in the context.
* @in_key: The input key. * @in_key: The input key.
* @key_len: The size of the key. * @key_len: The size of the key.
* *
* This function uses crypto_sm4_expand_key() to expand the key. * This function uses sm4_expandkey() to expand the key.
* &crypto_sm4_ctx _must_ be the private data embedded in @tfm which is * &sm4_ctx _must_ be the private data embedded in @tfm which is
* retrieved with crypto_tfm_ctx(). * retrieved with crypto_tfm_ctx().
* *
* Return: 0 on success; -EINVAL on failure (only happens for bad key lengths) * Return: 0 on success; -EINVAL on failure (only happens for bad key lengths)
*/ */
int crypto_sm4_set_key(struct crypto_tfm *tfm, const u8 *in_key, static int sm4_setkey(struct crypto_tfm *tfm, const u8 *in_key,
unsigned int key_len) unsigned int key_len)
{ {
struct crypto_sm4_ctx *ctx = crypto_tfm_ctx(tfm); struct sm4_ctx *ctx = crypto_tfm_ctx(tfm);
return crypto_sm4_expand_key(ctx, in_key, key_len);
}
EXPORT_SYMBOL_GPL(crypto_sm4_set_key);
static void sm4_do_crypt(const u32 *rk, u32 *out, const u32 *in)
{
u32 x[4], i, t;
for (i = 0; i < 4; ++i)
x[i] = get_unaligned_be32(&in[i]);
for (i = 0; i < 32; ++i) {
t = sm4_round(x, rk[i]);
x[0] = x[1];
x[1] = x[2];
x[2] = x[3];
x[3] = t;
}
for (i = 0; i < 4; ++i) return sm4_expandkey(ctx, in_key, key_len);
put_unaligned_be32(x[3 - i], &out[i]);
} }
/* encrypt a block of text */ /* encrypt a block of text */
void crypto_sm4_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) static void sm4_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
{ {
const struct crypto_sm4_ctx *ctx = crypto_tfm_ctx(tfm); const struct sm4_ctx *ctx = crypto_tfm_ctx(tfm);
sm4_do_crypt(ctx->rkey_enc, (u32 *)out, (u32 *)in); sm4_crypt_block(ctx->rkey_enc, out, in);
} }
EXPORT_SYMBOL_GPL(crypto_sm4_encrypt);
/* decrypt a block of text */ /* decrypt a block of text */
void crypto_sm4_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) static void sm4_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
{ {
const struct crypto_sm4_ctx *ctx = crypto_tfm_ctx(tfm); const struct sm4_ctx *ctx = crypto_tfm_ctx(tfm);
sm4_do_crypt(ctx->rkey_dec, (u32 *)out, (u32 *)in); sm4_crypt_block(ctx->rkey_dec, out, in);
} }
EXPORT_SYMBOL_GPL(crypto_sm4_decrypt);
static struct crypto_alg sm4_alg = { static struct crypto_alg sm4_alg = {
.cra_name = "sm4", .cra_name = "sm4",
...@@ -208,15 +60,15 @@ static struct crypto_alg sm4_alg = { ...@@ -208,15 +60,15 @@ static struct crypto_alg sm4_alg = {
.cra_priority = 100, .cra_priority = 100,
.cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = SM4_BLOCK_SIZE, .cra_blocksize = SM4_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct crypto_sm4_ctx), .cra_ctxsize = sizeof(struct sm4_ctx),
.cra_module = THIS_MODULE, .cra_module = THIS_MODULE,
.cra_u = { .cra_u = {
.cipher = { .cipher = {
.cia_min_keysize = SM4_KEY_SIZE, .cia_min_keysize = SM4_KEY_SIZE,
.cia_max_keysize = SM4_KEY_SIZE, .cia_max_keysize = SM4_KEY_SIZE,
.cia_setkey = crypto_sm4_set_key, .cia_setkey = sm4_setkey,
.cia_encrypt = crypto_sm4_encrypt, .cia_encrypt = sm4_encrypt,
.cia_decrypt = crypto_sm4_decrypt .cia_decrypt = sm4_decrypt
} }
} }
}; };
......
...@@ -77,7 +77,7 @@ static const char *check[] = { ...@@ -77,7 +77,7 @@ static const char *check[] = {
NULL NULL
}; };
static const int block_sizes[] = { 16, 64, 256, 1024, 1420, 4096, 0 }; static const int block_sizes[] = { 16, 64, 128, 256, 1024, 1420, 4096, 0 };
static const int aead_sizes[] = { 16, 64, 256, 512, 1024, 1420, 4096, 8192, 0 }; static const int aead_sizes[] = { 16, 64, 256, 512, 1024, 1420, 4096, 8192, 0 };
#define XBUFSIZE 8 #define XBUFSIZE 8
...@@ -290,6 +290,11 @@ static void test_mb_aead_speed(const char *algo, int enc, int secs, ...@@ -290,6 +290,11 @@ static void test_mb_aead_speed(const char *algo, int enc, int secs,
} }
ret = crypto_aead_setauthsize(tfm, authsize); ret = crypto_aead_setauthsize(tfm, authsize);
if (ret) {
pr_err("alg: aead: Failed to setauthsize for %s: %d\n", algo,
ret);
goto out_free_tfm;
}
for (i = 0; i < num_mb; ++i) for (i = 0; i < num_mb; ++i)
if (testmgr_alloc_buf(data[i].xbuf)) { if (testmgr_alloc_buf(data[i].xbuf)) {
...@@ -315,7 +320,7 @@ static void test_mb_aead_speed(const char *algo, int enc, int secs, ...@@ -315,7 +320,7 @@ static void test_mb_aead_speed(const char *algo, int enc, int secs,
for (i = 0; i < num_mb; ++i) { for (i = 0; i < num_mb; ++i) {
data[i].req = aead_request_alloc(tfm, GFP_KERNEL); data[i].req = aead_request_alloc(tfm, GFP_KERNEL);
if (!data[i].req) { if (!data[i].req) {
pr_err("alg: skcipher: Failed to allocate request for %s\n", pr_err("alg: aead: Failed to allocate request for %s\n",
algo); algo);
while (i--) while (i--)
aead_request_free(data[i].req); aead_request_free(data[i].req);
...@@ -567,13 +572,19 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs, ...@@ -567,13 +572,19 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs,
sgout = &sg[9]; sgout = &sg[9];
tfm = crypto_alloc_aead(algo, 0, 0); tfm = crypto_alloc_aead(algo, 0, 0);
if (IS_ERR(tfm)) { if (IS_ERR(tfm)) {
pr_err("alg: aead: Failed to load transform for %s: %ld\n", algo, pr_err("alg: aead: Failed to load transform for %s: %ld\n", algo,
PTR_ERR(tfm)); PTR_ERR(tfm));
goto out_notfm; goto out_notfm;
} }
ret = crypto_aead_setauthsize(tfm, authsize);
if (ret) {
pr_err("alg: aead: Failed to setauthsize for %s: %d\n", algo,
ret);
goto out_noreq;
}
crypto_init_wait(&wait); crypto_init_wait(&wait);
printk(KERN_INFO "\ntesting speed of %s (%s) %s\n", algo, printk(KERN_INFO "\ntesting speed of %s (%s) %s\n", algo,
get_driver_name(crypto_aead, tfm), e); get_driver_name(crypto_aead, tfm), e);
...@@ -611,8 +622,13 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs, ...@@ -611,8 +622,13 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs,
break; break;
} }
} }
ret = crypto_aead_setkey(tfm, key, *keysize); ret = crypto_aead_setkey(tfm, key, *keysize);
ret = crypto_aead_setauthsize(tfm, authsize); if (ret) {
pr_err("setkey() failed flags=%x: %d\n",
crypto_aead_get_flags(tfm), ret);
goto out;
}
iv_len = crypto_aead_ivsize(tfm); iv_len = crypto_aead_ivsize(tfm);
if (iv_len) if (iv_len)
...@@ -622,15 +638,8 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs, ...@@ -622,15 +638,8 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs,
printk(KERN_INFO "test %u (%d bit key, %d byte blocks): ", printk(KERN_INFO "test %u (%d bit key, %d byte blocks): ",
i, *keysize * 8, bs); i, *keysize * 8, bs);
memset(tvmem[0], 0xff, PAGE_SIZE); memset(tvmem[0], 0xff, PAGE_SIZE);
if (ret) {
pr_err("setkey() failed flags=%x\n",
crypto_aead_get_flags(tfm));
goto out;
}
sg_init_aead(sg, xbuf, bs + (enc ? 0 : authsize), sg_init_aead(sg, xbuf, bs + (enc ? 0 : authsize),
assoc, aad_size); assoc, aad_size);
...@@ -1907,6 +1916,14 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb) ...@@ -1907,6 +1916,14 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb)
ret += tcrypt_test("streebog512"); ret += tcrypt_test("streebog512");
break; break;
case 55:
ret += tcrypt_test("gcm(sm4)");
break;
case 56:
ret += tcrypt_test("ccm(sm4)");
break;
case 100: case 100:
ret += tcrypt_test("hmac(md5)"); ret += tcrypt_test("hmac(md5)");
break; break;
...@@ -1998,6 +2015,15 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb) ...@@ -1998,6 +2015,15 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb)
case 157: case 157:
ret += tcrypt_test("authenc(hmac(sha1),ecb(cipher_null))"); ret += tcrypt_test("authenc(hmac(sha1),ecb(cipher_null))");
break; break;
case 158:
ret += tcrypt_test("cbcmac(sm4)");
break;
case 159:
ret += tcrypt_test("cmac(sm4)");
break;
case 181: case 181:
ret += tcrypt_test("authenc(hmac(sha1),cbc(des))"); ret += tcrypt_test("authenc(hmac(sha1),cbc(des))");
break; break;
...@@ -2031,6 +2057,7 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb) ...@@ -2031,6 +2057,7 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb)
case 191: case 191:
ret += tcrypt_test("ecb(sm4)"); ret += tcrypt_test("ecb(sm4)");
ret += tcrypt_test("cbc(sm4)"); ret += tcrypt_test("cbc(sm4)");
ret += tcrypt_test("cfb(sm4)");
ret += tcrypt_test("ctr(sm4)"); ret += tcrypt_test("ctr(sm4)");
break; break;
case 200: case 200:
...@@ -2289,6 +2316,10 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb) ...@@ -2289,6 +2316,10 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb)
speed_template_16); speed_template_16);
test_cipher_speed("cbc(sm4)", DECRYPT, sec, NULL, 0, test_cipher_speed("cbc(sm4)", DECRYPT, sec, NULL, 0,
speed_template_16); speed_template_16);
test_cipher_speed("cfb(sm4)", ENCRYPT, sec, NULL, 0,
speed_template_16);
test_cipher_speed("cfb(sm4)", DECRYPT, sec, NULL, 0,
speed_template_16);
test_cipher_speed("ctr(sm4)", ENCRYPT, sec, NULL, 0, test_cipher_speed("ctr(sm4)", ENCRYPT, sec, NULL, 0,
speed_template_16); speed_template_16);
test_cipher_speed("ctr(sm4)", DECRYPT, sec, NULL, 0, test_cipher_speed("ctr(sm4)", DECRYPT, sec, NULL, 0,
...@@ -2322,6 +2353,34 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb) ...@@ -2322,6 +2353,34 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb)
NULL, 0, 16, 8, speed_template_16); NULL, 0, 16, 8, speed_template_16);
break; break;
case 222:
test_aead_speed("gcm(sm4)", ENCRYPT, sec,
NULL, 0, 16, 8, speed_template_16);
test_aead_speed("gcm(sm4)", DECRYPT, sec,
NULL, 0, 16, 8, speed_template_16);
break;
case 223:
test_aead_speed("rfc4309(ccm(sm4))", ENCRYPT, sec,
NULL, 0, 16, 16, aead_speed_template_19);
test_aead_speed("rfc4309(ccm(sm4))", DECRYPT, sec,
NULL, 0, 16, 16, aead_speed_template_19);
break;
case 224:
test_mb_aead_speed("gcm(sm4)", ENCRYPT, sec, NULL, 0, 16, 8,
speed_template_16, num_mb);
test_mb_aead_speed("gcm(sm4)", DECRYPT, sec, NULL, 0, 16, 8,
speed_template_16, num_mb);
break;
case 225:
test_mb_aead_speed("rfc4309(ccm(sm4))", ENCRYPT, sec, NULL, 0,
16, 16, aead_speed_template_19, num_mb);
test_mb_aead_speed("rfc4309(ccm(sm4))", DECRYPT, sec, NULL, 0,
16, 16, aead_speed_template_19, num_mb);
break;
case 300: case 300:
if (alg) { if (alg) {
test_hash_speed(alg, sec, generic_hash_speed_template); test_hash_speed(alg, sec, generic_hash_speed_template);
...@@ -2757,6 +2816,25 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb) ...@@ -2757,6 +2816,25 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb)
speed_template_8_32); speed_template_8_32);
break; break;
case 518:
test_acipher_speed("ecb(sm4)", ENCRYPT, sec, NULL, 0,
speed_template_16);
test_acipher_speed("ecb(sm4)", DECRYPT, sec, NULL, 0,
speed_template_16);
test_acipher_speed("cbc(sm4)", ENCRYPT, sec, NULL, 0,
speed_template_16);
test_acipher_speed("cbc(sm4)", DECRYPT, sec, NULL, 0,
speed_template_16);
test_acipher_speed("cfb(sm4)", ENCRYPT, sec, NULL, 0,
speed_template_16);
test_acipher_speed("cfb(sm4)", DECRYPT, sec, NULL, 0,
speed_template_16);
test_acipher_speed("ctr(sm4)", ENCRYPT, sec, NULL, 0,
speed_template_16);
test_acipher_speed("ctr(sm4)", DECRYPT, sec, NULL, 0,
speed_template_16);
break;
case 600: case 600:
test_mb_skcipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0, test_mb_skcipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0,
speed_template_16_24_32, num_mb); speed_template_16_24_32, num_mb);
......
...@@ -4450,6 +4450,12 @@ static const struct alg_test_desc alg_test_descs[] = { ...@@ -4450,6 +4450,12 @@ static const struct alg_test_desc alg_test_descs[] = {
.suite = { .suite = {
.hash = __VECS(aes_cbcmac_tv_template) .hash = __VECS(aes_cbcmac_tv_template)
} }
}, {
.alg = "cbcmac(sm4)",
.test = alg_test_hash,
.suite = {
.hash = __VECS(sm4_cbcmac_tv_template)
}
}, { }, {
.alg = "ccm(aes)", .alg = "ccm(aes)",
.generic_driver = "ccm_base(ctr(aes-generic),cbcmac(aes-generic))", .generic_driver = "ccm_base(ctr(aes-generic),cbcmac(aes-generic))",
...@@ -4461,6 +4467,16 @@ static const struct alg_test_desc alg_test_descs[] = { ...@@ -4461,6 +4467,16 @@ static const struct alg_test_desc alg_test_descs[] = {
.einval_allowed = 1, .einval_allowed = 1,
} }
} }
}, {
.alg = "ccm(sm4)",
.generic_driver = "ccm_base(ctr(sm4-generic),cbcmac(sm4-generic))",
.test = alg_test_aead,
.suite = {
.aead = {
____VECS(sm4_ccm_tv_template),
.einval_allowed = 1,
}
}
}, { }, {
.alg = "cfb(aes)", .alg = "cfb(aes)",
.test = alg_test_skcipher, .test = alg_test_skcipher,
...@@ -4494,6 +4510,12 @@ static const struct alg_test_desc alg_test_descs[] = { ...@@ -4494,6 +4510,12 @@ static const struct alg_test_desc alg_test_descs[] = {
.suite = { .suite = {
.hash = __VECS(des3_ede_cmac64_tv_template) .hash = __VECS(des3_ede_cmac64_tv_template)
} }
}, {
.alg = "cmac(sm4)",
.test = alg_test_hash,
.suite = {
.hash = __VECS(sm4_cmac128_tv_template)
}
}, { }, {
.alg = "compress_null", .alg = "compress_null",
.test = alg_test_null, .test = alg_test_null,
...@@ -4967,6 +4989,13 @@ static const struct alg_test_desc alg_test_descs[] = { ...@@ -4967,6 +4989,13 @@ static const struct alg_test_desc alg_test_descs[] = {
.suite = { .suite = {
.aead = __VECS(aes_gcm_tv_template) .aead = __VECS(aes_gcm_tv_template)
} }
}, {
.alg = "gcm(sm4)",
.generic_driver = "gcm_base(ctr(sm4-generic),ghash-generic)",
.test = alg_test_aead,
.suite = {
.aead = __VECS(sm4_gcm_tv_template)
}
}, { }, {
.alg = "ghash", .alg = "ghash",
.test = alg_test_hash, .test = alg_test_hash,
......
...@@ -13328,6 +13328,154 @@ static const struct cipher_testvec sm4_cfb_tv_template[] = { ...@@ -13328,6 +13328,154 @@ static const struct cipher_testvec sm4_cfb_tv_template[] = {
} }
}; };
static const struct aead_testvec sm4_gcm_tv_template[] = {
{ /* From https://datatracker.ietf.org/doc/html/rfc8998#appendix-A.1 */
.key = "\x01\x23\x45\x67\x89\xAB\xCD\xEF"
"\xFE\xDC\xBA\x98\x76\x54\x32\x10",
.klen = 16,
.iv = "\x00\x00\x12\x34\x56\x78\x00\x00"
"\x00\x00\xAB\xCD",
.ptext = "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
"\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB"
"\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE"
"\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA",
.plen = 64,
.assoc = "\xFE\xED\xFA\xCE\xDE\xAD\xBE\xEF"
"\xFE\xED\xFA\xCE\xDE\xAD\xBE\xEF"
"\xAB\xAD\xDA\xD2",
.alen = 20,
.ctext = "\x17\xF3\x99\xF0\x8C\x67\xD5\xEE"
"\x19\xD0\xDC\x99\x69\xC4\xBB\x7D"
"\x5F\xD4\x6F\xD3\x75\x64\x89\x06"
"\x91\x57\xB2\x82\xBB\x20\x07\x35"
"\xD8\x27\x10\xCA\x5C\x22\xF0\xCC"
"\xFA\x7C\xBF\x93\xD4\x96\xAC\x15"
"\xA5\x68\x34\xCB\xCF\x98\xC3\x97"
"\xB4\x02\x4A\x26\x91\x23\x3B\x8D"
"\x83\xDE\x35\x41\xE4\xC2\xB5\x81"
"\x77\xE0\x65\xA9\xBF\x7B\x62\xEC",
.clen = 80,
}
};
static const struct aead_testvec sm4_ccm_tv_template[] = {
{ /* From https://datatracker.ietf.org/doc/html/rfc8998#appendix-A.2 */
.key = "\x01\x23\x45\x67\x89\xAB\xCD\xEF"
"\xFE\xDC\xBA\x98\x76\x54\x32\x10",
.klen = 16,
.iv = "\x02\x00\x00\x12\x34\x56\x78\x00"
"\x00\x00\x00\xAB\xCD\x00\x00\x00",
.ptext = "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
"\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB"
"\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC"
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
"\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE"
"\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA",
.plen = 64,
.assoc = "\xFE\xED\xFA\xCE\xDE\xAD\xBE\xEF"
"\xFE\xED\xFA\xCE\xDE\xAD\xBE\xEF"
"\xAB\xAD\xDA\xD2",
.alen = 20,
.ctext = "\x48\xAF\x93\x50\x1F\xA6\x2A\xDB"
"\xCD\x41\x4C\xCE\x60\x34\xD8\x95"
"\xDD\xA1\xBF\x8F\x13\x2F\x04\x20"
"\x98\x66\x15\x72\xE7\x48\x30\x94"
"\xFD\x12\xE5\x18\xCE\x06\x2C\x98"
"\xAC\xEE\x28\xD9\x5D\xF4\x41\x6B"
"\xED\x31\xA2\xF0\x44\x76\xC1\x8B"
"\xB4\x0C\x84\xA7\x4B\x97\xDC\x5B"
"\x16\x84\x2D\x4F\xA1\x86\xF5\x6A"
"\xB3\x32\x56\x97\x1F\xA1\x10\xF4",
.clen = 80,
}
};
static const struct hash_testvec sm4_cbcmac_tv_template[] = {
{
.key = "\xff\xee\xdd\xcc\xbb\xaa\x99\x88"
"\x77\x66\x55\x44\x33\x22\x11\x00",
.plaintext = "\x01\x23\x45\x67\x89\xab\xcd\xef"
"\xfe\xdc\xba\x98\x76\x54\x32\x10",
.digest = "\x97\xb4\x75\x8f\x84\x92\x3d\x3f"
"\x86\x81\x0e\x0e\xea\x14\x6d\x73",
.psize = 16,
.ksize = 16,
}, {
.key = "\x01\x23\x45\x67\x89\xab\xcd\xef"
"\xfe\xdc\xBA\x98\x76\x54\x32\x10",
.plaintext = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb"
"\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc"
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
"\xee",
.digest = "\xc7\xdb\x17\x71\xa1\x5c\x0d\x22"
"\xa3\x39\x3a\x31\x88\x91\x49\xa1",
.psize = 33,
.ksize = 16,
}, {
.key = "\x01\x23\x45\x67\x89\xab\xcd\xef"
"\xfe\xdc\xBA\x98\x76\x54\x32\x10",
.plaintext = "\xfb\xd1\xbe\x92\x7e\x50\x3f\x16"
"\xf9\xdd\xbe\x91\x73\x53\x37\x1a"
"\xfe\xdd\xba\x97\x7e\x53\x3c\x1c"
"\xfe\xd7\xbf\x9c\x75\x5f\x3e\x11"
"\xf0\xd8\xbc\x96\x73\x5c\x34\x11"
"\xf5\xdb\xb1\x99\x7a\x5a\x32\x1f"
"\xf6\xdf\xb4\x95\x7f\x5f\x3b\x17"
"\xfd\xdb\xb1\x9b\x76\x5c\x37",
.digest = "\x9b\x07\x88\x7f\xd5\x95\x23\x12"
"\x64\x0a\x66\x7f\x4e\x25\xca\xd0",
.psize = 63,
.ksize = 16,
}
};
static const struct hash_testvec sm4_cmac128_tv_template[] = {
{
.key = "\xff\xee\xdd\xcc\xbb\xaa\x99\x88"
"\x77\x66\x55\x44\x33\x22\x11\x00",
.plaintext = "\x01\x23\x45\x67\x89\xab\xcd\xef"
"\xfe\xdc\xba\x98\x76\x54\x32\x10",
.digest = "\x00\xd4\x63\xb4\x9a\xf3\x52\xe2"
"\x74\xa9\x00\x55\x13\x54\x2a\xd1",
.psize = 16,
.ksize = 16,
}, {
.key = "\x01\x23\x45\x67\x89\xab\xcd\xef"
"\xfe\xdc\xBA\x98\x76\x54\x32\x10",
.plaintext = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
"\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb"
"\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc"
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
"\xee",
.digest = "\x8a\x8a\xe9\xc0\xc8\x97\x0e\x85"
"\x21\x57\x02\x10\x1a\xbf\x9c\xc6",
.psize = 33,
.ksize = 16,
}, {
.key = "\x01\x23\x45\x67\x89\xab\xcd\xef"
"\xfe\xdc\xBA\x98\x76\x54\x32\x10",
.plaintext = "\xfb\xd1\xbe\x92\x7e\x50\x3f\x16"
"\xf9\xdd\xbe\x91\x73\x53\x37\x1a"
"\xfe\xdd\xba\x97\x7e\x53\x3c\x1c"
"\xfe\xd7\xbf\x9c\x75\x5f\x3e\x11"
"\xf0\xd8\xbc\x96\x73\x5c\x34\x11"
"\xf5\xdb\xb1\x99\x7a\x5a\x32\x1f"
"\xf6\xdf\xb4\x95\x7f\x5f\x3b\x17"
"\xfd\xdb\xb1\x9b\x76\x5c\x37",
.digest = "\x5f\x14\xc9\xa9\x20\xb2\xb4\xf0"
"\x76\xe0\xd8\xd6\xdc\x4f\xe1\xbc",
.psize = 63,
.ksize = 16,
}
};
/* Cast6 test vectors from RFC 2612 */ /* Cast6 test vectors from RFC 2612 */
static const struct cipher_testvec cast6_tv_template[] = { static const struct cipher_testvec cast6_tv_template[] = {
{ {
...@@ -775,7 +775,7 @@ static const u64 rc[WHIRLPOOL_ROUNDS] = { ...@@ -775,7 +775,7 @@ static const u64 rc[WHIRLPOOL_ROUNDS] = {
0xca2dbf07ad5a8333ULL, 0xca2dbf07ad5a8333ULL,
}; };
/** /*
* The core Whirlpool transform. * The core Whirlpool transform.
*/ */
......
...@@ -524,6 +524,20 @@ config HW_RANDOM_XIPHERA ...@@ -524,6 +524,20 @@ config HW_RANDOM_XIPHERA
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called xiphera-trng. module will be called xiphera-trng.
config HW_RANDOM_ARM_SMCCC_TRNG
tristate "Arm SMCCC TRNG firmware interface support"
depends on HAVE_ARM_SMCCC_DISCOVERY
default HW_RANDOM
help
Say 'Y' to enable the True Random Number Generator driver using
the Arm SMCCC TRNG firmware interface. This reads entropy from
higher exception levels (firmware, hypervisor). Uses SMCCC for
communicating with the firmware:
https://developer.arm.com/documentation/den0098/latest/
To compile this driver as a module, choose M here: the
module will be called arm_smccc_trng.
endif # HW_RANDOM endif # HW_RANDOM
config UML_RANDOM config UML_RANDOM
......
...@@ -45,3 +45,4 @@ obj-$(CONFIG_HW_RANDOM_OPTEE) += optee-rng.o ...@@ -45,3 +45,4 @@ obj-$(CONFIG_HW_RANDOM_OPTEE) += optee-rng.o
obj-$(CONFIG_HW_RANDOM_NPCM) += npcm-rng.o obj-$(CONFIG_HW_RANDOM_NPCM) += npcm-rng.o
obj-$(CONFIG_HW_RANDOM_CCTRNG) += cctrng.o obj-$(CONFIG_HW_RANDOM_CCTRNG) += cctrng.o
obj-$(CONFIG_HW_RANDOM_XIPHERA) += xiphera-trng.o obj-$(CONFIG_HW_RANDOM_XIPHERA) += xiphera-trng.o
obj-$(CONFIG_HW_RANDOM_ARM_SMCCC_TRNG) += arm_smccc_trng.o
...@@ -124,7 +124,7 @@ static struct hwrng amd_rng = { ...@@ -124,7 +124,7 @@ static struct hwrng amd_rng = {
.read = amd_rng_read, .read = amd_rng_read,
}; };
static int __init mod_init(void) static int __init amd_rng_mod_init(void)
{ {
int err; int err;
struct pci_dev *pdev = NULL; struct pci_dev *pdev = NULL;
...@@ -188,7 +188,7 @@ static int __init mod_init(void) ...@@ -188,7 +188,7 @@ static int __init mod_init(void)
return err; return err;
} }
static void __exit mod_exit(void) static void __exit amd_rng_mod_exit(void)
{ {
struct amd768_priv *priv; struct amd768_priv *priv;
...@@ -203,8 +203,8 @@ static void __exit mod_exit(void) ...@@ -203,8 +203,8 @@ static void __exit mod_exit(void)
kfree(priv); kfree(priv);
} }
module_init(mod_init); module_init(amd_rng_mod_init);
module_exit(mod_exit); module_exit(amd_rng_mod_exit);
MODULE_AUTHOR("The Linux Kernel team"); MODULE_AUTHOR("The Linux Kernel team");
MODULE_DESCRIPTION("H/W RNG driver for AMD chipsets"); MODULE_DESCRIPTION("H/W RNG driver for AMD chipsets");
......
// SPDX-License-Identifier: GPL-2.0
/*
* Randomness driver for the ARM SMCCC TRNG Firmware Interface
* https://developer.arm.com/documentation/den0098/latest/
*
* Copyright (C) 2020 Arm Ltd.
*
* The ARM TRNG firmware interface specifies a protocol to read entropy
* from a higher exception level, to abstract from any machine specific
* implemenations and allow easier use in hypervisors.
*
* The firmware interface is realised using the SMCCC specification.
*/
#include <linux/bits.h>
#include <linux/device.h>
#include <linux/hw_random.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/arm-smccc.h>
#ifdef CONFIG_ARM64
#define ARM_SMCCC_TRNG_RND ARM_SMCCC_TRNG_RND64
#define MAX_BITS_PER_CALL (3 * 64UL)
#else
#define ARM_SMCCC_TRNG_RND ARM_SMCCC_TRNG_RND32
#define MAX_BITS_PER_CALL (3 * 32UL)
#endif
/* We don't want to allow the firmware to stall us forever. */
#define SMCCC_TRNG_MAX_TRIES 20
#define SMCCC_RET_TRNG_INVALID_PARAMETER -2
#define SMCCC_RET_TRNG_NO_ENTROPY -3
static int copy_from_registers(char *buf, struct arm_smccc_res *res,
size_t bytes)
{
unsigned int chunk, copied;
if (bytes == 0)
return 0;
chunk = min(bytes, sizeof(long));
memcpy(buf, &res->a3, chunk);
copied = chunk;
if (copied >= bytes)
return copied;
chunk = min((bytes - copied), sizeof(long));
memcpy(&buf[copied], &res->a2, chunk);
copied += chunk;
if (copied >= bytes)
return copied;
chunk = min((bytes - copied), sizeof(long));
memcpy(&buf[copied], &res->a1, chunk);
return copied + chunk;
}
static int smccc_trng_read(struct hwrng *rng, void *data, size_t max, bool wait)
{
struct arm_smccc_res res;
u8 *buf = data;
unsigned int copied = 0;
int tries = 0;
while (copied < max) {
size_t bits = min_t(size_t, (max - copied) * BITS_PER_BYTE,
MAX_BITS_PER_CALL);
arm_smccc_1_1_invoke(ARM_SMCCC_TRNG_RND, bits, &res);
if ((int)res.a0 < 0)
return (int)res.a0;
switch ((int)res.a0) {
case SMCCC_RET_SUCCESS:
copied += copy_from_registers(buf + copied, &res,
bits / BITS_PER_BYTE);
tries = 0;
break;
case SMCCC_RET_TRNG_NO_ENTROPY:
if (!wait)
return copied;
tries++;
if (tries >= SMCCC_TRNG_MAX_TRIES)
return copied;
cond_resched();
break;
}
}
return copied;
}
static int smccc_trng_probe(struct platform_device *pdev)
{
struct hwrng *trng;
trng = devm_kzalloc(&pdev->dev, sizeof(*trng), GFP_KERNEL);
if (!trng)
return -ENOMEM;
trng->name = "smccc_trng";
trng->read = smccc_trng_read;
platform_set_drvdata(pdev, trng);
return devm_hwrng_register(&pdev->dev, trng);
}
static struct platform_driver smccc_trng_driver = {
.driver = {
.name = "smccc_trng",
},
.probe = smccc_trng_probe,
};
module_platform_driver(smccc_trng_driver);
MODULE_ALIAS("platform:smccc_trng");
MODULE_AUTHOR("Andre Przywara");
MODULE_LICENSE("GPL");
...@@ -83,7 +83,7 @@ static struct hwrng geode_rng = { ...@@ -83,7 +83,7 @@ static struct hwrng geode_rng = {
}; };
static int __init mod_init(void) static int __init geode_rng_init(void)
{ {
int err = -ENODEV; int err = -ENODEV;
struct pci_dev *pdev = NULL; struct pci_dev *pdev = NULL;
...@@ -124,7 +124,7 @@ static int __init mod_init(void) ...@@ -124,7 +124,7 @@ static int __init mod_init(void)
goto out; goto out;
} }
static void __exit mod_exit(void) static void __exit geode_rng_exit(void)
{ {
void __iomem *mem = (void __iomem *)geode_rng.priv; void __iomem *mem = (void __iomem *)geode_rng.priv;
...@@ -132,8 +132,8 @@ static void __exit mod_exit(void) ...@@ -132,8 +132,8 @@ static void __exit mod_exit(void)
iounmap(mem); iounmap(mem);
} }
module_init(mod_init); module_init(geode_rng_init);
module_exit(mod_exit); module_exit(geode_rng_exit);
MODULE_DESCRIPTION("H/W RNG driver for AMD Geode LX CPUs"); MODULE_DESCRIPTION("H/W RNG driver for AMD Geode LX CPUs");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -325,7 +325,7 @@ PFX "RNG, try using the 'no_fwh_detect' option.\n"; ...@@ -325,7 +325,7 @@ PFX "RNG, try using the 'no_fwh_detect' option.\n";
} }
static int __init mod_init(void) static int __init intel_rng_mod_init(void)
{ {
int err = -ENODEV; int err = -ENODEV;
int i; int i;
...@@ -403,7 +403,7 @@ static int __init mod_init(void) ...@@ -403,7 +403,7 @@ static int __init mod_init(void)
} }
static void __exit mod_exit(void) static void __exit intel_rng_mod_exit(void)
{ {
void __iomem *mem = (void __iomem *)intel_rng.priv; void __iomem *mem = (void __iomem *)intel_rng.priv;
...@@ -411,8 +411,8 @@ static void __exit mod_exit(void) ...@@ -411,8 +411,8 @@ static void __exit mod_exit(void)
iounmap(mem); iounmap(mem);
} }
module_init(mod_init); module_init(intel_rng_mod_init);
module_exit(mod_exit); module_exit(intel_rng_mod_exit);
MODULE_DESCRIPTION("H/W RNG driver for Intel chipsets"); MODULE_DESCRIPTION("H/W RNG driver for Intel chipsets");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -192,7 +192,7 @@ static struct hwrng via_rng = { ...@@ -192,7 +192,7 @@ static struct hwrng via_rng = {
}; };
static int __init mod_init(void) static int __init via_rng_mod_init(void)
{ {
int err; int err;
...@@ -209,13 +209,13 @@ static int __init mod_init(void) ...@@ -209,13 +209,13 @@ static int __init mod_init(void)
out: out:
return err; return err;
} }
module_init(mod_init); module_init(via_rng_mod_init);
static void __exit mod_exit(void) static void __exit via_rng_mod_exit(void)
{ {
hwrng_unregister(&via_rng); hwrng_unregister(&via_rng);
} }
module_exit(mod_exit); module_exit(via_rng_mod_exit);
static struct x86_cpu_id __maybe_unused via_rng_cpu_id[] = { static struct x86_cpu_id __maybe_unused via_rng_cpu_id[] = {
X86_MATCH_FEATURE(X86_FEATURE_XSTORE, NULL), X86_MATCH_FEATURE(X86_FEATURE_XSTORE, NULL),
......
...@@ -26,8 +26,7 @@ void sun8i_ce_prng_exit(struct crypto_tfm *tfm) ...@@ -26,8 +26,7 @@ void sun8i_ce_prng_exit(struct crypto_tfm *tfm)
{ {
struct sun8i_ce_rng_tfm_ctx *ctx = crypto_tfm_ctx(tfm); struct sun8i_ce_rng_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
memzero_explicit(ctx->seed, ctx->slen); kfree_sensitive(ctx->seed);
kfree(ctx->seed);
ctx->seed = NULL; ctx->seed = NULL;
ctx->slen = 0; ctx->slen = 0;
} }
...@@ -38,8 +37,7 @@ int sun8i_ce_prng_seed(struct crypto_rng *tfm, const u8 *seed, ...@@ -38,8 +37,7 @@ int sun8i_ce_prng_seed(struct crypto_rng *tfm, const u8 *seed,
struct sun8i_ce_rng_tfm_ctx *ctx = crypto_rng_ctx(tfm); struct sun8i_ce_rng_tfm_ctx *ctx = crypto_rng_ctx(tfm);
if (ctx->seed && ctx->slen != slen) { if (ctx->seed && ctx->slen != slen) {
memzero_explicit(ctx->seed, ctx->slen); kfree_sensitive(ctx->seed);
kfree(ctx->seed);
ctx->slen = 0; ctx->slen = 0;
ctx->seed = NULL; ctx->seed = NULL;
} }
...@@ -157,9 +155,8 @@ int sun8i_ce_prng_generate(struct crypto_rng *tfm, const u8 *src, ...@@ -157,9 +155,8 @@ int sun8i_ce_prng_generate(struct crypto_rng *tfm, const u8 *src,
memcpy(dst, d, dlen); memcpy(dst, d, dlen);
memcpy(ctx->seed, d + dlen, ctx->slen); memcpy(ctx->seed, d + dlen, ctx->slen);
} }
memzero_explicit(d, todo);
err_iv: err_iv:
kfree(d); kfree_sensitive(d);
err_mem: err_mem:
return err; return err;
} }
...@@ -95,9 +95,8 @@ static int sun8i_ce_trng_read(struct hwrng *rng, void *data, size_t max, bool wa ...@@ -95,9 +95,8 @@ static int sun8i_ce_trng_read(struct hwrng *rng, void *data, size_t max, bool wa
memcpy(data, d, max); memcpy(data, d, max);
err = max; err = max;
} }
memzero_explicit(d, todo);
err_dst: err_dst:
kfree(d); kfree_sensitive(d);
return err; return err;
} }
......
...@@ -20,8 +20,7 @@ int sun8i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed, ...@@ -20,8 +20,7 @@ int sun8i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed,
struct sun8i_ss_rng_tfm_ctx *ctx = crypto_rng_ctx(tfm); struct sun8i_ss_rng_tfm_ctx *ctx = crypto_rng_ctx(tfm);
if (ctx->seed && ctx->slen != slen) { if (ctx->seed && ctx->slen != slen) {
memzero_explicit(ctx->seed, ctx->slen); kfree_sensitive(ctx->seed);
kfree(ctx->seed);
ctx->slen = 0; ctx->slen = 0;
ctx->seed = NULL; ctx->seed = NULL;
} }
...@@ -48,8 +47,7 @@ void sun8i_ss_prng_exit(struct crypto_tfm *tfm) ...@@ -48,8 +47,7 @@ void sun8i_ss_prng_exit(struct crypto_tfm *tfm)
{ {
struct sun8i_ss_rng_tfm_ctx *ctx = crypto_tfm_ctx(tfm); struct sun8i_ss_rng_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
memzero_explicit(ctx->seed, ctx->slen); kfree_sensitive(ctx->seed);
kfree(ctx->seed);
ctx->seed = NULL; ctx->seed = NULL;
ctx->slen = 0; ctx->slen = 0;
} }
...@@ -167,9 +165,8 @@ int sun8i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src, ...@@ -167,9 +165,8 @@ int sun8i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src,
/* Update seed */ /* Update seed */
memcpy(ctx->seed, d + dlen, ctx->slen); memcpy(ctx->seed, d + dlen, ctx->slen);
} }
memzero_explicit(d, todo);
err_free: err_free:
kfree(d); kfree_sensitive(d);
return err; return err;
} }
This diff is collapsed.
...@@ -196,23 +196,15 @@ static void atmel_tdes_write_n(struct atmel_tdes_dev *dd, u32 offset, ...@@ -196,23 +196,15 @@ static void atmel_tdes_write_n(struct atmel_tdes_dev *dd, u32 offset,
atmel_tdes_write(dd, offset, *value); atmel_tdes_write(dd, offset, *value);
} }
static struct atmel_tdes_dev *atmel_tdes_find_dev(struct atmel_tdes_ctx *ctx) static struct atmel_tdes_dev *atmel_tdes_dev_alloc(void)
{ {
struct atmel_tdes_dev *tdes_dd = NULL; struct atmel_tdes_dev *tdes_dd;
struct atmel_tdes_dev *tmp;
spin_lock_bh(&atmel_tdes.lock); spin_lock_bh(&atmel_tdes.lock);
if (!ctx->dd) { /* One TDES IP per SoC. */
list_for_each_entry(tmp, &atmel_tdes.dev_list, list) { tdes_dd = list_first_entry_or_null(&atmel_tdes.dev_list,
tdes_dd = tmp; struct atmel_tdes_dev, list);
break;
}
ctx->dd = tdes_dd;
} else {
tdes_dd = ctx->dd;
}
spin_unlock_bh(&atmel_tdes.lock); spin_unlock_bh(&atmel_tdes.lock);
return tdes_dd; return tdes_dd;
} }
...@@ -320,7 +312,7 @@ static int atmel_tdes_crypt_pdc_stop(struct atmel_tdes_dev *dd) ...@@ -320,7 +312,7 @@ static int atmel_tdes_crypt_pdc_stop(struct atmel_tdes_dev *dd)
dd->buf_out, dd->buflen, dd->dma_size, 1); dd->buf_out, dd->buflen, dd->dma_size, 1);
if (count != dd->dma_size) { if (count != dd->dma_size) {
err = -EINVAL; err = -EINVAL;
pr_err("not all data converted: %zu\n", count); dev_dbg(dd->dev, "not all data converted: %zu\n", count);
} }
} }
...@@ -337,24 +329,24 @@ static int atmel_tdes_buff_init(struct atmel_tdes_dev *dd) ...@@ -337,24 +329,24 @@ static int atmel_tdes_buff_init(struct atmel_tdes_dev *dd)
dd->buflen &= ~(DES_BLOCK_SIZE - 1); dd->buflen &= ~(DES_BLOCK_SIZE - 1);
if (!dd->buf_in || !dd->buf_out) { if (!dd->buf_in || !dd->buf_out) {
dev_err(dd->dev, "unable to alloc pages.\n"); dev_dbg(dd->dev, "unable to alloc pages.\n");
goto err_alloc; goto err_alloc;
} }
/* MAP here */ /* MAP here */
dd->dma_addr_in = dma_map_single(dd->dev, dd->buf_in, dd->dma_addr_in = dma_map_single(dd->dev, dd->buf_in,
dd->buflen, DMA_TO_DEVICE); dd->buflen, DMA_TO_DEVICE);
if (dma_mapping_error(dd->dev, dd->dma_addr_in)) { err = dma_mapping_error(dd->dev, dd->dma_addr_in);
dev_err(dd->dev, "dma %zd bytes error\n", dd->buflen); if (err) {
err = -EINVAL; dev_dbg(dd->dev, "dma %zd bytes error\n", dd->buflen);
goto err_map_in; goto err_map_in;
} }
dd->dma_addr_out = dma_map_single(dd->dev, dd->buf_out, dd->dma_addr_out = dma_map_single(dd->dev, dd->buf_out,
dd->buflen, DMA_FROM_DEVICE); dd->buflen, DMA_FROM_DEVICE);
if (dma_mapping_error(dd->dev, dd->dma_addr_out)) { err = dma_mapping_error(dd->dev, dd->dma_addr_out);
dev_err(dd->dev, "dma %zd bytes error\n", dd->buflen); if (err) {
err = -EINVAL; dev_dbg(dd->dev, "dma %zd bytes error\n", dd->buflen);
goto err_map_out; goto err_map_out;
} }
...@@ -367,8 +359,6 @@ static int atmel_tdes_buff_init(struct atmel_tdes_dev *dd) ...@@ -367,8 +359,6 @@ static int atmel_tdes_buff_init(struct atmel_tdes_dev *dd)
err_alloc: err_alloc:
free_page((unsigned long)dd->buf_out); free_page((unsigned long)dd->buf_out);
free_page((unsigned long)dd->buf_in); free_page((unsigned long)dd->buf_in);
if (err)
pr_err("error: %d\n", err);
return err; return err;
} }
...@@ -520,14 +510,14 @@ static int atmel_tdes_crypt_start(struct atmel_tdes_dev *dd) ...@@ -520,14 +510,14 @@ static int atmel_tdes_crypt_start(struct atmel_tdes_dev *dd)
err = dma_map_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE); err = dma_map_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
if (!err) { if (!err) {
dev_err(dd->dev, "dma_map_sg() error\n"); dev_dbg(dd->dev, "dma_map_sg() error\n");
return -EINVAL; return -EINVAL;
} }
err = dma_map_sg(dd->dev, dd->out_sg, 1, err = dma_map_sg(dd->dev, dd->out_sg, 1,
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
if (!err) { if (!err) {
dev_err(dd->dev, "dma_map_sg() error\n"); dev_dbg(dd->dev, "dma_map_sg() error\n");
dma_unmap_sg(dd->dev, dd->in_sg, 1, dma_unmap_sg(dd->dev, dd->in_sg, 1,
DMA_TO_DEVICE); DMA_TO_DEVICE);
return -EINVAL; return -EINVAL;
...@@ -646,7 +636,6 @@ static int atmel_tdes_handle_queue(struct atmel_tdes_dev *dd, ...@@ -646,7 +636,6 @@ static int atmel_tdes_handle_queue(struct atmel_tdes_dev *dd,
rctx->mode &= TDES_FLAGS_MODE_MASK; rctx->mode &= TDES_FLAGS_MODE_MASK;
dd->flags = (dd->flags & ~TDES_FLAGS_MODE_MASK) | rctx->mode; dd->flags = (dd->flags & ~TDES_FLAGS_MODE_MASK) | rctx->mode;
dd->ctx = ctx; dd->ctx = ctx;
ctx->dd = dd;
err = atmel_tdes_write_ctrl(dd); err = atmel_tdes_write_ctrl(dd);
if (!err) if (!err)
...@@ -679,7 +668,7 @@ static int atmel_tdes_crypt_dma_stop(struct atmel_tdes_dev *dd) ...@@ -679,7 +668,7 @@ static int atmel_tdes_crypt_dma_stop(struct atmel_tdes_dev *dd)
dd->buf_out, dd->buflen, dd->dma_size, 1); dd->buf_out, dd->buflen, dd->dma_size, 1);
if (count != dd->dma_size) { if (count != dd->dma_size) {
err = -EINVAL; err = -EINVAL;
pr_err("not all data converted: %zu\n", count); dev_dbg(dd->dev, "not all data converted: %zu\n", count);
} }
} }
} }
...@@ -691,11 +680,15 @@ static int atmel_tdes_crypt(struct skcipher_request *req, unsigned long mode) ...@@ -691,11 +680,15 @@ static int atmel_tdes_crypt(struct skcipher_request *req, unsigned long mode)
struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req);
struct atmel_tdes_ctx *ctx = crypto_skcipher_ctx(skcipher); struct atmel_tdes_ctx *ctx = crypto_skcipher_ctx(skcipher);
struct atmel_tdes_reqctx *rctx = skcipher_request_ctx(req); struct atmel_tdes_reqctx *rctx = skcipher_request_ctx(req);
struct device *dev = ctx->dd->dev;
if (!req->cryptlen)
return 0;
switch (mode & TDES_FLAGS_OPMODE_MASK) { switch (mode & TDES_FLAGS_OPMODE_MASK) {
case TDES_FLAGS_CFB8: case TDES_FLAGS_CFB8:
if (!IS_ALIGNED(req->cryptlen, CFB8_BLOCK_SIZE)) { if (!IS_ALIGNED(req->cryptlen, CFB8_BLOCK_SIZE)) {
pr_err("request size is not exact amount of CFB8 blocks\n"); dev_dbg(dev, "request size is not exact amount of CFB8 blocks\n");
return -EINVAL; return -EINVAL;
} }
ctx->block_size = CFB8_BLOCK_SIZE; ctx->block_size = CFB8_BLOCK_SIZE;
...@@ -703,7 +696,7 @@ static int atmel_tdes_crypt(struct skcipher_request *req, unsigned long mode) ...@@ -703,7 +696,7 @@ static int atmel_tdes_crypt(struct skcipher_request *req, unsigned long mode)
case TDES_FLAGS_CFB16: case TDES_FLAGS_CFB16:
if (!IS_ALIGNED(req->cryptlen, CFB16_BLOCK_SIZE)) { if (!IS_ALIGNED(req->cryptlen, CFB16_BLOCK_SIZE)) {
pr_err("request size is not exact amount of CFB16 blocks\n"); dev_dbg(dev, "request size is not exact amount of CFB16 blocks\n");
return -EINVAL; return -EINVAL;
} }
ctx->block_size = CFB16_BLOCK_SIZE; ctx->block_size = CFB16_BLOCK_SIZE;
...@@ -711,7 +704,7 @@ static int atmel_tdes_crypt(struct skcipher_request *req, unsigned long mode) ...@@ -711,7 +704,7 @@ static int atmel_tdes_crypt(struct skcipher_request *req, unsigned long mode)
case TDES_FLAGS_CFB32: case TDES_FLAGS_CFB32:
if (!IS_ALIGNED(req->cryptlen, CFB32_BLOCK_SIZE)) { if (!IS_ALIGNED(req->cryptlen, CFB32_BLOCK_SIZE)) {
pr_err("request size is not exact amount of CFB32 blocks\n"); dev_dbg(dev, "request size is not exact amount of CFB32 blocks\n");
return -EINVAL; return -EINVAL;
} }
ctx->block_size = CFB32_BLOCK_SIZE; ctx->block_size = CFB32_BLOCK_SIZE;
...@@ -719,7 +712,7 @@ static int atmel_tdes_crypt(struct skcipher_request *req, unsigned long mode) ...@@ -719,7 +712,7 @@ static int atmel_tdes_crypt(struct skcipher_request *req, unsigned long mode)
default: default:
if (!IS_ALIGNED(req->cryptlen, DES_BLOCK_SIZE)) { if (!IS_ALIGNED(req->cryptlen, DES_BLOCK_SIZE)) {
pr_err("request size is not exact amount of DES blocks\n"); dev_dbg(dev, "request size is not exact amount of DES blocks\n");
return -EINVAL; return -EINVAL;
} }
ctx->block_size = DES_BLOCK_SIZE; ctx->block_size = DES_BLOCK_SIZE;
...@@ -897,14 +890,13 @@ static int atmel_tdes_ofb_decrypt(struct skcipher_request *req) ...@@ -897,14 +890,13 @@ static int atmel_tdes_ofb_decrypt(struct skcipher_request *req)
static int atmel_tdes_init_tfm(struct crypto_skcipher *tfm) static int atmel_tdes_init_tfm(struct crypto_skcipher *tfm)
{ {
struct atmel_tdes_ctx *ctx = crypto_skcipher_ctx(tfm); struct atmel_tdes_ctx *ctx = crypto_skcipher_ctx(tfm);
struct atmel_tdes_dev *dd;
crypto_skcipher_set_reqsize(tfm, sizeof(struct atmel_tdes_reqctx));
dd = atmel_tdes_find_dev(ctx); ctx->dd = atmel_tdes_dev_alloc();
if (!dd) if (!ctx->dd)
return -ENODEV; return -ENODEV;
crypto_skcipher_set_reqsize(tfm, sizeof(struct atmel_tdes_reqctx));
return 0; return 0;
} }
...@@ -999,7 +991,7 @@ static struct skcipher_alg tdes_algs[] = { ...@@ -999,7 +991,7 @@ static struct skcipher_alg tdes_algs[] = {
{ {
.base.cra_name = "ofb(des)", .base.cra_name = "ofb(des)",
.base.cra_driver_name = "atmel-ofb-des", .base.cra_driver_name = "atmel-ofb-des",
.base.cra_blocksize = DES_BLOCK_SIZE, .base.cra_blocksize = 1,
.base.cra_alignmask = 0x7, .base.cra_alignmask = 0x7,
.min_keysize = DES_KEY_SIZE, .min_keysize = DES_KEY_SIZE,
......
...@@ -300,6 +300,9 @@ static int __sev_platform_shutdown_locked(int *error) ...@@ -300,6 +300,9 @@ static int __sev_platform_shutdown_locked(int *error)
struct sev_device *sev = psp_master->sev_data; struct sev_device *sev = psp_master->sev_data;
int ret; int ret;
if (sev->state == SEV_STATE_UNINIT)
return 0;
ret = __sev_do_cmd_locked(SEV_CMD_SHUTDOWN, NULL, error); ret = __sev_do_cmd_locked(SEV_CMD_SHUTDOWN, NULL, error);
if (ret) if (ret)
return ret; return ret;
...@@ -1019,6 +1022,20 @@ int sev_dev_init(struct psp_device *psp) ...@@ -1019,6 +1022,20 @@ int sev_dev_init(struct psp_device *psp)
return ret; return ret;
} }
static void sev_firmware_shutdown(struct sev_device *sev)
{
sev_platform_shutdown(NULL);
if (sev_es_tmr) {
/* The TMR area was encrypted, flush it from the cache */
wbinvd_on_all_cpus();
free_pages((unsigned long)sev_es_tmr,
get_order(SEV_ES_TMR_SIZE));
sev_es_tmr = NULL;
}
}
void sev_dev_destroy(struct psp_device *psp) void sev_dev_destroy(struct psp_device *psp)
{ {
struct sev_device *sev = psp->sev_data; struct sev_device *sev = psp->sev_data;
...@@ -1026,6 +1043,8 @@ void sev_dev_destroy(struct psp_device *psp) ...@@ -1026,6 +1043,8 @@ void sev_dev_destroy(struct psp_device *psp)
if (!sev) if (!sev)
return; return;
sev_firmware_shutdown(sev);
if (sev->misc) if (sev->misc)
kref_put(&misc_dev->refcount, sev_exit); kref_put(&misc_dev->refcount, sev_exit);
...@@ -1056,21 +1075,6 @@ void sev_pci_init(void) ...@@ -1056,21 +1075,6 @@ void sev_pci_init(void)
if (sev_get_api_version()) if (sev_get_api_version())
goto err; goto err;
/*
* If platform is not in UNINIT state then firmware upgrade and/or
* platform INIT command will fail. These command require UNINIT state.
*
* In a normal boot we should never run into case where the firmware
* is not in UNINIT state on boot. But in case of kexec boot, a reboot
* may not go through a typical shutdown sequence and may leave the
* firmware in INIT or WORKING state.
*/
if (sev->state != SEV_STATE_UNINIT) {
sev_platform_shutdown(NULL);
sev->state = SEV_STATE_UNINIT;
}
if (sev_version_greater_or_equal(0, 15) && if (sev_version_greater_or_equal(0, 15) &&
sev_update_firmware(sev->dev) == 0) sev_update_firmware(sev->dev) == 0)
sev_get_api_version(); sev_get_api_version();
...@@ -1115,17 +1119,10 @@ void sev_pci_init(void) ...@@ -1115,17 +1119,10 @@ void sev_pci_init(void)
void sev_pci_exit(void) void sev_pci_exit(void)
{ {
if (!psp_master->sev_data) struct sev_device *sev = psp_master->sev_data;
return;
sev_platform_shutdown(NULL);
if (sev_es_tmr) { if (!sev)
/* The TMR area was encrypted, flush it from the cache */ return;
wbinvd_on_all_cpus();
free_pages((unsigned long)sev_es_tmr, sev_firmware_shutdown(sev);
get_order(SEV_ES_TMR_SIZE));
sev_es_tmr = NULL;
}
} }
...@@ -241,6 +241,17 @@ static int sp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -241,6 +241,17 @@ static int sp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return ret; return ret;
} }
static void sp_pci_shutdown(struct pci_dev *pdev)
{
struct device *dev = &pdev->dev;
struct sp_device *sp = dev_get_drvdata(dev);
if (!sp)
return;
sp_destroy(sp);
}
static void sp_pci_remove(struct pci_dev *pdev) static void sp_pci_remove(struct pci_dev *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
...@@ -349,6 +360,12 @@ static const struct sp_dev_vdata dev_vdata[] = { ...@@ -349,6 +360,12 @@ static const struct sp_dev_vdata dev_vdata[] = {
#endif #endif
#ifdef CONFIG_CRYPTO_DEV_SP_PSP #ifdef CONFIG_CRYPTO_DEV_SP_PSP
.psp_vdata = &pspv3, .psp_vdata = &pspv3,
#endif
},
{ /* 5 */
.bar = 2,
#ifdef CONFIG_CRYPTO_DEV_SP_PSP
.psp_vdata = &pspv2,
#endif #endif
}, },
}; };
...@@ -359,6 +376,7 @@ static const struct pci_device_id sp_pci_table[] = { ...@@ -359,6 +376,7 @@ static const struct pci_device_id sp_pci_table[] = {
{ PCI_VDEVICE(AMD, 0x1486), (kernel_ulong_t)&dev_vdata[3] }, { PCI_VDEVICE(AMD, 0x1486), (kernel_ulong_t)&dev_vdata[3] },
{ PCI_VDEVICE(AMD, 0x15DF), (kernel_ulong_t)&dev_vdata[4] }, { PCI_VDEVICE(AMD, 0x15DF), (kernel_ulong_t)&dev_vdata[4] },
{ PCI_VDEVICE(AMD, 0x1649), (kernel_ulong_t)&dev_vdata[4] }, { PCI_VDEVICE(AMD, 0x1649), (kernel_ulong_t)&dev_vdata[4] },
{ PCI_VDEVICE(AMD, 0x14CA), (kernel_ulong_t)&dev_vdata[5] },
/* Last entry must be zero */ /* Last entry must be zero */
{ 0, } { 0, }
}; };
...@@ -371,6 +389,7 @@ static struct pci_driver sp_pci_driver = { ...@@ -371,6 +389,7 @@ static struct pci_driver sp_pci_driver = {
.id_table = sp_pci_table, .id_table = sp_pci_table,
.probe = sp_pci_probe, .probe = sp_pci_probe,
.remove = sp_pci_remove, .remove = sp_pci_remove,
.shutdown = sp_pci_shutdown,
.driver.pm = &sp_pci_pm_ops, .driver.pm = &sp_pci_pm_ops,
}; };
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/pm_runtime.h>
#include <linux/topology.h> #include <linux/topology.h>
#include <linux/uacce.h> #include <linux/uacce.h>
#include "hpre.h" #include "hpre.h"
...@@ -81,6 +82,16 @@ ...@@ -81,6 +82,16 @@
#define HPRE_PREFETCH_DISABLE BIT(30) #define HPRE_PREFETCH_DISABLE BIT(30)
#define HPRE_SVA_DISABLE_READY (BIT(4) | BIT(8)) #define HPRE_SVA_DISABLE_READY (BIT(4) | BIT(8))
/* clock gate */
#define HPRE_CLKGATE_CTL 0x301a10
#define HPRE_PEH_CFG_AUTO_GATE 0x301a2c
#define HPRE_CLUSTER_DYN_CTL 0x302010
#define HPRE_CORE_SHB_CFG 0x302088
#define HPRE_CLKGATE_CTL_EN BIT(0)
#define HPRE_PEH_CFG_AUTO_GATE_EN BIT(0)
#define HPRE_CLUSTER_DYN_CTL_EN BIT(0)
#define HPRE_CORE_GATE_EN (BIT(30) | BIT(31))
#define HPRE_AM_OOO_SHUTDOWN_ENB 0x301044 #define HPRE_AM_OOO_SHUTDOWN_ENB 0x301044
#define HPRE_AM_OOO_SHUTDOWN_ENABLE BIT(0) #define HPRE_AM_OOO_SHUTDOWN_ENABLE BIT(0)
#define HPRE_WR_MSI_PORT BIT(2) #define HPRE_WR_MSI_PORT BIT(2)
...@@ -417,12 +428,63 @@ static void hpre_close_sva_prefetch(struct hisi_qm *qm) ...@@ -417,12 +428,63 @@ static void hpre_close_sva_prefetch(struct hisi_qm *qm)
pci_err(qm->pdev, "failed to close sva prefetch\n"); pci_err(qm->pdev, "failed to close sva prefetch\n");
} }
static void hpre_enable_clock_gate(struct hisi_qm *qm)
{
u32 val;
if (qm->ver < QM_HW_V3)
return;
val = readl(qm->io_base + HPRE_CLKGATE_CTL);
val |= HPRE_CLKGATE_CTL_EN;
writel(val, qm->io_base + HPRE_CLKGATE_CTL);
val = readl(qm->io_base + HPRE_PEH_CFG_AUTO_GATE);
val |= HPRE_PEH_CFG_AUTO_GATE_EN;
writel(val, qm->io_base + HPRE_PEH_CFG_AUTO_GATE);
val = readl(qm->io_base + HPRE_CLUSTER_DYN_CTL);
val |= HPRE_CLUSTER_DYN_CTL_EN;
writel(val, qm->io_base + HPRE_CLUSTER_DYN_CTL);
val = readl_relaxed(qm->io_base + HPRE_CORE_SHB_CFG);
val |= HPRE_CORE_GATE_EN;
writel(val, qm->io_base + HPRE_CORE_SHB_CFG);
}
static void hpre_disable_clock_gate(struct hisi_qm *qm)
{
u32 val;
if (qm->ver < QM_HW_V3)
return;
val = readl(qm->io_base + HPRE_CLKGATE_CTL);
val &= ~HPRE_CLKGATE_CTL_EN;
writel(val, qm->io_base + HPRE_CLKGATE_CTL);
val = readl(qm->io_base + HPRE_PEH_CFG_AUTO_GATE);
val &= ~HPRE_PEH_CFG_AUTO_GATE_EN;
writel(val, qm->io_base + HPRE_PEH_CFG_AUTO_GATE);
val = readl(qm->io_base + HPRE_CLUSTER_DYN_CTL);
val &= ~HPRE_CLUSTER_DYN_CTL_EN;
writel(val, qm->io_base + HPRE_CLUSTER_DYN_CTL);
val = readl_relaxed(qm->io_base + HPRE_CORE_SHB_CFG);
val &= ~HPRE_CORE_GATE_EN;
writel(val, qm->io_base + HPRE_CORE_SHB_CFG);
}
static int hpre_set_user_domain_and_cache(struct hisi_qm *qm) static int hpre_set_user_domain_and_cache(struct hisi_qm *qm)
{ {
struct device *dev = &qm->pdev->dev; struct device *dev = &qm->pdev->dev;
u32 val; u32 val;
int ret; int ret;
/* disabel dynamic clock gate before sram init */
hpre_disable_clock_gate(qm);
writel(HPRE_QM_USR_CFG_MASK, qm->io_base + QM_ARUSER_M_CFG_ENABLE); writel(HPRE_QM_USR_CFG_MASK, qm->io_base + QM_ARUSER_M_CFG_ENABLE);
writel(HPRE_QM_USR_CFG_MASK, qm->io_base + QM_AWUSER_M_CFG_ENABLE); writel(HPRE_QM_USR_CFG_MASK, qm->io_base + QM_AWUSER_M_CFG_ENABLE);
writel_relaxed(HPRE_QM_AXI_CFG_MASK, qm->io_base + QM_AXI_M_CFG); writel_relaxed(HPRE_QM_AXI_CFG_MASK, qm->io_base + QM_AXI_M_CFG);
...@@ -473,6 +535,8 @@ static int hpre_set_user_domain_and_cache(struct hisi_qm *qm) ...@@ -473,6 +535,8 @@ static int hpre_set_user_domain_and_cache(struct hisi_qm *qm)
/* Config data buffer pasid needed by Kunpeng 920 */ /* Config data buffer pasid needed by Kunpeng 920 */
hpre_config_pasid(qm); hpre_config_pasid(qm);
hpre_enable_clock_gate(qm);
return ret; return ret;
} }
...@@ -595,10 +659,15 @@ static ssize_t hpre_ctrl_debug_read(struct file *filp, char __user *buf, ...@@ -595,10 +659,15 @@ static ssize_t hpre_ctrl_debug_read(struct file *filp, char __user *buf,
size_t count, loff_t *pos) size_t count, loff_t *pos)
{ {
struct hpre_debugfs_file *file = filp->private_data; struct hpre_debugfs_file *file = filp->private_data;
struct hisi_qm *qm = hpre_file_to_qm(file);
char tbuf[HPRE_DBGFS_VAL_MAX_LEN]; char tbuf[HPRE_DBGFS_VAL_MAX_LEN];
u32 val; u32 val;
int ret; int ret;
ret = hisi_qm_get_dfx_access(qm);
if (ret)
return ret;
spin_lock_irq(&file->lock); spin_lock_irq(&file->lock);
switch (file->type) { switch (file->type) {
case HPRE_CLEAR_ENABLE: case HPRE_CLEAR_ENABLE:
...@@ -608,18 +677,25 @@ static ssize_t hpre_ctrl_debug_read(struct file *filp, char __user *buf, ...@@ -608,18 +677,25 @@ static ssize_t hpre_ctrl_debug_read(struct file *filp, char __user *buf,
val = hpre_cluster_inqry_read(file); val = hpre_cluster_inqry_read(file);
break; break;
default: default:
spin_unlock_irq(&file->lock); goto err_input;
return -EINVAL;
} }
spin_unlock_irq(&file->lock); spin_unlock_irq(&file->lock);
hisi_qm_put_dfx_access(qm);
ret = snprintf(tbuf, HPRE_DBGFS_VAL_MAX_LEN, "%u\n", val); ret = snprintf(tbuf, HPRE_DBGFS_VAL_MAX_LEN, "%u\n", val);
return simple_read_from_buffer(buf, count, pos, tbuf, ret); return simple_read_from_buffer(buf, count, pos, tbuf, ret);
err_input:
spin_unlock_irq(&file->lock);
hisi_qm_put_dfx_access(qm);
return -EINVAL;
} }
static ssize_t hpre_ctrl_debug_write(struct file *filp, const char __user *buf, static ssize_t hpre_ctrl_debug_write(struct file *filp, const char __user *buf,
size_t count, loff_t *pos) size_t count, loff_t *pos)
{ {
struct hpre_debugfs_file *file = filp->private_data; struct hpre_debugfs_file *file = filp->private_data;
struct hisi_qm *qm = hpre_file_to_qm(file);
char tbuf[HPRE_DBGFS_VAL_MAX_LEN]; char tbuf[HPRE_DBGFS_VAL_MAX_LEN];
unsigned long val; unsigned long val;
int len, ret; int len, ret;
...@@ -639,6 +715,10 @@ static ssize_t hpre_ctrl_debug_write(struct file *filp, const char __user *buf, ...@@ -639,6 +715,10 @@ static ssize_t hpre_ctrl_debug_write(struct file *filp, const char __user *buf,
if (kstrtoul(tbuf, 0, &val)) if (kstrtoul(tbuf, 0, &val))
return -EFAULT; return -EFAULT;
ret = hisi_qm_get_dfx_access(qm);
if (ret)
return ret;
spin_lock_irq(&file->lock); spin_lock_irq(&file->lock);
switch (file->type) { switch (file->type) {
case HPRE_CLEAR_ENABLE: case HPRE_CLEAR_ENABLE:
...@@ -655,12 +735,12 @@ static ssize_t hpre_ctrl_debug_write(struct file *filp, const char __user *buf, ...@@ -655,12 +735,12 @@ static ssize_t hpre_ctrl_debug_write(struct file *filp, const char __user *buf,
ret = -EINVAL; ret = -EINVAL;
goto err_input; goto err_input;
} }
spin_unlock_irq(&file->lock);
return count; ret = count;
err_input: err_input:
spin_unlock_irq(&file->lock); spin_unlock_irq(&file->lock);
hisi_qm_put_dfx_access(qm);
return ret; return ret;
} }
...@@ -700,6 +780,24 @@ static int hpre_debugfs_atomic64_set(void *data, u64 val) ...@@ -700,6 +780,24 @@ static int hpre_debugfs_atomic64_set(void *data, u64 val)
DEFINE_DEBUGFS_ATTRIBUTE(hpre_atomic64_ops, hpre_debugfs_atomic64_get, DEFINE_DEBUGFS_ATTRIBUTE(hpre_atomic64_ops, hpre_debugfs_atomic64_get,
hpre_debugfs_atomic64_set, "%llu\n"); hpre_debugfs_atomic64_set, "%llu\n");
static int hpre_com_regs_show(struct seq_file *s, void *unused)
{
hisi_qm_regs_dump(s, s->private);
return 0;
}
DEFINE_SHOW_ATTRIBUTE(hpre_com_regs);
static int hpre_cluster_regs_show(struct seq_file *s, void *unused)
{
hisi_qm_regs_dump(s, s->private);
return 0;
}
DEFINE_SHOW_ATTRIBUTE(hpre_cluster_regs);
static int hpre_create_debugfs_file(struct hisi_qm *qm, struct dentry *dir, static int hpre_create_debugfs_file(struct hisi_qm *qm, struct dentry *dir,
enum hpre_ctrl_dbgfs_file type, int indx) enum hpre_ctrl_dbgfs_file type, int indx)
{ {
...@@ -737,8 +835,11 @@ static int hpre_pf_comm_regs_debugfs_init(struct hisi_qm *qm) ...@@ -737,8 +835,11 @@ static int hpre_pf_comm_regs_debugfs_init(struct hisi_qm *qm)
regset->regs = hpre_com_dfx_regs; regset->regs = hpre_com_dfx_regs;
regset->nregs = ARRAY_SIZE(hpre_com_dfx_regs); regset->nregs = ARRAY_SIZE(hpre_com_dfx_regs);
regset->base = qm->io_base; regset->base = qm->io_base;
regset->dev = dev;
debugfs_create_file("regs", 0444, qm->debug.debug_root,
regset, &hpre_com_regs_fops);
debugfs_create_regset32("regs", 0444, qm->debug.debug_root, regset);
return 0; return 0;
} }
...@@ -764,8 +865,10 @@ static int hpre_cluster_debugfs_init(struct hisi_qm *qm) ...@@ -764,8 +865,10 @@ static int hpre_cluster_debugfs_init(struct hisi_qm *qm)
regset->regs = hpre_cluster_dfx_regs; regset->regs = hpre_cluster_dfx_regs;
regset->nregs = ARRAY_SIZE(hpre_cluster_dfx_regs); regset->nregs = ARRAY_SIZE(hpre_cluster_dfx_regs);
regset->base = qm->io_base + hpre_cluster_offsets[i]; regset->base = qm->io_base + hpre_cluster_offsets[i];
regset->dev = dev;
debugfs_create_regset32("regs", 0444, tmp_d, regset); debugfs_create_file("regs", 0444, tmp_d, regset,
&hpre_cluster_regs_fops);
ret = hpre_create_debugfs_file(qm, tmp_d, HPRE_CLUSTER_CTRL, ret = hpre_create_debugfs_file(qm, tmp_d, HPRE_CLUSTER_CTRL,
i + HPRE_CLUSTER_CTRL); i + HPRE_CLUSTER_CTRL);
if (ret) if (ret)
...@@ -1017,6 +1120,8 @@ static int hpre_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -1017,6 +1120,8 @@ static int hpre_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_with_alg_register; goto err_with_alg_register;
} }
hisi_qm_pm_init(qm);
return 0; return 0;
err_with_alg_register: err_with_alg_register:
...@@ -1040,6 +1145,7 @@ static void hpre_remove(struct pci_dev *pdev) ...@@ -1040,6 +1145,7 @@ static void hpre_remove(struct pci_dev *pdev)
struct hisi_qm *qm = pci_get_drvdata(pdev); struct hisi_qm *qm = pci_get_drvdata(pdev);
int ret; int ret;
hisi_qm_pm_uninit(qm);
hisi_qm_wait_task_finish(qm, &hpre_devices); hisi_qm_wait_task_finish(qm, &hpre_devices);
hisi_qm_alg_unregister(qm, &hpre_devices); hisi_qm_alg_unregister(qm, &hpre_devices);
if (qm->fun_type == QM_HW_PF && qm->vfs_num) { if (qm->fun_type == QM_HW_PF && qm->vfs_num) {
...@@ -1062,6 +1168,10 @@ static void hpre_remove(struct pci_dev *pdev) ...@@ -1062,6 +1168,10 @@ static void hpre_remove(struct pci_dev *pdev)
hisi_qm_uninit(qm); hisi_qm_uninit(qm);
} }
static const struct dev_pm_ops hpre_pm_ops = {
SET_RUNTIME_PM_OPS(hisi_qm_suspend, hisi_qm_resume, NULL)
};
static const struct pci_error_handlers hpre_err_handler = { static const struct pci_error_handlers hpre_err_handler = {
.error_detected = hisi_qm_dev_err_detected, .error_detected = hisi_qm_dev_err_detected,
.slot_reset = hisi_qm_dev_slot_reset, .slot_reset = hisi_qm_dev_slot_reset,
...@@ -1078,6 +1188,7 @@ static struct pci_driver hpre_pci_driver = { ...@@ -1078,6 +1188,7 @@ static struct pci_driver hpre_pci_driver = {
hisi_qm_sriov_configure : NULL, hisi_qm_sriov_configure : NULL,
.err_handler = &hpre_err_handler, .err_handler = &hpre_err_handler,
.shutdown = hisi_qm_dev_shutdown, .shutdown = hisi_qm_dev_shutdown,
.driver.pm = &hpre_pm_ops,
}; };
static void hpre_register_debugfs(void) static void hpre_register_debugfs(void)
......
This diff is collapsed.
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#define HISI_ACC_QM_H #define HISI_ACC_QM_H
#include <linux/bitfield.h> #include <linux/bitfield.h>
#include <linux/debugfs.h>
#include <linux/iopoll.h> #include <linux/iopoll.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
...@@ -430,4 +431,11 @@ void hisi_qm_dev_shutdown(struct pci_dev *pdev); ...@@ -430,4 +431,11 @@ void hisi_qm_dev_shutdown(struct pci_dev *pdev);
void hisi_qm_wait_task_finish(struct hisi_qm *qm, struct hisi_qm_list *qm_list); void hisi_qm_wait_task_finish(struct hisi_qm *qm, struct hisi_qm_list *qm_list);
int hisi_qm_alg_register(struct hisi_qm *qm, struct hisi_qm_list *qm_list); int hisi_qm_alg_register(struct hisi_qm *qm, struct hisi_qm_list *qm_list);
void hisi_qm_alg_unregister(struct hisi_qm *qm, struct hisi_qm_list *qm_list); void hisi_qm_alg_unregister(struct hisi_qm *qm, struct hisi_qm_list *qm_list);
int hisi_qm_resume(struct device *dev);
int hisi_qm_suspend(struct device *dev);
void hisi_qm_pm_uninit(struct hisi_qm *qm);
void hisi_qm_pm_init(struct hisi_qm *qm);
int hisi_qm_get_dfx_access(struct hisi_qm *qm);
void hisi_qm_put_dfx_access(struct hisi_qm *qm);
void hisi_qm_regs_dump(struct seq_file *s, struct debugfs_regset32 *regset);
#endif #endif
...@@ -157,11 +157,6 @@ struct sec_ctx { ...@@ -157,11 +157,6 @@ struct sec_ctx {
struct device *dev; struct device *dev;
}; };
enum sec_endian {
SEC_LE = 0,
SEC_32BE,
SEC_64BE
};
enum sec_debug_file_index { enum sec_debug_file_index {
SEC_CLEAR_ENABLE, SEC_CLEAR_ENABLE,
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/pm_runtime.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/topology.h> #include <linux/topology.h>
#include <linux/uacce.h> #include <linux/uacce.h>
...@@ -57,10 +58,16 @@ ...@@ -57,10 +58,16 @@
#define SEC_MEM_START_INIT_REG 0x301100 #define SEC_MEM_START_INIT_REG 0x301100
#define SEC_MEM_INIT_DONE_REG 0x301104 #define SEC_MEM_INIT_DONE_REG 0x301104
/* clock gating */
#define SEC_CONTROL_REG 0x301200 #define SEC_CONTROL_REG 0x301200
#define SEC_TRNG_EN_SHIFT 8 #define SEC_DYNAMIC_GATE_REG 0x30121c
#define SEC_CORE_AUTO_GATE 0x30212c
#define SEC_DYNAMIC_GATE_EN 0x7bff
#define SEC_CORE_AUTO_GATE_EN GENMASK(3, 0)
#define SEC_CLK_GATE_ENABLE BIT(3) #define SEC_CLK_GATE_ENABLE BIT(3)
#define SEC_CLK_GATE_DISABLE (~BIT(3)) #define SEC_CLK_GATE_DISABLE (~BIT(3))
#define SEC_TRNG_EN_SHIFT 8
#define SEC_AXI_SHUTDOWN_ENABLE BIT(12) #define SEC_AXI_SHUTDOWN_ENABLE BIT(12)
#define SEC_AXI_SHUTDOWN_DISABLE 0xFFFFEFFF #define SEC_AXI_SHUTDOWN_DISABLE 0xFFFFEFFF
...@@ -312,31 +319,20 @@ static const struct pci_device_id sec_dev_ids[] = { ...@@ -312,31 +319,20 @@ static const struct pci_device_id sec_dev_ids[] = {
}; };
MODULE_DEVICE_TABLE(pci, sec_dev_ids); MODULE_DEVICE_TABLE(pci, sec_dev_ids);
static u8 sec_get_endian(struct hisi_qm *qm) static void sec_set_endian(struct hisi_qm *qm)
{ {
u32 reg; u32 reg;
/*
* As for VF, it is a wrong way to get endian setting by
* reading a register of the engine
*/
if (qm->pdev->is_virtfn) {
dev_err_ratelimited(&qm->pdev->dev,
"cannot access a register in VF!\n");
return SEC_LE;
}
reg = readl_relaxed(qm->io_base + SEC_CONTROL_REG); reg = readl_relaxed(qm->io_base + SEC_CONTROL_REG);
/* BD little endian mode */ reg &= ~(BIT(1) | BIT(0));
if (!(reg & BIT(0))) if (!IS_ENABLED(CONFIG_64BIT))
return SEC_LE; reg |= BIT(1);
/* BD 32-bits big endian mode */
else if (!(reg & BIT(1)))
return SEC_32BE;
/* BD 64-bits big endian mode */ if (!IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN))
else reg |= BIT(0);
return SEC_64BE;
writel_relaxed(reg, qm->io_base + SEC_CONTROL_REG);
} }
static void sec_open_sva_prefetch(struct hisi_qm *qm) static void sec_open_sva_prefetch(struct hisi_qm *qm)
...@@ -378,15 +374,43 @@ static void sec_close_sva_prefetch(struct hisi_qm *qm) ...@@ -378,15 +374,43 @@ static void sec_close_sva_prefetch(struct hisi_qm *qm)
pci_err(qm->pdev, "failed to close sva prefetch\n"); pci_err(qm->pdev, "failed to close sva prefetch\n");
} }
static void sec_enable_clock_gate(struct hisi_qm *qm)
{
u32 val;
if (qm->ver < QM_HW_V3)
return;
val = readl_relaxed(qm->io_base + SEC_CONTROL_REG);
val |= SEC_CLK_GATE_ENABLE;
writel_relaxed(val, qm->io_base + SEC_CONTROL_REG);
val = readl(qm->io_base + SEC_DYNAMIC_GATE_REG);
val |= SEC_DYNAMIC_GATE_EN;
writel(val, qm->io_base + SEC_DYNAMIC_GATE_REG);
val = readl(qm->io_base + SEC_CORE_AUTO_GATE);
val |= SEC_CORE_AUTO_GATE_EN;
writel(val, qm->io_base + SEC_CORE_AUTO_GATE);
}
static void sec_disable_clock_gate(struct hisi_qm *qm)
{
u32 val;
/* Kunpeng920 needs to close clock gating */
val = readl_relaxed(qm->io_base + SEC_CONTROL_REG);
val &= SEC_CLK_GATE_DISABLE;
writel_relaxed(val, qm->io_base + SEC_CONTROL_REG);
}
static int sec_engine_init(struct hisi_qm *qm) static int sec_engine_init(struct hisi_qm *qm)
{ {
int ret; int ret;
u32 reg; u32 reg;
/* disable clock gate control */ /* disable clock gate control before mem init */
reg = readl_relaxed(qm->io_base + SEC_CONTROL_REG); sec_disable_clock_gate(qm);
reg &= SEC_CLK_GATE_DISABLE;
writel_relaxed(reg, qm->io_base + SEC_CONTROL_REG);
writel_relaxed(0x1, qm->io_base + SEC_MEM_START_INIT_REG); writel_relaxed(0x1, qm->io_base + SEC_MEM_START_INIT_REG);
...@@ -429,9 +453,9 @@ static int sec_engine_init(struct hisi_qm *qm) ...@@ -429,9 +453,9 @@ static int sec_engine_init(struct hisi_qm *qm)
qm->io_base + SEC_BD_ERR_CHK_EN_REG3); qm->io_base + SEC_BD_ERR_CHK_EN_REG3);
/* config endian */ /* config endian */
reg = readl_relaxed(qm->io_base + SEC_CONTROL_REG); sec_set_endian(qm);
reg |= sec_get_endian(qm);
writel_relaxed(reg, qm->io_base + SEC_CONTROL_REG); sec_enable_clock_gate(qm);
return 0; return 0;
} }
...@@ -533,17 +557,14 @@ static void sec_hw_error_disable(struct hisi_qm *qm) ...@@ -533,17 +557,14 @@ static void sec_hw_error_disable(struct hisi_qm *qm)
writel(SEC_RAS_DISABLE, qm->io_base + SEC_RAS_NFE_REG); writel(SEC_RAS_DISABLE, qm->io_base + SEC_RAS_NFE_REG);
} }
static u32 sec_clear_enable_read(struct sec_debug_file *file) static u32 sec_clear_enable_read(struct hisi_qm *qm)
{ {
struct hisi_qm *qm = file->qm;
return readl(qm->io_base + SEC_CTRL_CNT_CLR_CE) & return readl(qm->io_base + SEC_CTRL_CNT_CLR_CE) &
SEC_CTRL_CNT_CLR_CE_BIT; SEC_CTRL_CNT_CLR_CE_BIT;
} }
static int sec_clear_enable_write(struct sec_debug_file *file, u32 val) static int sec_clear_enable_write(struct hisi_qm *qm, u32 val)
{ {
struct hisi_qm *qm = file->qm;
u32 tmp; u32 tmp;
if (val != 1 && val) if (val != 1 && val)
...@@ -561,24 +582,34 @@ static ssize_t sec_debug_read(struct file *filp, char __user *buf, ...@@ -561,24 +582,34 @@ static ssize_t sec_debug_read(struct file *filp, char __user *buf,
{ {
struct sec_debug_file *file = filp->private_data; struct sec_debug_file *file = filp->private_data;
char tbuf[SEC_DBGFS_VAL_MAX_LEN]; char tbuf[SEC_DBGFS_VAL_MAX_LEN];
struct hisi_qm *qm = file->qm;
u32 val; u32 val;
int ret; int ret;
ret = hisi_qm_get_dfx_access(qm);
if (ret)
return ret;
spin_lock_irq(&file->lock); spin_lock_irq(&file->lock);
switch (file->index) { switch (file->index) {
case SEC_CLEAR_ENABLE: case SEC_CLEAR_ENABLE:
val = sec_clear_enable_read(file); val = sec_clear_enable_read(qm);
break; break;
default: default:
spin_unlock_irq(&file->lock); goto err_input;
return -EINVAL;
} }
spin_unlock_irq(&file->lock); spin_unlock_irq(&file->lock);
ret = snprintf(tbuf, SEC_DBGFS_VAL_MAX_LEN, "%u\n", val);
hisi_qm_put_dfx_access(qm);
ret = snprintf(tbuf, SEC_DBGFS_VAL_MAX_LEN, "%u\n", val);
return simple_read_from_buffer(buf, count, pos, tbuf, ret); return simple_read_from_buffer(buf, count, pos, tbuf, ret);
err_input:
spin_unlock_irq(&file->lock);
hisi_qm_put_dfx_access(qm);
return -EINVAL;
} }
static ssize_t sec_debug_write(struct file *filp, const char __user *buf, static ssize_t sec_debug_write(struct file *filp, const char __user *buf,
...@@ -586,6 +617,7 @@ static ssize_t sec_debug_write(struct file *filp, const char __user *buf, ...@@ -586,6 +617,7 @@ static ssize_t sec_debug_write(struct file *filp, const char __user *buf,
{ {
struct sec_debug_file *file = filp->private_data; struct sec_debug_file *file = filp->private_data;
char tbuf[SEC_DBGFS_VAL_MAX_LEN]; char tbuf[SEC_DBGFS_VAL_MAX_LEN];
struct hisi_qm *qm = file->qm;
unsigned long val; unsigned long val;
int len, ret; int len, ret;
...@@ -604,11 +636,15 @@ static ssize_t sec_debug_write(struct file *filp, const char __user *buf, ...@@ -604,11 +636,15 @@ static ssize_t sec_debug_write(struct file *filp, const char __user *buf,
if (kstrtoul(tbuf, 0, &val)) if (kstrtoul(tbuf, 0, &val))
return -EFAULT; return -EFAULT;
ret = hisi_qm_get_dfx_access(qm);
if (ret)
return ret;
spin_lock_irq(&file->lock); spin_lock_irq(&file->lock);
switch (file->index) { switch (file->index) {
case SEC_CLEAR_ENABLE: case SEC_CLEAR_ENABLE:
ret = sec_clear_enable_write(file, val); ret = sec_clear_enable_write(qm, val);
if (ret) if (ret)
goto err_input; goto err_input;
break; break;
...@@ -617,12 +653,11 @@ static ssize_t sec_debug_write(struct file *filp, const char __user *buf, ...@@ -617,12 +653,11 @@ static ssize_t sec_debug_write(struct file *filp, const char __user *buf,
goto err_input; goto err_input;
} }
spin_unlock_irq(&file->lock); ret = count;
return count;
err_input: err_input:
spin_unlock_irq(&file->lock); spin_unlock_irq(&file->lock);
hisi_qm_put_dfx_access(qm);
return ret; return ret;
} }
...@@ -653,6 +688,15 @@ static int sec_debugfs_atomic64_set(void *data, u64 val) ...@@ -653,6 +688,15 @@ static int sec_debugfs_atomic64_set(void *data, u64 val)
DEFINE_DEBUGFS_ATTRIBUTE(sec_atomic64_ops, sec_debugfs_atomic64_get, DEFINE_DEBUGFS_ATTRIBUTE(sec_atomic64_ops, sec_debugfs_atomic64_get,
sec_debugfs_atomic64_set, "%lld\n"); sec_debugfs_atomic64_set, "%lld\n");
static int sec_regs_show(struct seq_file *s, void *unused)
{
hisi_qm_regs_dump(s, s->private);
return 0;
}
DEFINE_SHOW_ATTRIBUTE(sec_regs);
static int sec_core_debug_init(struct hisi_qm *qm) static int sec_core_debug_init(struct hisi_qm *qm)
{ {
struct sec_dev *sec = container_of(qm, struct sec_dev, qm); struct sec_dev *sec = container_of(qm, struct sec_dev, qm);
...@@ -671,9 +715,10 @@ static int sec_core_debug_init(struct hisi_qm *qm) ...@@ -671,9 +715,10 @@ static int sec_core_debug_init(struct hisi_qm *qm)
regset->regs = sec_dfx_regs; regset->regs = sec_dfx_regs;
regset->nregs = ARRAY_SIZE(sec_dfx_regs); regset->nregs = ARRAY_SIZE(sec_dfx_regs);
regset->base = qm->io_base; regset->base = qm->io_base;
regset->dev = dev;
if (qm->pdev->device == SEC_PF_PCI_DEVICE_ID) if (qm->pdev->device == SEC_PF_PCI_DEVICE_ID)
debugfs_create_regset32("regs", 0444, tmp_d, regset); debugfs_create_file("regs", 0444, tmp_d, regset, &sec_regs_fops);
for (i = 0; i < ARRAY_SIZE(sec_dfx_labels); i++) { for (i = 0; i < ARRAY_SIZE(sec_dfx_labels); i++) {
atomic64_t *data = (atomic64_t *)((uintptr_t)dfx + atomic64_t *data = (atomic64_t *)((uintptr_t)dfx +
...@@ -981,10 +1026,13 @@ static int sec_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -981,10 +1026,13 @@ static int sec_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_alg_unregister; goto err_alg_unregister;
} }
hisi_qm_pm_init(qm);
return 0; return 0;
err_alg_unregister: err_alg_unregister:
hisi_qm_alg_unregister(qm, &sec_devices); if (qm->qp_num >= ctx_q_num)
hisi_qm_alg_unregister(qm, &sec_devices);
err_qm_stop: err_qm_stop:
sec_debugfs_exit(qm); sec_debugfs_exit(qm);
hisi_qm_stop(qm, QM_NORMAL); hisi_qm_stop(qm, QM_NORMAL);
...@@ -999,6 +1047,7 @@ static void sec_remove(struct pci_dev *pdev) ...@@ -999,6 +1047,7 @@ static void sec_remove(struct pci_dev *pdev)
{ {
struct hisi_qm *qm = pci_get_drvdata(pdev); struct hisi_qm *qm = pci_get_drvdata(pdev);
hisi_qm_pm_uninit(qm);
hisi_qm_wait_task_finish(qm, &sec_devices); hisi_qm_wait_task_finish(qm, &sec_devices);
if (qm->qp_num >= ctx_q_num) if (qm->qp_num >= ctx_q_num)
hisi_qm_alg_unregister(qm, &sec_devices); hisi_qm_alg_unregister(qm, &sec_devices);
...@@ -1018,6 +1067,10 @@ static void sec_remove(struct pci_dev *pdev) ...@@ -1018,6 +1067,10 @@ static void sec_remove(struct pci_dev *pdev)
sec_qm_uninit(qm); sec_qm_uninit(qm);
} }
static const struct dev_pm_ops sec_pm_ops = {
SET_RUNTIME_PM_OPS(hisi_qm_suspend, hisi_qm_resume, NULL)
};
static const struct pci_error_handlers sec_err_handler = { static const struct pci_error_handlers sec_err_handler = {
.error_detected = hisi_qm_dev_err_detected, .error_detected = hisi_qm_dev_err_detected,
.slot_reset = hisi_qm_dev_slot_reset, .slot_reset = hisi_qm_dev_slot_reset,
...@@ -1033,6 +1086,7 @@ static struct pci_driver sec_pci_driver = { ...@@ -1033,6 +1086,7 @@ static struct pci_driver sec_pci_driver = {
.err_handler = &sec_err_handler, .err_handler = &sec_err_handler,
.sriov_configure = hisi_qm_sriov_configure, .sriov_configure = hisi_qm_sriov_configure,
.shutdown = hisi_qm_dev_shutdown, .shutdown = hisi_qm_dev_shutdown,
.driver.pm = &sec_pm_ops,
}; };
static void sec_register_debugfs(void) static void sec_register_debugfs(void)
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/pm_runtime.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/topology.h> #include <linux/topology.h>
#include <linux/uacce.h> #include <linux/uacce.h>
...@@ -107,6 +108,14 @@ ...@@ -107,6 +108,14 @@
#define HZIP_DELAY_1_US 1 #define HZIP_DELAY_1_US 1
#define HZIP_POLL_TIMEOUT_US 1000 #define HZIP_POLL_TIMEOUT_US 1000
/* clock gating */
#define HZIP_PEH_CFG_AUTO_GATE 0x3011A8
#define HZIP_PEH_CFG_AUTO_GATE_EN BIT(0)
#define HZIP_CORE_GATED_EN GENMASK(15, 8)
#define HZIP_CORE_GATED_OOO_EN BIT(29)
#define HZIP_CLOCK_GATED_EN (HZIP_CORE_GATED_EN | \
HZIP_CORE_GATED_OOO_EN)
static const char hisi_zip_name[] = "hisi_zip"; static const char hisi_zip_name[] = "hisi_zip";
static struct dentry *hzip_debugfs_root; static struct dentry *hzip_debugfs_root;
...@@ -312,6 +321,22 @@ static void hisi_zip_close_sva_prefetch(struct hisi_qm *qm) ...@@ -312,6 +321,22 @@ static void hisi_zip_close_sva_prefetch(struct hisi_qm *qm)
pci_err(qm->pdev, "failed to close sva prefetch\n"); pci_err(qm->pdev, "failed to close sva prefetch\n");
} }
static void hisi_zip_enable_clock_gate(struct hisi_qm *qm)
{
u32 val;
if (qm->ver < QM_HW_V3)
return;
val = readl(qm->io_base + HZIP_CLOCK_GATE_CTRL);
val |= HZIP_CLOCK_GATED_EN;
writel(val, qm->io_base + HZIP_CLOCK_GATE_CTRL);
val = readl(qm->io_base + HZIP_PEH_CFG_AUTO_GATE);
val |= HZIP_PEH_CFG_AUTO_GATE_EN;
writel(val, qm->io_base + HZIP_PEH_CFG_AUTO_GATE);
}
static int hisi_zip_set_user_domain_and_cache(struct hisi_qm *qm) static int hisi_zip_set_user_domain_and_cache(struct hisi_qm *qm)
{ {
void __iomem *base = qm->io_base; void __iomem *base = qm->io_base;
...@@ -359,6 +384,8 @@ static int hisi_zip_set_user_domain_and_cache(struct hisi_qm *qm) ...@@ -359,6 +384,8 @@ static int hisi_zip_set_user_domain_and_cache(struct hisi_qm *qm)
CQC_CACHE_WB_ENABLE | FIELD_PREP(SQC_CACHE_WB_THRD, 1) | CQC_CACHE_WB_ENABLE | FIELD_PREP(SQC_CACHE_WB_THRD, 1) |
FIELD_PREP(CQC_CACHE_WB_THRD, 1), base + QM_CACHE_CTL); FIELD_PREP(CQC_CACHE_WB_THRD, 1), base + QM_CACHE_CTL);
hisi_zip_enable_clock_gate(qm);
return 0; return 0;
} }
...@@ -423,17 +450,14 @@ static inline struct hisi_qm *file_to_qm(struct ctrl_debug_file *file) ...@@ -423,17 +450,14 @@ static inline struct hisi_qm *file_to_qm(struct ctrl_debug_file *file)
return &hisi_zip->qm; return &hisi_zip->qm;
} }
static u32 clear_enable_read(struct ctrl_debug_file *file) static u32 clear_enable_read(struct hisi_qm *qm)
{ {
struct hisi_qm *qm = file_to_qm(file);
return readl(qm->io_base + HZIP_SOFT_CTRL_CNT_CLR_CE) & return readl(qm->io_base + HZIP_SOFT_CTRL_CNT_CLR_CE) &
HZIP_SOFT_CTRL_CNT_CLR_CE_BIT; HZIP_SOFT_CTRL_CNT_CLR_CE_BIT;
} }
static int clear_enable_write(struct ctrl_debug_file *file, u32 val) static int clear_enable_write(struct hisi_qm *qm, u32 val)
{ {
struct hisi_qm *qm = file_to_qm(file);
u32 tmp; u32 tmp;
if (val != 1 && val != 0) if (val != 1 && val != 0)
...@@ -450,22 +474,33 @@ static ssize_t hisi_zip_ctrl_debug_read(struct file *filp, char __user *buf, ...@@ -450,22 +474,33 @@ static ssize_t hisi_zip_ctrl_debug_read(struct file *filp, char __user *buf,
size_t count, loff_t *pos) size_t count, loff_t *pos)
{ {
struct ctrl_debug_file *file = filp->private_data; struct ctrl_debug_file *file = filp->private_data;
struct hisi_qm *qm = file_to_qm(file);
char tbuf[HZIP_BUF_SIZE]; char tbuf[HZIP_BUF_SIZE];
u32 val; u32 val;
int ret; int ret;
ret = hisi_qm_get_dfx_access(qm);
if (ret)
return ret;
spin_lock_irq(&file->lock); spin_lock_irq(&file->lock);
switch (file->index) { switch (file->index) {
case HZIP_CLEAR_ENABLE: case HZIP_CLEAR_ENABLE:
val = clear_enable_read(file); val = clear_enable_read(qm);
break; break;
default: default:
spin_unlock_irq(&file->lock); goto err_input;
return -EINVAL;
} }
spin_unlock_irq(&file->lock); spin_unlock_irq(&file->lock);
hisi_qm_put_dfx_access(qm);
ret = scnprintf(tbuf, sizeof(tbuf), "%u\n", val); ret = scnprintf(tbuf, sizeof(tbuf), "%u\n", val);
return simple_read_from_buffer(buf, count, pos, tbuf, ret); return simple_read_from_buffer(buf, count, pos, tbuf, ret);
err_input:
spin_unlock_irq(&file->lock);
hisi_qm_put_dfx_access(qm);
return -EINVAL;
} }
static ssize_t hisi_zip_ctrl_debug_write(struct file *filp, static ssize_t hisi_zip_ctrl_debug_write(struct file *filp,
...@@ -473,6 +508,7 @@ static ssize_t hisi_zip_ctrl_debug_write(struct file *filp, ...@@ -473,6 +508,7 @@ static ssize_t hisi_zip_ctrl_debug_write(struct file *filp,
size_t count, loff_t *pos) size_t count, loff_t *pos)
{ {
struct ctrl_debug_file *file = filp->private_data; struct ctrl_debug_file *file = filp->private_data;
struct hisi_qm *qm = file_to_qm(file);
char tbuf[HZIP_BUF_SIZE]; char tbuf[HZIP_BUF_SIZE];
unsigned long val; unsigned long val;
int len, ret; int len, ret;
...@@ -491,10 +527,14 @@ static ssize_t hisi_zip_ctrl_debug_write(struct file *filp, ...@@ -491,10 +527,14 @@ static ssize_t hisi_zip_ctrl_debug_write(struct file *filp,
if (kstrtoul(tbuf, 0, &val)) if (kstrtoul(tbuf, 0, &val))
return -EFAULT; return -EFAULT;
ret = hisi_qm_get_dfx_access(qm);
if (ret)
return ret;
spin_lock_irq(&file->lock); spin_lock_irq(&file->lock);
switch (file->index) { switch (file->index) {
case HZIP_CLEAR_ENABLE: case HZIP_CLEAR_ENABLE:
ret = clear_enable_write(file, val); ret = clear_enable_write(qm, val);
if (ret) if (ret)
goto err_input; goto err_input;
break; break;
...@@ -502,12 +542,12 @@ static ssize_t hisi_zip_ctrl_debug_write(struct file *filp, ...@@ -502,12 +542,12 @@ static ssize_t hisi_zip_ctrl_debug_write(struct file *filp,
ret = -EINVAL; ret = -EINVAL;
goto err_input; goto err_input;
} }
spin_unlock_irq(&file->lock);
return count; ret = count;
err_input: err_input:
spin_unlock_irq(&file->lock); spin_unlock_irq(&file->lock);
hisi_qm_put_dfx_access(qm);
return ret; return ret;
} }
...@@ -538,6 +578,15 @@ static int zip_debugfs_atomic64_get(void *data, u64 *val) ...@@ -538,6 +578,15 @@ static int zip_debugfs_atomic64_get(void *data, u64 *val)
DEFINE_DEBUGFS_ATTRIBUTE(zip_atomic64_ops, zip_debugfs_atomic64_get, DEFINE_DEBUGFS_ATTRIBUTE(zip_atomic64_ops, zip_debugfs_atomic64_get,
zip_debugfs_atomic64_set, "%llu\n"); zip_debugfs_atomic64_set, "%llu\n");
static int hisi_zip_regs_show(struct seq_file *s, void *unused)
{
hisi_qm_regs_dump(s, s->private);
return 0;
}
DEFINE_SHOW_ATTRIBUTE(hisi_zip_regs);
static int hisi_zip_core_debug_init(struct hisi_qm *qm) static int hisi_zip_core_debug_init(struct hisi_qm *qm)
{ {
struct device *dev = &qm->pdev->dev; struct device *dev = &qm->pdev->dev;
...@@ -560,9 +609,11 @@ static int hisi_zip_core_debug_init(struct hisi_qm *qm) ...@@ -560,9 +609,11 @@ static int hisi_zip_core_debug_init(struct hisi_qm *qm)
regset->regs = hzip_dfx_regs; regset->regs = hzip_dfx_regs;
regset->nregs = ARRAY_SIZE(hzip_dfx_regs); regset->nregs = ARRAY_SIZE(hzip_dfx_regs);
regset->base = qm->io_base + core_offsets[i]; regset->base = qm->io_base + core_offsets[i];
regset->dev = dev;
tmp_d = debugfs_create_dir(buf, qm->debug.debug_root); tmp_d = debugfs_create_dir(buf, qm->debug.debug_root);
debugfs_create_regset32("regs", 0444, tmp_d, regset); debugfs_create_file("regs", 0444, tmp_d, regset,
&hisi_zip_regs_fops);
} }
return 0; return 0;
...@@ -898,6 +949,8 @@ static int hisi_zip_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -898,6 +949,8 @@ static int hisi_zip_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_qm_alg_unregister; goto err_qm_alg_unregister;
} }
hisi_qm_pm_init(qm);
return 0; return 0;
err_qm_alg_unregister: err_qm_alg_unregister:
...@@ -920,6 +973,7 @@ static void hisi_zip_remove(struct pci_dev *pdev) ...@@ -920,6 +973,7 @@ static void hisi_zip_remove(struct pci_dev *pdev)
{ {
struct hisi_qm *qm = pci_get_drvdata(pdev); struct hisi_qm *qm = pci_get_drvdata(pdev);
hisi_qm_pm_uninit(qm);
hisi_qm_wait_task_finish(qm, &zip_devices); hisi_qm_wait_task_finish(qm, &zip_devices);
hisi_qm_alg_unregister(qm, &zip_devices); hisi_qm_alg_unregister(qm, &zip_devices);
...@@ -932,6 +986,10 @@ static void hisi_zip_remove(struct pci_dev *pdev) ...@@ -932,6 +986,10 @@ static void hisi_zip_remove(struct pci_dev *pdev)
hisi_zip_qm_uninit(qm); hisi_zip_qm_uninit(qm);
} }
static const struct dev_pm_ops hisi_zip_pm_ops = {
SET_RUNTIME_PM_OPS(hisi_qm_suspend, hisi_qm_resume, NULL)
};
static const struct pci_error_handlers hisi_zip_err_handler = { static const struct pci_error_handlers hisi_zip_err_handler = {
.error_detected = hisi_qm_dev_err_detected, .error_detected = hisi_qm_dev_err_detected,
.slot_reset = hisi_qm_dev_slot_reset, .slot_reset = hisi_qm_dev_slot_reset,
...@@ -948,6 +1006,7 @@ static struct pci_driver hisi_zip_pci_driver = { ...@@ -948,6 +1006,7 @@ static struct pci_driver hisi_zip_pci_driver = {
hisi_qm_sriov_configure : NULL, hisi_qm_sriov_configure : NULL,
.err_handler = &hisi_zip_err_handler, .err_handler = &hisi_zip_err_handler,
.shutdown = hisi_qm_dev_shutdown, .shutdown = hisi_qm_dev_shutdown,
.driver.pm = &hisi_zip_pm_ops,
}; };
static void hisi_zip_register_debugfs(void) static void hisi_zip_register_debugfs(void)
......
This diff is collapsed.
...@@ -1175,9 +1175,9 @@ static int omap_aes_probe(struct platform_device *pdev) ...@@ -1175,9 +1175,9 @@ static int omap_aes_probe(struct platform_device *pdev)
spin_lock_init(&dd->lock); spin_lock_init(&dd->lock);
INIT_LIST_HEAD(&dd->list); INIT_LIST_HEAD(&dd->list);
spin_lock(&list_lock); spin_lock_bh(&list_lock);
list_add_tail(&dd->list, &dev_list); list_add_tail(&dd->list, &dev_list);
spin_unlock(&list_lock); spin_unlock_bh(&list_lock);
/* Initialize crypto engine */ /* Initialize crypto engine */
dd->engine = crypto_engine_alloc_init(dev, 1); dd->engine = crypto_engine_alloc_init(dev, 1);
...@@ -1264,9 +1264,9 @@ static int omap_aes_remove(struct platform_device *pdev) ...@@ -1264,9 +1264,9 @@ static int omap_aes_remove(struct platform_device *pdev)
if (!dd) if (!dd)
return -ENODEV; return -ENODEV;
spin_lock(&list_lock); spin_lock_bh(&list_lock);
list_del(&dd->list); list_del(&dd->list);
spin_unlock(&list_lock); spin_unlock_bh(&list_lock);
for (i = dd->pdata->algs_info_size - 1; i >= 0; i--) for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--) { for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--) {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment