* [linus:master] [treewide] b04e317b52: INFO:task_blocked_for_more_than#seconds
From: kernel test robot @ 2025-02-12 4:57 UTC (permalink / raw)
To: Frederic Weisbecker
Cc: oe-lkp, lkp, linux-kernel, Dan Carpenter, kvm, linux-crypto,
linux-pm, dri-devel, intel-gfx, linux-arm-msm, freedreno,
linux-media, netdev, intel-wired-lan, chrome-platform, linux-spi,
linux-usb, virtualization, linux-watchdog, linux-erofs, rcu,
oliver.sang
Hello,
we noticed the issue happens with a low rate on this commit, but keeps clean
on parent when we even run the tests up to 999 times. just FYI.
41f70d8e16349c65 b04e317b522630b46f78ee62ecb
---------------- ---------------------------
fail:runs %reproduction fail:runs
| | |
:999 2% 16:999 dmesg.INFO:task_blocked_for_more_than#seconds
:999 2% 16:999 dmesg.Kernel_panic-not_syncing:hung_task:blocked_tasks
kernel test robot noticed "INFO:task_blocked_for_more_than#seconds" on:
commit: b04e317b522630b46f78ee62ecbdc5734e8d43de ("treewide: Introduce kthread_run_worker[_on_cpu]()")
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git master
[test failed on linus/master 7ee983c850b40043ac4751836fbd9a2b4d0c5937]
[test failed on linux-next/master ed58d103e6da15a442ff87567898768dc3a66987]
in testcase: rcuscale
version:
with following parameters:
runtime: 300s
scale_type: rcu
config: i386-randconfig-052-20250205
compiler: gcc-12
test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 16G
(please refer to attached dmesg/kmsg for entire log/backtrace)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <oliver.sang@intel.com>
| Closes: https://lore.kernel.org/oe-lkp/202502121025.55bfa801-lkp@intel.com
[ 1023.501569][ T32] INFO: task UVCG:82 blocked for more than 491 seconds.
[ 1023.510932][ T32] Tainted: G T 6.13.0-rc2-00014-gb04e317b5226 #1
[ 1023.528506][ T32] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[ 1023.551252][ T32] task:UVCG state:D stack:0 pid:82 tgid:82 ppid:2 flags:0x00004000
[ 1023.582336][ T32] Call Trace:
[ 1023.599286][ T32] __schedule (kernel/sched/core.c:5372 kernel/sched/core.c:6756)
[ 1023.617204][ T32] ? __this_cpu_preempt_check (lib/smp_processor_id.c:67)
[ 1023.637326][ T32] schedule (kernel/sched/core.c:6834 kernel/sched/core.c:6848)
[ 1023.653175][ T32] schedule_preempt_disabled (kernel/sched/core.c:6906)
[ 1023.672095][ T32] kthread (kernel/kthread.c:453)
[ 1023.684220][ T32] ? kthread_flush_work (kernel/kthread.c:970)
[ 1023.700611][ T32] ? kthread_is_per_cpu (kernel/kthread.c:413)
[ 1023.716756][ T32] ret_from_fork (arch/x86/kernel/process.c:153)
[ 1023.732758][ T32] ? kthread_is_per_cpu (kernel/kthread.c:413)
[ 1023.748605][ T32] ret_from_fork_asm (arch/x86/entry/entry_32.S:737)
[ 1023.764004][ T32] entry_INT80_32 (arch/x86/entry/entry_32.S:942)
[ 1023.776959][ T32]
[ 1023.776959][ T32] Showing all locks held in the system:
[ 1023.803410][ T32] 1 lock held by khungtaskd/32:
[ 1023.815913][ T32] #0: c3baa3d4 (rcu_read_lock){....}-{1:3}, at: rcu_lock_acquire (include/linux/rcupdate.h:336)
[ 1023.842061][ T32] 1 lock held by in:imklog/227:
[ 1023.849815][ T32] #0: ecd0e884 (&f->f_pos_lock){+.+.}-{4:4}, at: fdget_pos (fs/file.c:1194)
[ 1023.877481][ T32] 1 lock held by dmesg/494:
[ 1023.885260][ T32] 2 locks held by depmod/567:
[ 1023.903871][ T32]
[ 1023.907007][ T32] =============================================
[ 1023.907007][ T32]
[ 1023.938278][ T32] Kernel panic - not syncing: hung_task: blocked tasks
[ 1023.951013][ T32] CPU: 0 UID: 0 PID: 32 Comm: khungtaskd Tainted: G T 6.13.0-rc2-00014-gb04e317b5226 #1 78ab3595737b7bb7ccfbfed5c1dcb65e25af99a7
[ 1023.973770][ T32] Tainted: [T]=RANDSTRUCT
[ 1023.979010][ T32] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
[ 1023.991787][ T32] Call Trace:
[ 1023.995862][ T32] dump_stack_lvl (lib/dump_stack.c:122)
[ 1024.001535][ T32] dump_stack (lib/dump_stack.c:130)
[ 1024.006622][ T32] panic (kernel/panic.c:258 kernel/panic.c:375)
[ 1024.011360][ T32] check_hung_uninterruptible_tasks (kernel/hung_task.c:239)
[ 1024.018678][ T32] watchdog (kernel/hung_task.c:398)
[ 1024.023798][ T32] kthread (kernel/kthread.c:466)
[ 1024.028697][ T32] ? check_hung_uninterruptible_tasks (kernel/hung_task.c:380)
[ 1024.036601][ T32] ? kthread_is_per_cpu (kernel/kthread.c:413)
[ 1024.042763][ T32] ret_from_fork (arch/x86/kernel/process.c:153)
[ 1024.048431][ T32] ? kthread_is_per_cpu (kernel/kthread.c:413)
[ 1024.054588][ T32] ret_from_fork_asm (arch/x86/entry/entry_32.S:737)
[ 1024.060422][ T32] entry_INT80_32 (arch/x86/entry/entry_32.S:942)
[ 1024.067908][ T32] Kernel Offset: disabled
The kernel config and materials to reproduce are available at:
https://download.01.org/0day-ci/archive/20250212/202502121025.55bfa801-lkp@intel.com
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* [PATCH] crypto: lib/Kconfig - Fix lib built-in failure when arch is modular
From: Herbert Xu @ 2025-02-12 4:48 UTC (permalink / raw)
To: kernel test robot
Cc: Danny Tsen, oe-kbuild-all, linux-kernel, Ard Biesheuvel,
Linux Crypto Mailing List
In-Reply-To: <202501230223.ikroNDr1-lkp@intel.com>
On Thu, Jan 23, 2025 at 02:18:27AM +0800, kernel test robot wrote:
> tree: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
> head: c4b9570cfb63501638db720f3bee9f6dfd044b82
> commit: b42519dbba838c928e82b55f32712fbe3eed2c45 crypto: ppc/curve25519 - Update Kconfig and Makefile for ppc64le
> date: 8 months ago
> config: powerpc64-randconfig-r111-20250122 (https://download.01.org/0day-ci/archive/20250123/202501230223.ikroNDr1-lkp@intel.com/config)
> compiler: clang version 15.0.7 (https://github.com/llvm/llvm-project 8dfdcc7b7bf66834a761bd8de445840ef68e4d1a)
> reproduce: (https://download.01.org/0day-ci/archive/20250123/202501230223.ikroNDr1-lkp@intel.com/reproduce)
Thanks for the report. This is the old built-in vs. modular Kconfig
problem. This patch should fix it:
---8<---
The HAVE_ARCH Kconfig options in lib/crypto try to solve the
modular versus built-in problem, but it still fails when the
the LIB option (e.g., CRYPTO_LIB_CURVE25519) is selected externally.
Fix this by introducing a level of indirection with ARCH_MAY_HAVE
Kconfig options, these then go on to select the ARCH_HAVE options
if the ARCH Kconfig options matches that of the LIB option.
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202501230223.ikroNDr1-lkp@intel.com/
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
diff --git a/arch/arm/crypto/Kconfig b/arch/arm/crypto/Kconfig
index 32650c8431d9..47d9cc59f254 100644
--- a/arch/arm/crypto/Kconfig
+++ b/arch/arm/crypto/Kconfig
@@ -6,7 +6,7 @@ config CRYPTO_CURVE25519_NEON
tristate "Public key crypto: Curve25519 (NEON)"
depends on KERNEL_MODE_NEON
select CRYPTO_LIB_CURVE25519_GENERIC
- select CRYPTO_ARCH_HAVE_LIB_CURVE25519
+ select CRYPTO_ARCH_MAY_HAVE_LIB_CURVE25519
help
Curve25519 algorithm
@@ -47,7 +47,7 @@ config CRYPTO_NHPOLY1305_NEON
config CRYPTO_POLY1305_ARM
tristate "Hash functions: Poly1305 (NEON)"
select CRYPTO_HASH
- select CRYPTO_ARCH_HAVE_LIB_POLY1305
+ select CRYPTO_ARCH_MAY_HAVE_LIB_POLY1305
help
Poly1305 authenticator algorithm (RFC7539)
@@ -214,7 +214,7 @@ config CRYPTO_AES_ARM_CE
config CRYPTO_CHACHA20_NEON
tristate "Ciphers: ChaCha20, XChaCha20, XChaCha12 (NEON)"
select CRYPTO_SKCIPHER
- select CRYPTO_ARCH_HAVE_LIB_CHACHA
+ select CRYPTO_ARCH_MAY_HAVE_LIB_CHACHA
help
Length-preserving ciphers: ChaCha20, XChaCha20, and XChaCha12
stream cipher algorithms
diff --git a/arch/powerpc/crypto/Kconfig b/arch/powerpc/crypto/Kconfig
index 5b315e9756b3..e453cb0c82d2 100644
--- a/arch/powerpc/crypto/Kconfig
+++ b/arch/powerpc/crypto/Kconfig
@@ -6,7 +6,7 @@ config CRYPTO_CURVE25519_PPC64
tristate "Public key crypto: Curve25519 (PowerPC64)"
depends on PPC64 && CPU_LITTLE_ENDIAN
select CRYPTO_LIB_CURVE25519_GENERIC
- select CRYPTO_ARCH_HAVE_LIB_CURVE25519
+ select CRYPTO_ARCH_MAY_HAVE_LIB_CURVE25519
help
Curve25519 algorithm
@@ -95,7 +95,7 @@ config CRYPTO_CHACHA20_P10
depends on PPC64 && CPU_LITTLE_ENDIAN && VSX
select CRYPTO_SKCIPHER
select CRYPTO_LIB_CHACHA_GENERIC
- select CRYPTO_ARCH_HAVE_LIB_CHACHA
+ select CRYPTO_ARCH_MAY_HAVE_LIB_CHACHA
help
Length-preserving ciphers: ChaCha20, XChaCha20, and XChaCha12
stream cipher algorithms
diff --git a/arch/x86/crypto/Kconfig b/arch/x86/crypto/Kconfig
index 4757bf922075..c189dad0969b 100644
--- a/arch/x86/crypto/Kconfig
+++ b/arch/x86/crypto/Kconfig
@@ -6,7 +6,7 @@ config CRYPTO_CURVE25519_X86
tristate "Public key crypto: Curve25519 (ADX)"
depends on X86 && 64BIT
select CRYPTO_LIB_CURVE25519_GENERIC
- select CRYPTO_ARCH_HAVE_LIB_CURVE25519
+ select CRYPTO_ARCH_MAY_HAVE_LIB_CURVE25519
help
Curve25519 algorithm
@@ -352,7 +352,7 @@ config CRYPTO_CHACHA20_X86_64
depends on X86 && 64BIT
select CRYPTO_SKCIPHER
select CRYPTO_LIB_CHACHA_GENERIC
- select CRYPTO_ARCH_HAVE_LIB_CHACHA
+ select CRYPTO_ARCH_MAY_HAVE_LIB_CHACHA
help
Length-preserving ciphers: ChaCha20, XChaCha20, and XChaCha12
stream cipher algorithms
@@ -420,7 +420,7 @@ config CRYPTO_POLY1305_X86_64
tristate "Hash functions: Poly1305 (SSE2/AVX2)"
depends on X86 && 64BIT
select CRYPTO_LIB_POLY1305_GENERIC
- select CRYPTO_ARCH_HAVE_LIB_POLY1305
+ select CRYPTO_ARCH_MAY_HAVE_LIB_POLY1305
help
Poly1305 authenticator algorithm (RFC7539)
diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig
index b01253cac70a..c542ef1d64d0 100644
--- a/lib/crypto/Kconfig
+++ b/lib/crypto/Kconfig
@@ -42,12 +42,17 @@ config CRYPTO_LIB_BLAKE2S_GENERIC
of CRYPTO_LIB_BLAKE2S.
config CRYPTO_ARCH_HAVE_LIB_CHACHA
- tristate
+ bool
help
Declares whether the architecture provides an arch-specific
accelerated implementation of the ChaCha library interface,
either builtin or as a module.
+config CRYPTO_ARCH_MAY_HAVE_LIB_CHACHA
+ tristate
+ select CRYPTO_ARCH_HAVE_LIB_CHACHA if CRYPTO_LIB_CHACHA=m
+ select CRYPTO_ARCH_HAVE_LIB_CHACHA if CRYPTO_ARCH_MAY_HAVE_LIB_CHACHA=y
+
config CRYPTO_LIB_CHACHA_GENERIC
tristate
select CRYPTO_LIB_UTILS
@@ -60,7 +65,6 @@ config CRYPTO_LIB_CHACHA_GENERIC
config CRYPTO_LIB_CHACHA
tristate "ChaCha library interface"
- depends on CRYPTO_ARCH_HAVE_LIB_CHACHA || !CRYPTO_ARCH_HAVE_LIB_CHACHA
select CRYPTO_LIB_CHACHA_GENERIC if CRYPTO_ARCH_HAVE_LIB_CHACHA=n
help
Enable the ChaCha library interface. This interface may be fulfilled
@@ -68,12 +72,17 @@ config CRYPTO_LIB_CHACHA
is available and enabled.
config CRYPTO_ARCH_HAVE_LIB_CURVE25519
- tristate
+ bool
help
Declares whether the architecture provides an arch-specific
accelerated implementation of the Curve25519 library interface,
either builtin or as a module.
+config CRYPTO_ARCH_MAY_HAVE_LIB_CURVE25519
+ tristate
+ select CRYPTO_ARCH_HAVE_LIB_CURVE25519 if CRYPTO_LIB_CURVE25519=m
+ select CRYPTO_ARCH_HAVE_LIB_CURVE25519 if CRYPTO_ARCH_MAY_HAVE_LIB_CURVE25519=y
+
config CRYPTO_LIB_CURVE25519_GENERIC
tristate
help
@@ -85,7 +94,6 @@ config CRYPTO_LIB_CURVE25519_GENERIC
config CRYPTO_LIB_CURVE25519
tristate "Curve25519 scalar multiplication library"
- depends on CRYPTO_ARCH_HAVE_LIB_CURVE25519 || !CRYPTO_ARCH_HAVE_LIB_CURVE25519
select CRYPTO_LIB_CURVE25519_GENERIC if CRYPTO_ARCH_HAVE_LIB_CURVE25519=n
select CRYPTO_LIB_UTILS
help
@@ -104,12 +112,17 @@ config CRYPTO_LIB_POLY1305_RSIZE
default 1
config CRYPTO_ARCH_HAVE_LIB_POLY1305
- tristate
+ bool
help
Declares whether the architecture provides an arch-specific
accelerated implementation of the Poly1305 library interface,
either builtin or as a module.
+config CRYPTO_ARCH_MAY_HAVE_LIB_POLY1305
+ tristate
+ select CRYPTO_ARCH_HAVE_LIB_POLY1305 if CRYPTO_LIB_POLY1305=m
+ select CRYPTO_ARCH_HAVE_LIB_POLY1305 if CRYPTO_ARCH_MAY_HAVE_LIB_POLY1305=y
+
config CRYPTO_LIB_POLY1305_GENERIC
tristate
help
@@ -121,7 +134,6 @@ config CRYPTO_LIB_POLY1305_GENERIC
config CRYPTO_LIB_POLY1305
tristate "Poly1305 library interface"
- depends on CRYPTO_ARCH_HAVE_LIB_POLY1305 || !CRYPTO_ARCH_HAVE_LIB_POLY1305
select CRYPTO_LIB_POLY1305_GENERIC if CRYPTO_ARCH_HAVE_LIB_POLY1305=n
help
Enable the Poly1305 library interface. This interface may be fulfilled
@@ -130,8 +142,6 @@ config CRYPTO_LIB_POLY1305
config CRYPTO_LIB_CHACHA20POLY1305
tristate "ChaCha20-Poly1305 AEAD support (8-byte nonce library version)"
- depends on CRYPTO_ARCH_HAVE_LIB_CHACHA || !CRYPTO_ARCH_HAVE_LIB_CHACHA
- depends on CRYPTO_ARCH_HAVE_LIB_POLY1305 || !CRYPTO_ARCH_HAVE_LIB_POLY1305
depends on CRYPTO
select CRYPTO_LIB_CHACHA
select CRYPTO_LIB_POLY1305
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply related
* Re: [PATCH v11 11/22] crypto: amlogic - Introduce hasher
From: Herbert Xu @ 2025-02-12 3:51 UTC (permalink / raw)
To: Alexey Romanov
Cc: clabbe, conor+dt, davem, devicetree, jbrunet, kernel, khilman,
krzk+dt, krzysztof.kozlowski+dt, linux-amlogic, linux-arm-kernel,
linux-crypto, linux-kernel, martin.blumenstingl, neil.armstrong,
robh+dt, vadim.fedorenko
In-Reply-To: <Z2aokzSrAHpJE_PG@gondor.apana.org.au>
On Wed, Jan 22, 2025 at 03:41:29PM +0300, Alexey Romanov wrote:
>
> Why? I couldn't find this explanation anywhere.
Because the digest function can be called from atomic contexts,
such as networking.
> In addition, I found an example of one of the digest functions that is sleeping [1].
>
> Links:
>
> - [1] https://elixir.bootlin.com/linux/v6.12.6/source/drivers/crypto/mxs-dcp.c#L804
That driver is just broken. If you look through the git history,
you'll find that a similar problem was fixed by replacing the
mutex with a spinlock in the cipher path. Unfortunately the same
fix hasn't been extended to hashing in mxs-dcp.
Cheeers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: [PATCH v10 2/5] s390/crypto: New s390 specific protected key hash phmac
From: Eric Biggers @ 2025-02-12 3:32 UTC (permalink / raw)
To: Herbert Xu; +Cc: Harald Freudenberger, linux-s390, linux-crypto, davem, dengler
In-Reply-To: <Z6wUO-8wPTyzF5SK@gondor.apana.org.au>
On Wed, Feb 12, 2025 at 11:23:39AM +0800, Herbert Xu wrote:
> On Wed, Feb 12, 2025 at 11:19:40AM +0800, Herbert Xu wrote:
> >
> > Don't worry about this. It can easily be reverted once a patch
> > using it is submitted.
>
> I just reverted it in cryptodev.
>
Nacked-by: Eric Biggers <ebiggers@kernel.org>
- Eric
^ permalink raw reply
* [PATCH v2 3/3] tpm: Add a driver for Loongson TPM device
From: Qunqin Zhao @ 2025-02-12 3:31 UTC (permalink / raw)
To: lee, herbert, davem, peterhuewe, jarkko
Cc: linux-kernel, loongarch, linux-crypto, jgg, linux-integrity,
Qunqin Zhao, Yinggang Gu
In-Reply-To: <20250212033113.15137-1-zhaoqunqin@loongson.cn>
TPM2.0 is implemented in Loongson security engine. This is the driver
for it.
Co-developed-by: Yinggang Gu <guyinggang@loongson.cn>
Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
Signed-off-by: Qunqin Zhao <zhaoqunqin@loongson.cn>
---
MAINTAINERS | 1 +
drivers/char/tpm/Kconfig | 9 ++++
drivers/char/tpm/Makefile | 1 +
drivers/char/tpm/tpm_lsse.c | 104 ++++++++++++++++++++++++++++++++++++
4 files changed, 115 insertions(+)
create mode 100644 drivers/char/tpm/tpm_lsse.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 6493d58436..6aad0f08ad 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13484,6 +13484,7 @@ LOONGSON CRYPTO DRIVER
M: Qunqin Zhao <zhaoqunqin@loongson.com>
L: linux-crypto@vger.kernel.org
S: Maintained
+F: drivers/char/tpm/tpm_lsse.c
F: drivers/crypto/loongson/
LOONGSON-2 APB DMA DRIVER
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index 0fc9a510e0..56d0417065 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -225,5 +225,14 @@ config TCG_FTPM_TEE
help
This driver proxies for firmware TPM running in TEE.
+config TCG_LSSE
+ tristate "Loongson TPM Interface"
+ depends on MFD_LS6000SE
+ help
+ If you want to make Loongson TPM support available, say Yes and
+ it will be accessible from within Linux. To compile this
+ driver as a module, choose M here; the module will be called
+ tpm_lsse.
+
source "drivers/char/tpm/st33zp24/Kconfig"
endif # TCG_TPM
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 9bb142c752..bf2280352d 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -44,3 +44,4 @@ obj-$(CONFIG_TCG_XEN) += xen-tpmfront.o
obj-$(CONFIG_TCG_CRB) += tpm_crb.o
obj-$(CONFIG_TCG_VTPM_PROXY) += tpm_vtpm_proxy.o
obj-$(CONFIG_TCG_FTPM_TEE) += tpm_ftpm_tee.o
+obj-$(CONFIG_TCG_LSSE) += tpm_lsse.o
diff --git a/drivers/char/tpm/tpm_lsse.c b/drivers/char/tpm/tpm_lsse.c
new file mode 100644
index 0000000000..3fd2d9bac8
--- /dev/null
+++ b/drivers/char/tpm/tpm_lsse.c
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2025 Loongson Technology Corporation Limited. */
+
+#include <linux/device.h>
+#include <linux/mfd/ls6000se.h>
+#include <linux/platform_device.h>
+#include <linux/wait.h>
+
+#include "tpm.h"
+
+struct tpm_msg {
+ u32 cmd;
+ u32 data_off;
+ u32 data_len;
+ u32 info[5];
+};
+
+struct tpm_dev {
+ struct lsse_ch *se_ch;
+ struct completion tpm_completion;
+};
+
+static void tpm_complete(struct lsse_ch *ch)
+{
+ struct tpm_dev *td = ch->priv;
+
+ complete(&td->tpm_completion);
+}
+
+static int tpm_ls_recv(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+ struct tpm_dev *td = dev_get_drvdata(&chip->dev);
+ struct tpm_msg *rmsg;
+ int sig;
+
+ sig = wait_for_completion_interruptible(&td->tpm_completion);
+ if (sig)
+ return sig;
+
+ rmsg = td->se_ch->rmsg;
+ memcpy(buf, td->se_ch->data_buffer, rmsg->data_len);
+
+ return rmsg->data_len;
+}
+
+static int tpm_ls_send(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+ struct tpm_dev *td = dev_get_drvdata(&chip->dev);
+ struct tpm_msg *smsg = td->se_ch->smsg;
+
+ memcpy(td->se_ch->data_buffer, buf, count);
+ smsg->data_len = count;
+
+ return se_send_ch_requeset(td->se_ch);
+}
+
+static const struct tpm_class_ops lsse_tpm_ops = {
+ .flags = TPM_OPS_AUTO_STARTUP,
+ .recv = tpm_ls_recv,
+ .send = tpm_ls_send,
+};
+
+static int lsse_tpm_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct tpm_chip *chip;
+ struct tpm_msg *smsg;
+ struct tpm_dev *td;
+
+ td = devm_kzalloc(dev, sizeof(struct tpm_dev), GFP_KERNEL);
+ if (!td)
+ return -ENOMEM;
+
+ init_completion(&td->tpm_completion);
+ td->se_ch = se_init_ch(dev->parent, SE_CH_TPM, PAGE_SIZE,
+ 2 * sizeof(struct tpm_msg), td, tpm_complete);
+ if (!td->se_ch)
+ return -ENODEV;
+ smsg = td->se_ch->smsg;
+ smsg->cmd = SE_CMD_TPM;
+ smsg->data_off = td->se_ch->off;
+
+ chip = tpmm_chip_alloc(dev, &lsse_tpm_ops);
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ chip->flags = TPM_CHIP_FLAG_TPM2 | TPM_CHIP_FLAG_IRQ;
+ dev_set_drvdata(&chip->dev, td);
+
+ return tpm_chip_register(chip);
+}
+
+static struct platform_driver lsse_tpm_driver = {
+ .probe = lsse_tpm_probe,
+ .driver = {
+ .name = "ls6000se-tpm",
+ },
+};
+module_platform_driver(lsse_tpm_driver);
+
+MODULE_ALIAS("platform:ls6000se-tpm");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yinggang Gu <guyinggang@loongson.cn>");
+MODULE_AUTHOR("Qunqin Zhao <zhaoqunqin@loongson.cn>");
+MODULE_DESCRIPTION("Loongson TPM driver");
--
2.43.0
^ permalink raw reply related
* [PATCH v2 2/3] crypto: loongson - add Loongson RNG driver support
From: Qunqin Zhao @ 2025-02-12 3:31 UTC (permalink / raw)
To: lee, herbert, davem, peterhuewe, jarkko
Cc: linux-kernel, loongarch, linux-crypto, jgg, linux-integrity,
Qunqin Zhao, Yinggang Gu
In-Reply-To: <20250212033113.15137-1-zhaoqunqin@loongson.cn>
Loongson's Random Number Generator is found inside Loongson 6000SE.
Co-developed-by: Yinggang Gu <guyinggang@loongson.cn>
Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
Signed-off-by: Qunqin Zhao <zhaoqunqin@loongson.cn>
---
v2: None
MAINTAINERS | 6 +
drivers/crypto/Kconfig | 1 +
drivers/crypto/Makefile | 1 +
drivers/crypto/loongson/Kconfig | 6 +
drivers/crypto/loongson/Makefile | 2 +
drivers/crypto/loongson/ls6000se-rng.c | 190 +++++++++++++++++++++++++
6 files changed, 206 insertions(+)
create mode 100644 drivers/crypto/loongson/Kconfig
create mode 100644 drivers/crypto/loongson/Makefile
create mode 100644 drivers/crypto/loongson/ls6000se-rng.c
diff --git a/MAINTAINERS b/MAINTAINERS
index cd6c029398..6493d58436 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13480,6 +13480,12 @@ S: Maintained
F: Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml
F: drivers/gpio/gpio-loongson-64bit.c
+LOONGSON CRYPTO DRIVER
+M: Qunqin Zhao <zhaoqunqin@loongson.com>
+L: linux-crypto@vger.kernel.org
+S: Maintained
+F: drivers/crypto/loongson/
+
LOONGSON-2 APB DMA DRIVER
M: Binbin Zhou <zhoubinbin@loongson.cn>
L: dmaengine@vger.kernel.org
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 0a9cdd31cb..80caf6158e 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -872,5 +872,6 @@ config CRYPTO_DEV_SA2UL
source "drivers/crypto/aspeed/Kconfig"
source "drivers/crypto/starfive/Kconfig"
+source "drivers/crypto/loongson/Kconfig"
endif # CRYPTO_HW
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index ad4ccef67d..a80e2586f7 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -52,3 +52,4 @@ obj-y += hisilicon/
obj-$(CONFIG_CRYPTO_DEV_AMLOGIC_GXL) += amlogic/
obj-y += intel/
obj-y += starfive/
+obj-y += loongson/
diff --git a/drivers/crypto/loongson/Kconfig b/drivers/crypto/loongson/Kconfig
new file mode 100644
index 0000000000..2b0b8b3241
--- /dev/null
+++ b/drivers/crypto/loongson/Kconfig
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+config CRYPTO_DEV_LS6000SE_RNG
+ tristate "Support for Loongson 6000SE RNG Driver"
+ depends on MFD_LS6000SE
+ help
+ Support for Loongson 6000SE RNG Driver.
diff --git a/drivers/crypto/loongson/Makefile b/drivers/crypto/loongson/Makefile
new file mode 100644
index 0000000000..17b0fa89e9
--- /dev/null
+++ b/drivers/crypto/loongson/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_CRYPTO_DEV_LS6000SE_RNG) += ls6000se-rng.o
diff --git a/drivers/crypto/loongson/ls6000se-rng.c b/drivers/crypto/loongson/ls6000se-rng.c
new file mode 100644
index 0000000000..b366475782
--- /dev/null
+++ b/drivers/crypto/loongson/ls6000se-rng.c
@@ -0,0 +1,190 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2019 HiSilicon Limited. */
+/* Copyright (c) 2025 Loongson Technology Corporation Limited. */
+
+#include <linux/crypto.h>
+#include <linux/err.h>
+#include <linux/hw_random.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/mfd/ls6000se.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/random.h>
+#include <crypto/internal/rng.h>
+
+struct lsrng_list {
+ struct mutex lock;
+ struct list_head list;
+ int is_init;
+};
+
+struct lsrng {
+ bool is_used;
+ struct lsse_ch *se_ch;
+ struct list_head list;
+ struct completion rng_completion;
+};
+
+struct lsrng_ctx {
+ struct lsrng *rng;
+};
+
+struct rng_msg {
+ u32 cmd;
+ union {
+ u32 len;
+ u32 ret;
+ } u;
+ u32 resved;
+ u32 out_off;
+ u32 pad[4];
+};
+
+static atomic_t rng_active_devs;
+static struct lsrng_list rng_devices;
+
+static void lsrng_complete(struct lsse_ch *ch)
+{
+ struct lsrng *rng = (struct lsrng *)ch->priv;
+
+ complete(&rng->rng_completion);
+}
+
+static int lsrng_generate(struct crypto_rng *tfm, const u8 *src,
+ unsigned int slen, u8 *dstn, unsigned int dlen)
+{
+ struct lsrng_ctx *ctx = crypto_rng_ctx(tfm);
+ struct lsrng *rng = ctx->rng;
+ struct rng_msg *msg;
+ int err, len;
+
+ do {
+ len = min(dlen, PAGE_SIZE);
+ msg = rng->se_ch->smsg;
+ msg->u.len = len;
+ err = se_send_ch_requeset(rng->se_ch);
+ if (err)
+ return err;
+
+ wait_for_completion_interruptible(&rng->rng_completion);
+
+ msg = rng->se_ch->rmsg;
+ if (msg->u.ret)
+ return -EFAULT;
+
+ memcpy(dstn, rng->se_ch->data_buffer, len);
+ dlen -= len;
+ dstn += len;
+ } while (dlen > 0);
+
+ return 0;
+}
+
+static int lsrng_init(struct crypto_tfm *tfm)
+{
+ struct lsrng_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct lsrng *rng;
+ int ret = -EBUSY;
+
+ mutex_lock(&rng_devices.lock);
+ list_for_each_entry(rng, &rng_devices.list, list) {
+ if (!rng->is_used) {
+ rng->is_used = true;
+ ctx->rng = rng;
+ ret = 0;
+ break;
+ }
+ }
+ mutex_unlock(&rng_devices.lock);
+
+ return ret;
+}
+
+static void lsrng_exit(struct crypto_tfm *tfm)
+{
+ struct lsrng_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ mutex_lock(&rng_devices.lock);
+ ctx->rng->is_used = false;
+ mutex_unlock(&rng_devices.lock);
+}
+
+static int no_seed(struct crypto_rng *tfm, const u8 *seed, unsigned int slen)
+{
+ return 0;
+}
+
+static struct rng_alg lsrng_alg = {
+ .generate = lsrng_generate,
+ .seed = no_seed,
+ .base = {
+ .cra_name = "stdrng",
+ .cra_driver_name = "loongson_stdrng",
+ .cra_priority = 300,
+ .cra_ctxsize = sizeof(struct lsrng_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_init = lsrng_init,
+ .cra_exit = lsrng_exit,
+ },
+};
+
+static void lsrng_add_to_list(struct lsrng *rng)
+{
+ mutex_lock(&rng_devices.lock);
+ list_add_tail(&rng->list, &rng_devices.list);
+ mutex_unlock(&rng_devices.lock);
+}
+
+static int lsrng_probe(struct platform_device *pdev)
+{
+ struct rng_msg *msg;
+ struct lsrng *rng;
+ int ret;
+
+ rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
+ if (!rng)
+ return -ENOMEM;
+
+ init_completion(&rng->rng_completion);
+ rng->se_ch = se_init_ch(pdev->dev.parent, SE_CH_RNG, PAGE_SIZE,
+ sizeof(struct rng_msg) * 2, rng, lsrng_complete);
+ if (!rng->se_ch)
+ return -ENODEV;
+ msg = rng->se_ch->smsg;
+ msg->cmd = SE_CMD_RNG;
+ msg->out_off = rng->se_ch->off;
+
+ if (!rng_devices.is_init) {
+ ret = crypto_register_rng(&lsrng_alg);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register crypto(%d)\n", ret);
+ return ret;
+ }
+ INIT_LIST_HEAD(&rng_devices.list);
+ mutex_init(&rng_devices.lock);
+ rng_devices.is_init = true;
+ }
+
+ lsrng_add_to_list(rng);
+ atomic_inc(&rng_active_devs);
+
+ return 0;
+}
+
+static struct platform_driver lsrng_driver = {
+ .probe = lsrng_probe,
+ .driver = {
+ .name = "ls6000se-rng",
+ },
+};
+module_platform_driver(lsrng_driver);
+
+MODULE_ALIAS("platform:ls6000se-rng");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yinggang Gu <guyinggang@loongson.cn>");
+MODULE_AUTHOR("Qunqin Zhao <zhaoqunqin@loongson.cn>");
+MODULE_DESCRIPTION("Loongson random number generator driver");
--
2.43.0
^ permalink raw reply related
* [PATCH v2 1/3] mfd: Add support for Loongson Security Module
From: Qunqin Zhao @ 2025-02-12 3:31 UTC (permalink / raw)
To: lee, herbert, davem, peterhuewe, jarkko
Cc: linux-kernel, loongarch, linux-crypto, jgg, linux-integrity,
Qunqin Zhao, Yinggang Gu
In-Reply-To: <20250212033113.15137-1-zhaoqunqin@loongson.cn>
This driver supports Loongson Security Module, which provides the control
for it's hardware encryption acceleration child devices.
Co-developed-by: Yinggang Gu <guyinggang@loongson.cn>
Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
Signed-off-by: Qunqin Zhao <zhaoqunqin@loongson.cn>
---
v2: Removed "ls6000se-sdf" device, added "ls6000se-tpm" device.
Passed size to SE firmware in se_init_hw() function.
MAINTAINERS | 7 +
drivers/mfd/Kconfig | 9 +
drivers/mfd/Makefile | 2 +
drivers/mfd/ls6000se.c | 374 +++++++++++++++++++++++++++++++++++
include/linux/mfd/ls6000se.h | 75 +++++++
5 files changed, 467 insertions(+)
create mode 100644 drivers/mfd/ls6000se.c
create mode 100644 include/linux/mfd/ls6000se.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 5583df569c..cd6c029398 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13494,6 +13494,13 @@ S: Maintained
F: Documentation/devicetree/bindings/i2c/loongson,ls2x-i2c.yaml
F: drivers/i2c/busses/i2c-ls2x.c
+LOONGSON SECURITY MODULE DRIVER
+M: Qunqin Zhao <zhaoqunqin@loongson.cn>
+L: loongarch@lists.linux.dev
+S: Maintained
+F: drivers/mfd/ls6000se.c
+F: include/linux/mfd/ls6000se.h
+
LOONGSON-2 SOC SERIES CLOCK DRIVER
M: Yinbo Zhu <zhuyinbo@loongson.cn>
L: linux-clk@vger.kernel.org
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 6b0682af6e..a17554d64e 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -2438,6 +2438,15 @@ config MFD_UPBOARD_FPGA
To compile this driver as a module, choose M here: the module will be
called upboard-fpga.
+config MFD_LS6000SE
+ tristate "Loongson Security Module Interface"
+ depends on LOONGARCH && ACPI
+ select MFD_CORE
+ help
+ The Loongson security module provides the control for hardware
+ encryption acceleration devices. Each device uses at least one
+ channel to interact with security module, and each channel may
+ have its own buffer provided by security module.
endmenu
endif
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 9220eaf7cf..9556de7715 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -294,3 +294,5 @@ obj-$(CONFIG_MFD_RSMU_I2C) += rsmu_i2c.o rsmu_core.o
obj-$(CONFIG_MFD_RSMU_SPI) += rsmu_spi.o rsmu_core.o
obj-$(CONFIG_MFD_UPBOARD_FPGA) += upboard-fpga.o
+
+obj-$(CONFIG_MFD_LS6000SE) += ls6000se.o
diff --git a/drivers/mfd/ls6000se.c b/drivers/mfd/ls6000se.c
new file mode 100644
index 0000000000..24d76c2ffc
--- /dev/null
+++ b/drivers/mfd/ls6000se.c
@@ -0,0 +1,374 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2025 Loongson Technology Corporation Limited */
+
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/ls6000se.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+/*
+ * The Loongson Security Module provides the control for hardware
+ * encryption acceleration child devices. The SE framework is
+ * shown as follows:
+ *
+ * +------------+
+ * | CPU |
+ * +------------+
+ * ^ ^
+ * DMA | | IRQ
+ * v v
+ * +-----------------------------------+
+ * | Loongson Security Module |
+ * +-----------------------------------+
+ * ^ ^
+ * channel1 | channel2 |
+ * v v
+ * +-----------+ +----------+
+ * | sub-dev1 | | sub-dev2 | ..... Max sub-dev31
+ * +-----------+ +----------+
+ *
+ * The CPU cannot directly communicate with SE's sub devices,
+ * but sends commands to SE, which processes the commands and
+ * sends them to the corresponding sub devices.
+ */
+
+struct loongson_se {
+ void __iomem *base;
+ u32 version;
+ spinlock_t dev_lock;
+ struct completion cmd_completion;
+
+ /* dma memory */
+ void *mem_base;
+ int mem_map_pages;
+ unsigned long *mem_map;
+
+ /* channel */
+ struct mutex ch_init_lock;
+ struct lsse_ch chs[SE_CH_MAX];
+};
+
+union se_request {
+ u32 info[8];
+ struct se_cmd {
+ u32 cmd;
+ u32 info[7];
+ } req;
+ struct se_res {
+ u32 cmd;
+ u32 cmd_ret;
+ u32 info[6];
+ } res;
+};
+
+static inline u32 se_readl(struct loongson_se *se, u32 off)
+{
+ return readl(se->base + off);
+}
+
+static inline void se_writel(struct loongson_se *se, u32 val, u32 off)
+{
+ writel(val, se->base + off);
+}
+
+static void se_enable_int_locked(struct loongson_se *se, u32 int_bit)
+{
+ u32 tmp;
+
+ tmp = se_readl(se, SE_S2LINT_EN);
+ tmp |= int_bit;
+ se_writel(se, tmp, SE_S2LINT_EN);
+}
+
+static void se_disable_int(struct loongson_se *se, u32 int_bit)
+{
+ unsigned long flag;
+ u32 tmp;
+
+ spin_lock_irqsave(&se->dev_lock, flag);
+
+ tmp = se_readl(se, SE_S2LINT_EN);
+ tmp &= ~(int_bit);
+ se_writel(se, tmp, SE_S2LINT_EN);
+
+ spin_unlock_irqrestore(&se->dev_lock, flag);
+}
+
+static int se_poll(struct loongson_se *se, u32 int_bit)
+{
+ u32 status;
+ int err;
+
+ spin_lock_irq(&se->dev_lock);
+
+ se_enable_int_locked(se, int_bit);
+ se_writel(se, int_bit, SE_L2SINT_SET);
+ err = readl_relaxed_poll_timeout_atomic(se->base + SE_L2SINT_STAT, status,
+ !(status & int_bit), 1, 10000);
+
+ spin_unlock_irq(&se->dev_lock);
+
+ return err;
+}
+
+static int se_send_requeset(struct loongson_se *se, union se_request *req)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(req->info); i++)
+ se_writel(se, req->info[i], SE_DATA_S + i * 4);
+
+ return se_poll(se, SE_INT_SETUP);
+}
+
+/*
+ * Called by SE's child device driver.
+ * Send a request to the corresponding device.
+ */
+int se_send_ch_requeset(struct lsse_ch *ch)
+{
+ return se_poll(ch->se, ch->int_bit);
+}
+EXPORT_SYMBOL_GPL(se_send_ch_requeset);
+
+static int se_get_res(struct loongson_se *se, u32 cmd, union se_request *res)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(res->info); i++)
+ res->info[i] = se_readl(se, SE_DATA_L + i * 4);
+
+ if (res->res.cmd != cmd)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int se_send_genl_cmd(struct loongson_se *se, union se_request *req)
+{
+ int err;
+
+ err = se_send_requeset(se, req);
+ if (err)
+ return err;
+
+ if (!wait_for_completion_timeout(&se->cmd_completion, HZ))
+ return -ETIME;
+
+ return se_get_res(se, req->req.cmd, req);
+}
+
+static int se_set_msg(struct lsse_ch *ch)
+{
+ struct loongson_se *se = ch->se;
+ union se_request req;
+
+ req.req.cmd = SE_CMD_SETMSG;
+ req.req.info[0] = ch->id;
+ req.req.info[1] = ch->smsg - se->mem_base;
+ req.req.info[2] = ch->msg_size;
+
+ return se_send_genl_cmd(se, &req);
+}
+
+static irqreturn_t se_irq(int irq, void *dev_id)
+{
+ struct loongson_se *se = (struct loongson_se *)dev_id;
+ struct lsse_ch *ch;
+ u32 int_status;
+ int id;
+
+ int_status = se_readl(se, SE_S2LINT_STAT);
+ se_disable_int(se, int_status);
+ if (int_status & SE_INT_SETUP) {
+ complete(&se->cmd_completion);
+ int_status &= ~SE_INT_SETUP;
+ se_writel(se, SE_INT_SETUP, SE_S2LINT_CL);
+ }
+
+ while (int_status) {
+ id = __ffs(int_status);
+
+ ch = &se->chs[id];
+ if (ch->complete)
+ ch->complete(ch);
+ int_status &= ~BIT(id);
+ se_writel(se, BIT(id), SE_S2LINT_CL);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int se_init_hw(struct loongson_se *se, dma_addr_t addr, int size)
+{
+ union se_request req;
+ int err;
+
+ /* Start engine */
+ req.req.cmd = SE_CMD_START;
+ err = se_send_genl_cmd(se, &req);
+ if (err)
+ return err;
+
+ /* Get Version */
+ req.req.cmd = SE_CMD_GETVER;
+ err = se_send_genl_cmd(se, &req);
+ if (err)
+ return err;
+ se->version = req.res.info[0];
+
+ /* Setup dma memory */
+ req.req.cmd = SE_CMD_SETBUF;
+ req.req.info[0] = addr & 0xffffffff;
+ req.req.info[1] = addr >> 32;
+ req.req.info[2] = size;
+
+ return se_send_genl_cmd(se, &req);
+}
+
+/*
+ * se_init_ch() - Init the channel used by child device.
+ *
+ * Allocate dma memory as agreed upon with SE on SE probe,
+ * and register the callback function when the data processing
+ * in this channel is completed.
+ */
+struct lsse_ch *se_init_ch(struct device *dev, int id, int data_size, int msg_size,
+ void *priv, void (*complete)(struct lsse_ch *se_ch))
+{
+ struct loongson_se *se = dev_get_drvdata(dev);
+ struct lsse_ch *ch;
+ int data_first, data_nr;
+ int msg_first, msg_nr;
+
+ mutex_lock(&se->ch_init_lock);
+
+ ch = &se->chs[id];
+ ch->se = se;
+ ch->id = id;
+ ch->int_bit = BIT(id);
+
+ data_nr = round_up(data_size, PAGE_SIZE) / PAGE_SIZE;
+ data_first = bitmap_find_next_zero_area(se->mem_map, se->mem_map_pages,
+ 0, data_nr, 0);
+ if (data_first >= se->mem_map_pages) {
+ ch = NULL;
+ goto out_unlock;
+ }
+
+ bitmap_set(se->mem_map, data_first, data_nr);
+ ch->off = data_first * PAGE_SIZE;
+ ch->data_buffer = se->mem_base + ch->off;
+ ch->data_size = data_size;
+
+ msg_nr = round_up(msg_size, PAGE_SIZE) / PAGE_SIZE;
+ msg_first = bitmap_find_next_zero_area(se->mem_map, se->mem_map_pages,
+ 0, msg_nr, 0);
+ if (msg_first >= se->mem_map_pages) {
+ ch = NULL;
+ goto out_unlock;
+ }
+
+ bitmap_set(se->mem_map, msg_first, msg_nr);
+ ch->smsg = se->mem_base + msg_first * PAGE_SIZE;
+ ch->rmsg = ch->smsg + msg_size / 2;
+ ch->msg_size = msg_size;
+ ch->complete = complete;
+ ch->priv = priv;
+ ch->version = se->version;
+
+ if (se_set_msg(ch))
+ ch = NULL;
+
+out_unlock:
+ mutex_unlock(&se->ch_init_lock);
+
+ return ch;
+}
+EXPORT_SYMBOL_GPL(se_init_ch);
+
+static const struct mfd_cell se_devs[] = {
+ { .name = "ls6000se-sdf" },
+ { .name = "ls6000se-tpm" },
+};
+
+static int loongson_se_probe(struct platform_device *pdev)
+{
+ struct loongson_se *se;
+ struct device *dev = &pdev->dev;
+ int nr_irq, irq, err, size;
+ dma_addr_t paddr;
+
+ se = devm_kmalloc(dev, sizeof(*se), GFP_KERNEL);
+ if (!se)
+ return -ENOMEM;
+ dev_set_drvdata(dev, se);
+ init_completion(&se->cmd_completion);
+ spin_lock_init(&se->dev_lock);
+ mutex_init(&se->ch_init_lock);
+ dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
+ if (device_property_read_u32(dev, "dmam_size", &size))
+ return -ENODEV;
+ size = roundup_pow_of_two(size);
+ se->mem_base = dmam_alloc_coherent(dev, size, &paddr, GFP_KERNEL);
+ if (!se->mem_base)
+ return -ENOMEM;
+ se->mem_map_pages = size / PAGE_SIZE;
+ se->mem_map = devm_bitmap_zalloc(dev, se->mem_map_pages, GFP_KERNEL);
+ if (!se->mem_map)
+ return -ENOMEM;
+
+ se->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(se->base))
+ return PTR_ERR(se->base);
+
+ nr_irq = platform_irq_count(pdev);
+ if (nr_irq <= 0)
+ return -ENODEV;
+ while (nr_irq) {
+ irq = platform_get_irq(pdev, --nr_irq);
+ /* Use the same interrupt handler address.
+ * Determine which irq it is accroding
+ * SE_S2LINT_STAT register.
+ */
+ err = devm_request_irq(dev, irq, se_irq, 0, "ls6000se", se);
+ if (err)
+ dev_err(dev, "failed to request irq: %d\n", irq);
+ }
+
+ err = se_init_hw(se, paddr, size);
+ if (err)
+ return err;
+
+ return devm_mfd_add_devices(dev, 0, se_devs, ARRAY_SIZE(se_devs),
+ NULL, 0, NULL);
+}
+
+static const struct acpi_device_id loongson_se_acpi_match[] = {
+ {"LOON0011", 0},
+ {}
+};
+MODULE_DEVICE_TABLE(acpi, loongson_se_acpi_match);
+
+static struct platform_driver loongson_se_driver = {
+ .probe = loongson_se_probe,
+ .driver = {
+ .name = "ls6000se",
+ .acpi_match_table = loongson_se_acpi_match,
+ },
+};
+module_platform_driver(loongson_se_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yinggang Gu <guyinggang@loongson.cn>");
+MODULE_AUTHOR("Qunqin Zhao <zhaoqunqin@loongson.cn>");
+MODULE_DESCRIPTION("Loongson Security Module driver");
diff --git a/include/linux/mfd/ls6000se.h b/include/linux/mfd/ls6000se.h
new file mode 100644
index 0000000000..f70e9f196a
--- /dev/null
+++ b/include/linux/mfd/ls6000se.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (C) 2025 Loongson Technology Corporation Limited */
+
+#ifndef __LOONGSON_SE_H__
+#define __LOONGSON_SE_H__
+
+#define SE_DATA_S 0x0
+#define SE_DATA_L 0x20
+#define SE_S2LINT_STAT 0x88
+#define SE_S2LINT_EN 0x8c
+#define SE_S2LINT_SET 0x90
+#define SE_S2LINT_CL 0x94
+#define SE_L2SINT_STAT 0x98
+#define SE_L2SINT_EN 0x9c
+#define SE_L2SINT_SET 0xa0
+#define SE_L2SINT_CL 0xa4
+
+/* INT bit definition */
+#define SE_INT_SETUP BIT(0)
+#define SE_INT_TPM BIT(5)
+
+#define SE_CMD_START 0x0
+#define SE_CMD_STOP 0x1
+#define SE_CMD_GETVER 0x2
+#define SE_CMD_SETBUF 0x3
+#define SE_CMD_SETMSG 0x4
+
+#define SE_CMD_RNG 0x100
+#define SE_CMD_SM2_SIGN 0x200
+#define SE_CMD_SM2_VSIGN 0x201
+#define SE_CMD_SM3_DIGEST 0x300
+#define SE_CMD_SM3_UPDATE 0x301
+#define SE_CMD_SM3_FINISH 0x302
+#define SE_CMD_SM4_ECB_ENCRY 0x400
+#define SE_CMD_SM4_ECB_DECRY 0x401
+#define SE_CMD_SM4_CBC_ENCRY 0x402
+#define SE_CMD_SM4_CBC_DECRY 0x403
+#define SE_CMD_SM4_CTR 0x404
+#define SE_CMD_TPM 0x500
+#define SE_CMD_ZUC_INIT_READ 0x600
+#define SE_CMD_ZUC_READ 0x601
+#define SE_CMD_SDF 0x700
+
+#define SE_CH_MAX 32
+#define SE_CH_RNG 1
+#define SE_CH_SM2 2
+#define SE_CH_SM3 3
+#define SE_CH_SM4 4
+#define SE_CH_TPM 5
+#define SE_CH_ZUC 6
+#define SE_CH_SDF 7
+
+struct lsse_ch {
+ struct loongson_se *se;
+ void *priv;
+ u32 version;
+ u32 id;
+ u32 int_bit;
+
+ void *smsg;
+ void *rmsg;
+ int msg_size;
+
+ void *data_buffer;
+ int data_size;
+ u32 off;
+
+ void (*complete)(struct lsse_ch *se_ch);
+};
+
+struct lsse_ch *se_init_ch(struct device *dev, int id, int data_size, int msg_size,
+ void *priv, void (*complete)(struct lsse_ch *se_ch));
+int se_send_ch_requeset(struct lsse_ch *ch);
+
+#endif
--
2.43.0
^ permalink raw reply related
* [PATCH v2 0/3] Drivers for Loongson security engine
From: Qunqin Zhao @ 2025-02-12 3:31 UTC (permalink / raw)
To: lee, herbert, davem, peterhuewe, jarkko
Cc: linux-kernel, loongarch, linux-crypto, jgg, linux-integrity,
Qunqin Zhao
Loongson security engine supports random number generation, hash,
symmetric encryption and asymmetric encryption. Based on these
encryption functions, TPM2.0 have been implemented in it.
mfd is the baser driver, crypto and tpm are users.
v2: Removed misc driver. Added tpm driver.
Qunqin Zhao (3):
mfd: Add support for Loongson Security Module
crypto: loongson - add Loongson RNG driver support
tpm: Add a driver for Loongson TPM device
MAINTAINERS | 14 +
drivers/char/tpm/Kconfig | 9 +
drivers/char/tpm/Makefile | 1 +
drivers/char/tpm/tpm_lsse.c | 104 +++++++
drivers/crypto/Kconfig | 1 +
drivers/crypto/Makefile | 1 +
drivers/crypto/loongson/Kconfig | 6 +
drivers/crypto/loongson/Makefile | 2 +
drivers/crypto/loongson/ls6000se-rng.c | 190 +++++++++++++
drivers/mfd/Kconfig | 9 +
drivers/mfd/Makefile | 2 +
drivers/mfd/ls6000se.c | 374 +++++++++++++++++++++++++
include/linux/mfd/ls6000se.h | 75 +++++
13 files changed, 788 insertions(+)
create mode 100644 drivers/char/tpm/tpm_lsse.c
create mode 100644 drivers/crypto/loongson/Kconfig
create mode 100644 drivers/crypto/loongson/Makefile
create mode 100644 drivers/crypto/loongson/ls6000se-rng.c
create mode 100644 drivers/mfd/ls6000se.c
create mode 100644 include/linux/mfd/ls6000se.h
base-commit: 2816b0c949af89640b8dc05de53e650cbf1d55fb
--
2.43.0
^ permalink raw reply
* Re: [PATCH v10 2/5] s390/crypto: New s390 specific protected key hash phmac
From: Herbert Xu @ 2025-02-12 3:23 UTC (permalink / raw)
To: Harald Freudenberger; +Cc: ebiggers, linux-s390, linux-crypto, davem, dengler
In-Reply-To: <Z6wTTJz8uUNwT8Gg@gondor.apana.org.au>
On Wed, Feb 12, 2025 at 11:19:40AM +0800, Herbert Xu wrote:
>
> Don't worry about this. It can easily be reverted once a patch
> using it is submitted.
I just reverted it in cryptodev.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: [PATCH v10 2/5] s390/crypto: New s390 specific protected key hash phmac
From: Herbert Xu @ 2025-02-12 3:19 UTC (permalink / raw)
To: Harald Freudenberger; +Cc: ebiggers, linux-s390, linux-crypto, davem, dengler
In-Reply-To: <265b5abbf32fcb6748abad7d0ec360cc@linux.ibm.com>
On Tue, Feb 11, 2025 at 01:09:12PM +0100, Harald Freudenberger wrote:
>
> with your commit
> 7fa481734016 crypto: ahash - make hash walk functions private to ahash.c
> you move the crypto_hash_walk_* functions to private context into ahash.c.
> So for example my new phmac does not compile any more.
> What is the replacement for these functions then? Should I really do
> the scatter walk by my own now or is there a set of new functions to come?
Don't worry about this. It can easily be reverted once a patch
using it is submitted.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: [PATCH v6 9/9] KVM: selftests: Add a basic SEV-SNP smoke test
From: Sean Christopherson @ 2025-02-12 2:31 UTC (permalink / raw)
To: Pratik R. Sampat
Cc: linux-kernel, x86, kvm, linux-crypto, linux-kselftest, pbonzini,
thomas.lendacky, tglx, mingo, bp, dave.hansen, shuah, pgonda,
ashish.kalra, nikunj, pankaj.gupta, michael.roth, sraithal
In-Reply-To: <20250203223205.36121-10-prsampat@amd.com>
On Mon, Feb 03, 2025, Pratik R. Sampat wrote:
> @@ -217,5 +244,20 @@ int main(int argc, char *argv[])
> }
> }
>
> + if (kvm_cpu_has(X86_FEATURE_SEV_SNP)) {
> + uint64_t snp_policy = snp_default_policy();
> +
> + test_snp(snp_policy);
> + /* Test minimum firmware level */
> + test_snp(snp_policy | SNP_FW_VER_MAJOR(SNP_MIN_API_MAJOR) |
> + SNP_FW_VER_MINOR(SNP_MIN_API_MINOR));
Ah, this is where the firmware policy stuff is used. Refresh me, can userspace
request _any_ major/minor as the min, and expect failure if the version isn't
supported? If so, the test should iterate over the major/minor combinations that
are guaranteed to fail. And if userspace can query the supported minor/major,
the test should iterate over all the happy versions too.
Unless there's nothing interesting to test, I would move the major/minor stuff to
a separate patch.
> +
> + test_snp_shutdown(snp_policy);
> +
> + if (kvm_has_cap(KVM_CAP_XCRS) &&
> + (xgetbv(0) & kvm_cpu_supported_xcr0() & xf_mask) == xf_mask)
> + test_sync_vmsa_snp(snp_policy);
This is all copy+paste from SEV-ES tests, minus SEV_POLICY_NO_DBG. There's gotta
be a way to dedup this code.
Something like this?
static void needs_a_better_name(uint32_t type, uint64_t policy)
{
const u64 xf_mask = XFEATURE_MASK_X87_AVX;
test_sev(guest_sev_code, policy | SEV_POLICY_NO_DBG);
test_sev(guest_sev_code, policy);
if (type == KVM_X86_SEV_VM)
return;
test_sev_shutdown(policy);
if (kvm_has_cap(KVM_CAP_XCRS) &&
(xgetbv(0) & kvm_cpu_supported_xcr0() & xf_mask) == xf_mask) {
test_sync_vmsa(policy);
test_sync_vmsa(policy | SEV_POLICY_NO_DBG);
}
}
int main(int argc, char *argv[])
{
TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SEV));
needs_a_better_name(KVM_X86_SEV_VM, 0);
if (kvm_cpu_has(X86_FEATURE_SEV_ES))
needs_a_better_name(KVM_X86_SEV_ES_VM, 0);
if (kvm_cpu_has(X86_FEATURE_SEV_SNP))
needs_a_better_name(KVM_X86_SEV_SNP_VM, 0);
return 0;
}
^ permalink raw reply
* Re: [PATCH v6 6/9] KVM: selftests: Add library support for interacting with SNP
From: Sean Christopherson @ 2025-02-12 2:12 UTC (permalink / raw)
To: Pratik R. Sampat
Cc: linux-kernel, x86, kvm, linux-crypto, linux-kselftest, pbonzini,
thomas.lendacky, tglx, mingo, bp, dave.hansen, shuah, pgonda,
ashish.kalra, nikunj, pankaj.gupta, michael.roth, sraithal
In-Reply-To: <20250203223205.36121-7-prsampat@amd.com>
On Mon, Feb 03, 2025, Pratik R. Sampat wrote:
> Extend the SEV library to include support for SNP ioctl() wrappers,
> which aid in launching and interacting with a SEV-SNP guest.
>
> Tested-by: Srikanth Aithal <sraithal@amd.com>
> Signed-off-by: Pratik R. Sampat <prsampat@amd.com>
> ---
> v5..v6:
>
> * Collected tags from Srikanth.
> ---
> tools/testing/selftests/kvm/include/x86/sev.h | 49 ++++++++++-
> tools/testing/selftests/kvm/lib/x86/sev.c | 82 +++++++++++++++++--
> 2 files changed, 125 insertions(+), 6 deletions(-)
>
> diff --git a/tools/testing/selftests/kvm/include/x86/sev.h b/tools/testing/selftests/kvm/include/x86/sev.h
> index faed91435963..fd5d5261e10e 100644
> --- a/tools/testing/selftests/kvm/include/x86/sev.h
> +++ b/tools/testing/selftests/kvm/include/x86/sev.h
> @@ -22,9 +22,20 @@ enum sev_guest_state {
> SEV_GUEST_STATE_RUNNING,
> };
>
> +/* Minimum firmware version required for the SEV-SNP support */
> +#define SNP_MIN_API_MAJOR 1
> +#define SNP_MIN_API_MINOR 51
Dead code. Selftests don't care about this.
> #define SEV_POLICY_NO_DBG (1UL << 0)
> #define SEV_POLICY_ES (1UL << 2)
>
> +#define SNP_POLICY_SMT (1ULL << 16)
> +#define SNP_POLICY_RSVD_MBO (1ULL << 17)
> +#define SNP_POLICY_DBG (1ULL << 19)
> +
> +#define SNP_FW_VER_MINOR(min) ((uint8_t)(min) << 0)
> +#define SNP_FW_VER_MAJOR(maj) ((uint8_t)(maj) << 8)
Also dead code.
> #define GHCB_MSR_TERM_REQ 0x100
>
> #define VMGEXIT() { __asm__ __volatile__("rep; vmmcall"); }
> @@ -36,13 +47,35 @@ bool is_sev_snp_vm(struct kvm_vm *vm);
> void sev_vm_launch(struct kvm_vm *vm, uint32_t policy);
> void sev_vm_launch_measure(struct kvm_vm *vm, uint8_t *measurement);
> void sev_vm_launch_finish(struct kvm_vm *vm);
> +void snp_vm_launch_start(struct kvm_vm *vm, uint64_t policy);
> +void snp_vm_launch_update(struct kvm_vm *vm);
> +void snp_vm_launch_finish(struct kvm_vm *vm);
>
> struct kvm_vm *vm_sev_create_with_one_vcpu(uint32_t type, void *guest_code,
> struct kvm_vcpu **cpu);
> -void vm_sev_launch(struct kvm_vm *vm, uint32_t policy, uint8_t *measurement);
> +void vm_sev_launch(struct kvm_vm *vm, uint64_t policy, uint8_t *measurement);
>
> kvm_static_assert(SEV_RET_SUCCESS == 0);
>
> +/*
> + * A SEV-SNP VM requires the policy reserved bit to always be set.
> + * The SMT policy bit is also required to be set based on SMT being
> + * available and active on the system.
> + */
> +static inline u64 snp_default_policy(void)
> +{
> + bool smt_active = false;
> + FILE *f;
> +
> + f = fopen("/sys/devices/system/cpu/smt/active", "r");
Please add a helper to query if SMT is enabled. I doubt there will ever be many
users of this, but it doesn't seem like something that should buried in SNP code.
Ha! smt_possible() in tools/testing/selftests/kvm/x86/hyperv_cpuid.c is already
guilty of burying a related helper, and it looks like it's a more robust version.
> + if (f) {
> + smt_active = fgetc(f) - '0';
> + fclose(f);
> + }
> +
> + return SNP_POLICY_RSVD_MBO | (smt_active ? SNP_POLICY_SMT : 0);
> +}
> +
> /*
> * The KVM_MEMORY_ENCRYPT_OP uAPI is utter garbage and takes an "unsigned long"
> * instead of a proper struct. The size of the parameter is embedded in the
> @@ -76,6 +109,7 @@ kvm_static_assert(SEV_RET_SUCCESS == 0);
>
> void sev_vm_init(struct kvm_vm *vm);
> void sev_es_vm_init(struct kvm_vm *vm);
> +void snp_vm_init(struct kvm_vm *vm);
>
> static inline void sev_register_encrypted_memory(struct kvm_vm *vm,
> struct userspace_mem_region *region)
> @@ -99,4 +133,17 @@ static inline void sev_launch_update_data(struct kvm_vm *vm, vm_paddr_t gpa,
> vm_sev_ioctl(vm, KVM_SEV_LAUNCH_UPDATE_DATA, &update_data);
> }
>
> +static inline void snp_launch_update_data(struct kvm_vm *vm, vm_paddr_t gpa,
> + uint64_t hva, uint64_t size, uint8_t type)
> +{
> + struct kvm_sev_snp_launch_update update_data = {
> + .uaddr = hva,
> + .gfn_start = gpa >> PAGE_SHIFT,
> + .len = size,
> + .type = type,
> + };
> +
> + vm_sev_ioctl(vm, KVM_SEV_SNP_LAUNCH_UPDATE, &update_data);
> +}
> +
> #endif /* SELFTEST_KVM_SEV_H */
> diff --git a/tools/testing/selftests/kvm/lib/x86/sev.c b/tools/testing/selftests/kvm/lib/x86/sev.c
> index 280ec42e281b..17d493e9907a 100644
> --- a/tools/testing/selftests/kvm/lib/x86/sev.c
> +++ b/tools/testing/selftests/kvm/lib/x86/sev.c
> @@ -31,7 +31,8 @@ bool is_sev_vm(struct kvm_vm *vm)
> * and find the first range, but that's correct because the condition
> * expression would cause us to quit the loop.
> */
> -static void encrypt_region(struct kvm_vm *vm, struct userspace_mem_region *region)
> +static void encrypt_region(struct kvm_vm *vm, struct userspace_mem_region *region,
> + uint8_t page_type)
> {
> const struct sparsebit *protected_phy_pages = region->protected_phy_pages;
> const vm_paddr_t gpa_base = region->region.guest_phys_addr;
> @@ -41,13 +42,35 @@ static void encrypt_region(struct kvm_vm *vm, struct userspace_mem_region *regio
> if (!sparsebit_any_set(protected_phy_pages))
> return;
>
> - sev_register_encrypted_memory(vm, region);
> + if (!is_sev_snp_vm(vm))
> + sev_register_encrypted_memory(vm, region);
>
> sparsebit_for_each_set_range(protected_phy_pages, i, j) {
> const uint64_t size = (j - i + 1) * vm->page_size;
> const uint64_t offset = (i - lowest_page_in_region) * vm->page_size;
>
> - sev_launch_update_data(vm, gpa_base + offset, size);
> + if (is_sev_snp_vm(vm)) {
Curly braces are unnecessary.
> + snp_launch_update_data(vm, gpa_base + offset,
> + (uint64_t)addr_gpa2hva(vm, gpa_base + offset),
> + size, page_type);
> + } else {
> + sev_launch_update_data(vm, gpa_base + offset, size);
> + }
> + }
> +}
> +
> +static void privatize_region(struct kvm_vm *vm, struct userspace_mem_region *region)
Can't this just be a param to encrypt_region() that also says "make it private"?
> +{
> + const struct sparsebit *protected_phy_pages = region->protected_phy_pages;
> + const vm_paddr_t gpa_base = region->region.guest_phys_addr;
> + const sparsebit_idx_t lowest_page_in_region = gpa_base >> vm->page_shift;
> + sparsebit_idx_t i, j;
> +
> + sparsebit_for_each_set_range(protected_phy_pages, i, j) {
> + const uint64_t size = (j - i + 1) * vm->page_size;
> + const uint64_t offset = (i - lowest_page_in_region) * vm->page_size;
> +
> + vm_mem_set_private(vm, gpa_base + offset, size);
> }
> }
>
> @@ -77,6 +100,14 @@ void sev_es_vm_init(struct kvm_vm *vm)
> }
> }
>
> +void snp_vm_init(struct kvm_vm *vm)
> +{
> + struct kvm_sev_init init = { 0 };
> +
> + assert(vm->type == KVM_X86_SNP_VM);
Use TEST_ASSERT(), or do nothing, don't use assert().
> + vm_sev_ioctl(vm, KVM_SEV_INIT2, &init);
> +}
> +
> void sev_vm_launch(struct kvm_vm *vm, uint32_t policy)
> {
> struct kvm_sev_launch_start launch_start = {
> @@ -93,7 +124,7 @@ void sev_vm_launch(struct kvm_vm *vm, uint32_t policy)
> TEST_ASSERT_EQ(status.state, SEV_GUEST_STATE_LAUNCH_UPDATE);
>
> hash_for_each(vm->regions.slot_hash, ctr, region, slot_node)
> - encrypt_region(vm, region);
> + encrypt_region(vm, region, 0);
Please add an enum/macro instead of open coding a literal '0'. I gotta assume
there's an appropriate name for page type '0'.
>
> if (policy & SEV_POLICY_ES)
> vm_sev_ioctl(vm, KVM_SEV_LAUNCH_UPDATE_VMSA, NULL);
^ permalink raw reply
* Re: [PATCH v6 4/9] KVM: selftests: Add VMGEXIT helper
From: Sean Christopherson @ 2025-02-12 1:59 UTC (permalink / raw)
To: Pratik R. Sampat
Cc: linux-kernel, x86, kvm, linux-crypto, linux-kselftest, pbonzini,
thomas.lendacky, tglx, mingo, bp, dave.hansen, shuah, pgonda,
ashish.kalra, nikunj, pankaj.gupta, michael.roth, sraithal
In-Reply-To: <20250203223205.36121-5-prsampat@amd.com>
On Mon, Feb 03, 2025, Pratik R. Sampat wrote:
> Abstract rep vmmcall coded into the VMGEXIT helper for the sev
> library.
>
> No functional change intended.
>
> Reviewed-by: Pankaj Gupta <pankaj.gupta@amd.com>
> Tested-by: Srikanth Aithal <sraithal@amd.com>
> Signed-off-by: Pratik R. Sampat <prsampat@amd.com>
> ---
> v5..v6:
>
> * Collected tags from Pankaj and Srikanth.
> ---
> tools/testing/selftests/kvm/include/x86/sev.h | 2 ++
> tools/testing/selftests/kvm/x86/sev_smoke_test.c | 2 +-
> 2 files changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/tools/testing/selftests/kvm/include/x86/sev.h b/tools/testing/selftests/kvm/include/x86/sev.h
> index 82c11c81a956..e7df5d0987f6 100644
> --- a/tools/testing/selftests/kvm/include/x86/sev.h
> +++ b/tools/testing/selftests/kvm/include/x86/sev.h
> @@ -27,6 +27,8 @@ enum sev_guest_state {
>
> #define GHCB_MSR_TERM_REQ 0x100
>
> +#define VMGEXIT() { __asm__ __volatile__("rep; vmmcall"); }
Please make this a proper inline function, there's no reason to use a macro.
^ permalink raw reply
* Re: [PATCH v6 2/9] KVM: SEV: Disable SEV on platform init failure
From: Sean Christopherson @ 2025-02-12 1:58 UTC (permalink / raw)
To: Pratik R. Sampat
Cc: linux-kernel, x86, kvm, linux-crypto, linux-kselftest, pbonzini,
thomas.lendacky, tglx, mingo, bp, dave.hansen, shuah, pgonda,
ashish.kalra, nikunj, pankaj.gupta, michael.roth, sraithal
In-Reply-To: <20250203223205.36121-3-prsampat@amd.com>
On Mon, Feb 03, 2025, Pratik R. Sampat wrote:
> If the platform initialization sev_platform_init() fails, SEV cannot be
> set up and a secure VM cannot be spawned. Therefore, in this case,
> ensure that KVM does not set up, nor advertise support for SEV, SEV-ES,
> and SEV-SNP.
>
> Suggested-by: Nikunj A Dadhania <nikunj@amd.com>
> Tested-by: Srikanth Aithal <sraithal@amd.com>
> Signed-off-by: Pratik R. Sampat <prsampat@amd.com>
> ---
> v5..v6:
>
> * Rename is_sev_platform_init to sev_fw_initialized (Nikunj)
> * Collected tags from Srikanth.
> ---
> arch/x86/kvm/svm/sev.c | 2 +-
> drivers/crypto/ccp/sev-dev.c | 10 ++++++++++
> include/linux/psp-sev.h | 3 +++
> 3 files changed, 14 insertions(+), 1 deletion(-)
>
> diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
> index b709c2f0945c..42d1309f8a54 100644
> --- a/arch/x86/kvm/svm/sev.c
> +++ b/arch/x86/kvm/svm/sev.c
> @@ -2957,7 +2957,7 @@ void __init sev_hardware_setup(void)
> bool sev_es_supported = false;
> bool sev_supported = false;
>
> - if (!sev_enabled || !npt_enabled || !nrips)
> + if (!sev_fw_initialized() || !sev_enabled || !npt_enabled || !nrips)
> goto out;
Me thinks this wasn't tested with KVM_AMD built-in[1]. I'm pretty sure Ashish's
fix[2] solves all of this?
[1] https://lore.kernel.org/all/d6d08c6b-9602-4f3d-92c2-8db6d50a1b92@amd.com
[2] https://lore.kernel.org/all/f78ddb64087df27e7bcb1ae0ab53f55aa0804fab.1739226950.git.ashish.kalra@amd.com
^ permalink raw reply
* Re: [PATCH v6 1/9] KVM: SEV: Disable SEV-SNP on FW validation failure
From: Sean Christopherson @ 2025-02-12 1:54 UTC (permalink / raw)
To: Pratik R. Sampat
Cc: linux-kernel, x86, kvm, linux-crypto, linux-kselftest, pbonzini,
thomas.lendacky, tglx, mingo, bp, dave.hansen, shuah, pgonda,
ashish.kalra, nikunj, pankaj.gupta, michael.roth, sraithal
In-Reply-To: <20250203223205.36121-2-prsampat@amd.com>
On Mon, Feb 03, 2025, Pratik R. Sampat wrote:
> diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
> index 0f04f365885c..b709c2f0945c 100644
> --- a/arch/x86/kvm/svm/sev.c
> +++ b/arch/x86/kvm/svm/sev.c
> @@ -3040,7 +3040,9 @@ void __init sev_hardware_setup(void)
> sev_es_asid_count = min_sev_asid - 1;
> WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV_ES, sev_es_asid_count));
> sev_es_supported = true;
> - sev_snp_supported = sev_snp_enabled && cc_platform_has(CC_ATTR_HOST_SEV_SNP);
> + sev_snp_supported = (sev_snp_enabled &&
> + cc_platform_has(CC_ATTR_HOST_SEV_SNP) &&
> + snp_fw_valid());
>
> out:
> if (boot_cpu_has(X86_FEATURE_SEV))
> diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
> index af018afd9cd7..b45cd60c19b0 100644
> --- a/drivers/crypto/ccp/sev-dev.c
> +++ b/drivers/crypto/ccp/sev-dev.c
> @@ -122,6 +122,12 @@ static inline bool sev_version_greater_or_equal(u8 maj, u8 min)
> return false;
> }
>
> +bool snp_fw_valid(void)
> +{
> + return sev_version_greater_or_equal(SNP_MIN_API_MAJOR, SNP_MIN_API_MINOR);
This lacks any sense of abstraction. KVM doesn't care if the firmware is valid,
KVM only cares if SNP is support. KVM _must_ run after ASP initialization[*],
so I'm pretty sure KVM just needs a way to query sev->snp_initialized.
[*] https://lore.kernel.org/all/f78ddb64087df27e7bcb1ae0ab53f55aa0804fab.1739226950.git.ashish.kalra@amd.com
^ permalink raw reply
* Re: [PATCH v4 0/3] Fix broken SNP support with KVM module built-in
From: Sean Christopherson @ 2025-02-11 21:31 UTC (permalink / raw)
To: Ashish Kalra
Cc: pbonzini, tglx, mingo, bp, dave.hansen, x86, hpa, thomas.lendacky,
john.allen, herbert, davem, joro, suravee.suthikulpanit, will,
robin.murphy, michael.roth, dionnaglaze, nikunj, ardb,
kevinloughlin, Neeraj.Upadhyay, vasant.hegde, Stable, kvm,
linux-kernel, linux-crypto, linux-coco, iommu
In-Reply-To: <cover.1739226950.git.ashish.kalra@amd.com>
On Mon, Feb 10, 2025, Ashish Kalra wrote:
> Ashish Kalra (1):
> x86/sev: Fix broken SNP support with KVM module built-in
>
> Sean Christopherson (2):
> crypto: ccp: Add external API interface for PSP module initialization
> KVM: SVM: Ensure PSP module is initialized if KVM module is built-in
Unless I've overlooked a dependency, patch 3 (IOMMU vs. RMP) is entirely
independent of patches 1 and 2 (PSP vs. KVM). If no one objects, I'll take the
first two patches through the kvm-x86 tree, and let the tip/iommu maintainers
sort out the last patch.
> arch/x86/include/asm/sev.h | 2 ++
> arch/x86/kvm/svm/sev.c | 10 ++++++++++
> arch/x86/virt/svm/sev.c | 23 +++++++----------------
> drivers/crypto/ccp/sp-dev.c | 14 ++++++++++++++
> drivers/iommu/amd/init.c | 34 ++++++++++++++++++++++++++++++----
> include/linux/psp-sev.h | 9 +++++++++
> 6 files changed, 72 insertions(+), 20 deletions(-)
>
> --
> 2.34.1
>
^ permalink raw reply
* Re: [PATCH v6 00/16] zswap IAA compress batching
From: Nhat Pham @ 2025-02-11 17:52 UTC (permalink / raw)
To: Eric Biggers
Cc: Kanchana P Sridhar, linux-kernel, linux-mm, hannes, yosry.ahmed,
chengming.zhou, usamaarif642, ryan.roberts, 21cnbao, akpm,
linux-crypto, herbert, davem, clabbe, ardb, surenb,
kristen.c.accardi, wajdi.k.feghali, vinodh.gopal
In-Reply-To: <20250211170513.GB1227@sol.localdomain>
On Tue, Feb 11, 2025 at 9:05 AM Eric Biggers <ebiggers@kernel.org> wrote:
>
> On Wed, Feb 05, 2025 at 11:20:46PM -0800, Kanchana P Sridhar wrote:
>
> So, zswap is passed a large folio to swap out, and it divides it into 4K pages
> and compresses each independently. The performance improvement in this patchset
> comes entirely from compressing the folio's pages in parallel, synchronously,
> using IAA.
>
> Before even considering IAA and going through all the pain of supporting
> batching with an off-CPU offload, wouldn't it make a lot more sense to try just
> compressing each folio in software as a single unit? Compared to the existing
> approach of compressing the folio in 4K chunks, that should be much faster and
> produce a much better compression ratio. Compression algorithms are very much
> designed for larger amounts of data, so that they can find more matches.
>
> It looks like the mm subsystem used to always break up folios when swapping them
> out, but that is now been fixed. It looks like zswap just hasn't been updated
> to do otherwise yet?
>
> FWIW, here are some speed and compression ratio results I collected in a
> compression benchmark module that tests feeding vmlinux (uncompressed_size:
> 26624 KiB) though zstd in 4 KiB page or 2 MiB folio-sized chunks:
>
> zstd level 3, 4K chunks: 86 ms; compressed_size 9429 KiB
> zstd level 3, 2M chunks: 57 ms; compressed_size 8251 KiB
> zstd level 1, 4K chunks: 65 ms; compressed_size 9806 KiB
> zstd level 1, 2M chunks: 34 ms; compressed_size 8878 KiB
>
> The current zswap parameterization is "zstd level 3, 4K chunks". I would
> recommend "zstd level 1, 2M chunks", which would be 2.5 times as fast and give a
> 6% better compression ratio.
>
> What is preventing zswap from compressing whole folios?
Thanks for the input, Eric! That was one of the directions we have
been exploring for zswap and zram. Here's what's going on:
The first issue is zsmalloc, which is the backend memory allocator for
zswap, currently does not support larger-than-4K object size. Barry
Song is working on this:
https://lore.kernel.org/linux-mm/20241121222521.83458-1-21cnbao@gmail.com/
Performance-wise, compressing whole folios also means that at swap-in
time, you have to decompress and load the entire folio/chunk. This can
create extra memory pressure (for example, you have to either allocate
a huge page or multiple small pages for the folio/chunk), which is
particularly bad when the system is already in trouble :) I believe
that is one of the blockers for the above patch series as well.
^ permalink raw reply
* [PATCH v2 10/10] crypto: tegra: Use HMAC fallback when keyslots are full
From: Akhil R @ 2025-02-11 17:17 UTC (permalink / raw)
To: herbert, davem, thierry.reding, jonathanh, linux-crypto,
linux-tegra, linux-kernel
Cc: Akhil R
In-Reply-To: <20250211171713.65770-1-akhilrajeev@nvidia.com>
The intermediate results for HMAC is stored in the allocated keyslot by
the hardware. Dynamic allocation of keyslot during an operation is hence
not possible. As the number of keyslots are limited in the hardware,
fallback to the HMAC software implementation if keyslots are not available
Fixes: 0880bb3b00c8 ("crypto: tegra - Add Tegra Security Engine driver")
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
---
drivers/crypto/tegra/tegra-se-hash.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/crypto/tegra/tegra-se-hash.c b/drivers/crypto/tegra/tegra-se-hash.c
index 89c1e1a0016b..c607a37d5e0e 100644
--- a/drivers/crypto/tegra/tegra-se-hash.c
+++ b/drivers/crypto/tegra/tegra-se-hash.c
@@ -631,13 +631,18 @@ static int tegra_hmac_setkey(struct crypto_ahash *tfm, const u8 *key,
unsigned int keylen)
{
struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
+ int ret;
if (aes_check_keylen(keylen))
return tegra_hmac_fallback_setkey(ctx, key, keylen);
+ ret = tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
+ if (ret)
+ return tegra_hmac_fallback_setkey(ctx, key, keylen);
+
ctx->fallback = false;
- return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
+ return 0;
}
static int tegra_sha_init(struct ahash_request *req)
--
2.43.2
^ permalink raw reply related
* [PATCH v2 09/10] crypto: tegra: Reserve keyslots to allocate dynamically
From: Akhil R @ 2025-02-11 17:17 UTC (permalink / raw)
To: herbert, davem, thierry.reding, jonathanh, linux-crypto,
linux-tegra, linux-kernel
Cc: Akhil R
In-Reply-To: <20250211171713.65770-1-akhilrajeev@nvidia.com>
The HW supports only storing 15 keys at a time. This limits the number
of tfms that can work without failutes. Reserve keyslots to solve this
and use the reserved ones during the encryption/decryption operation.
This allow users to have the capability of hardware protected keys
and faster operations if there are limited number of tfms while not
halting the operation if there are more tfms.
Fixes: 0880bb3b00c8 ("crypto: tegra - Add Tegra Security Engine driver")
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
---
drivers/crypto/tegra/tegra-se-aes.c | 139 +++++++++++++++++++++++-----
drivers/crypto/tegra/tegra-se-key.c | 17 ++++
drivers/crypto/tegra/tegra-se.h | 28 ++++++
3 files changed, 163 insertions(+), 21 deletions(-)
diff --git a/drivers/crypto/tegra/tegra-se-aes.c b/drivers/crypto/tegra/tegra-se-aes.c
index 196f3b7ad7bb..212ab20e54d7 100644
--- a/drivers/crypto/tegra/tegra-se-aes.c
+++ b/drivers/crypto/tegra/tegra-se-aes.c
@@ -28,6 +28,9 @@ struct tegra_aes_ctx {
u32 ivsize;
u32 key1_id;
u32 key2_id;
+ u32 keylen;
+ u8 key1[AES_MAX_KEY_SIZE];
+ u8 key2[AES_MAX_KEY_SIZE];
};
struct tegra_aes_reqctx {
@@ -43,8 +46,9 @@ struct tegra_aead_ctx {
struct tegra_se *se;
unsigned int authsize;
u32 alg;
- u32 keylen;
u32 key_id;
+ u32 keylen;
+ u8 key[AES_MAX_KEY_SIZE];
};
struct tegra_aead_reqctx {
@@ -56,8 +60,8 @@ struct tegra_aead_reqctx {
unsigned int cryptlen;
unsigned int authsize;
bool encrypt;
- u32 config;
u32 crypto_config;
+ u32 config;
u32 key_id;
u32 iv[4];
u8 authdata[16];
@@ -67,6 +71,8 @@ struct tegra_cmac_ctx {
struct tegra_se *se;
unsigned int alg;
u32 key_id;
+ u32 keylen;
+ u8 key[AES_MAX_KEY_SIZE];
struct crypto_shash *fallback_tfm;
};
@@ -260,11 +266,13 @@ static int tegra_aes_do_one_req(struct crypto_engine *engine, void *areq)
struct tegra_aes_ctx *ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req));
struct tegra_aes_reqctx *rctx = skcipher_request_ctx(req);
struct tegra_se *se = ctx->se;
- unsigned int cmdlen;
+ unsigned int cmdlen, key1_id, key2_id;
int ret;
rctx->iv = (u32 *)req->iv;
rctx->len = req->cryptlen;
+ key1_id = ctx->key1_id;
+ key2_id = ctx->key2_id;
/* Pad input to AES Block size */
if (ctx->alg != SE_ALG_XTS) {
@@ -282,6 +290,29 @@ static int tegra_aes_do_one_req(struct crypto_engine *engine, void *areq)
scatterwalk_map_and_copy(rctx->datbuf.buf, req->src, 0, req->cryptlen, 0);
+ rctx->config = tegra234_aes_cfg(ctx->alg, rctx->encrypt);
+ rctx->crypto_config = tegra234_aes_crypto_cfg(ctx->alg, rctx->encrypt);
+
+ if (!key1_id) {
+ ret = tegra_key_submit_reserved_aes(ctx->se, ctx->key1,
+ ctx->keylen, ctx->alg, &key1_id);
+ if (ret)
+ goto out;
+ }
+
+ rctx->crypto_config |= SE_AES_KEY_INDEX(key1_id);
+
+ if (ctx->alg == SE_ALG_XTS) {
+ if (!key2_id) {
+ ret = tegra_key_submit_reserved_xts(ctx->se, ctx->key2,
+ ctx->keylen, ctx->alg, &key2_id);
+ if (ret)
+ goto out;
+ }
+
+ rctx->crypto_config |= SE_AES_KEY2_INDEX(key2_id);
+ }
+
/* Prepare the command and submit for execution */
cmdlen = tegra_aes_prep_cmd(ctx, rctx);
ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen);
@@ -290,10 +321,17 @@ static int tegra_aes_do_one_req(struct crypto_engine *engine, void *areq)
tegra_aes_update_iv(req, ctx);
scatterwalk_map_and_copy(rctx->datbuf.buf, req->dst, 0, req->cryptlen, 1);
+out:
/* Free the buffer */
dma_free_coherent(ctx->se->dev, rctx->datbuf.size,
rctx->datbuf.buf, rctx->datbuf.addr);
+ if (tegra_key_is_reserved(key1_id))
+ tegra_key_invalidate_reserved(ctx->se, key1_id, ctx->alg);
+
+ if (tegra_key_is_reserved(key2_id))
+ tegra_key_invalidate_reserved(ctx->se, key2_id, ctx->alg);
+
out_finalize:
crypto_finalize_skcipher_request(se->engine, req, ret);
@@ -316,6 +354,7 @@ static int tegra_aes_cra_init(struct crypto_skcipher *tfm)
ctx->se = se_alg->se_dev;
ctx->key1_id = 0;
ctx->key2_id = 0;
+ ctx->keylen = 0;
algname = crypto_tfm_alg_name(&tfm->base);
ret = se_algname_to_algid(algname);
@@ -344,13 +383,20 @@ static int tegra_aes_setkey(struct crypto_skcipher *tfm,
const u8 *key, u32 keylen)
{
struct tegra_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
+ int ret;
if (aes_check_keylen(keylen)) {
dev_dbg(ctx->se->dev, "invalid key length (%d)\n", keylen);
return -EINVAL;
}
- return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key1_id);
+ ret = tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key1_id);
+ if (ret) {
+ ctx->keylen = keylen;
+ memcpy(ctx->key1, key, keylen);
+ }
+
+ return 0;
}
static int tegra_xts_setkey(struct crypto_skcipher *tfm,
@@ -368,11 +414,17 @@ static int tegra_xts_setkey(struct crypto_skcipher *tfm,
ret = tegra_key_submit(ctx->se, key, len,
ctx->alg, &ctx->key1_id);
- if (ret)
- return ret;
+ if (ret) {
+ ctx->keylen = len;
+ memcpy(ctx->key1, key, len);
+ }
- return tegra_key_submit(ctx->se, key + len, len,
+ ret = tegra_key_submit(ctx->se, key + len, len,
ctx->alg, &ctx->key2_id);
+ if (ret) {
+ ctx->keylen = len;
+ memcpy(ctx->key2, key + len, len);
+ }
return 0;
}
@@ -450,12 +502,6 @@ static int tegra_aes_crypt(struct skcipher_request *req, bool encrypt)
req->iv = NULL;
rctx->encrypt = encrypt;
- rctx->config = tegra234_aes_cfg(ctx->alg, encrypt);
- rctx->crypto_config = tegra234_aes_crypto_cfg(ctx->alg, encrypt);
- rctx->crypto_config |= SE_AES_KEY_INDEX(ctx->key1_id);
-
- if (ctx->key2_id)
- rctx->crypto_config |= SE_AES_KEY2_INDEX(ctx->key2_id);
return crypto_transfer_skcipher_request_to_engine(ctx->se->engine, req);
}
@@ -721,7 +767,7 @@ static int tegra_gcm_do_gmac(struct tegra_aead_ctx *ctx, struct tegra_aead_reqct
rctx->config = tegra234_aes_cfg(SE_ALG_GMAC, rctx->encrypt);
rctx->crypto_config = tegra234_aes_crypto_cfg(SE_ALG_GMAC, rctx->encrypt) |
- SE_AES_KEY_INDEX(ctx->key_id);
+ SE_AES_KEY_INDEX(rctx->key_id);
cmdlen = tegra_gmac_prep_cmd(ctx, rctx);
@@ -738,7 +784,7 @@ static int tegra_gcm_do_crypt(struct tegra_aead_ctx *ctx, struct tegra_aead_reqc
rctx->config = tegra234_aes_cfg(SE_ALG_GCM, rctx->encrypt);
rctx->crypto_config = tegra234_aes_crypto_cfg(SE_ALG_GCM, rctx->encrypt) |
- SE_AES_KEY_INDEX(ctx->key_id);
+ SE_AES_KEY_INDEX(rctx->key_id);
/* Prepare command and submit */
cmdlen = tegra_gcm_crypt_prep_cmd(ctx, rctx);
@@ -761,7 +807,7 @@ static int tegra_gcm_do_final(struct tegra_aead_ctx *ctx, struct tegra_aead_reqc
rctx->config = tegra234_aes_cfg(SE_ALG_GCM_FINAL, rctx->encrypt);
rctx->crypto_config = tegra234_aes_crypto_cfg(SE_ALG_GCM_FINAL, rctx->encrypt) |
- SE_AES_KEY_INDEX(ctx->key_id);
+ SE_AES_KEY_INDEX(rctx->key_id);
/* Prepare command and submit */
cmdlen = tegra_gcm_prep_final_cmd(se, cpuvaddr, rctx);
@@ -892,7 +938,7 @@ static int tegra_ccm_do_cbcmac(struct tegra_aead_ctx *ctx, struct tegra_aead_req
rctx->config = tegra234_aes_cfg(SE_ALG_CBC_MAC, rctx->encrypt);
rctx->crypto_config = tegra234_aes_crypto_cfg(SE_ALG_CBC_MAC,
rctx->encrypt) |
- SE_AES_KEY_INDEX(ctx->key_id);
+ SE_AES_KEY_INDEX(rctx->key_id);
/* Prepare command and submit */
cmdlen = tegra_cbcmac_prep_cmd(ctx, rctx);
@@ -1079,7 +1125,7 @@ static int tegra_ccm_do_ctr(struct tegra_aead_ctx *ctx, struct tegra_aead_reqctx
rctx->config = tegra234_aes_cfg(SE_ALG_CTR, rctx->encrypt);
rctx->crypto_config = tegra234_aes_crypto_cfg(SE_ALG_CTR, rctx->encrypt) |
- SE_AES_KEY_INDEX(ctx->key_id);
+ SE_AES_KEY_INDEX(rctx->key_id);
/* Copy authdata in the top of buffer for encryption/decryption */
if (rctx->encrypt)
@@ -1160,6 +1206,8 @@ static int tegra_ccm_do_one_req(struct crypto_engine *engine, void *areq)
if (ret)
goto out_finalize;
+ rctx->key_id = ctx->key_id;
+
/* Allocate buffers required */
rctx->inbuf.size = rctx->assoclen + rctx->authsize + rctx->cryptlen + 100;
rctx->inbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->inbuf.size,
@@ -1175,6 +1223,13 @@ static int tegra_ccm_do_one_req(struct crypto_engine *engine, void *areq)
goto out_free_inbuf;
}
+ if (!ctx->key_id) {
+ ret = tegra_key_submit_reserved_aes(ctx->se, ctx->key,
+ ctx->keylen, ctx->alg, &rctx->key_id);
+ if (ret)
+ goto out;
+ }
+
if (rctx->encrypt) {
/* CBC MAC Operation */
ret = tegra_ccm_compute_auth(ctx, rctx);
@@ -1205,6 +1260,9 @@ static int tegra_ccm_do_one_req(struct crypto_engine *engine, void *areq)
dma_free_coherent(ctx->se->dev, rctx->outbuf.size,
rctx->inbuf.buf, rctx->inbuf.addr);
+ if (tegra_key_is_reserved(rctx->key_id))
+ tegra_key_invalidate_reserved(ctx->se, rctx->key_id, ctx->alg);
+
out_finalize:
crypto_finalize_aead_request(ctx->se->engine, req, ret);
@@ -1232,6 +1290,8 @@ static int tegra_gcm_do_one_req(struct crypto_engine *engine, void *areq)
memcpy(rctx->iv, req->iv, GCM_AES_IV_SIZE);
rctx->iv[3] = (1 << 24);
+ rctx->key_id = ctx->key_id;
+
/* Allocate buffers required */
rctx->inbuf.size = rctx->assoclen + rctx->authsize + rctx->cryptlen;
rctx->inbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->inbuf.size,
@@ -1249,6 +1309,13 @@ static int tegra_gcm_do_one_req(struct crypto_engine *engine, void *areq)
goto out_free_inbuf;
}
+ if (!ctx->key_id) {
+ ret = tegra_key_submit_reserved_aes(ctx->se, ctx->key,
+ ctx->keylen, ctx->alg, &rctx->key_id);
+ if (ret)
+ goto out;
+ }
+
/* If there is associated data perform GMAC operation */
if (rctx->assoclen) {
ret = tegra_gcm_do_gmac(ctx, rctx);
@@ -1279,6 +1346,9 @@ static int tegra_gcm_do_one_req(struct crypto_engine *engine, void *areq)
dma_free_coherent(ctx->se->dev, rctx->inbuf.size,
rctx->inbuf.buf, rctx->inbuf.addr);
+ if (tegra_key_is_reserved(rctx->key_id))
+ tegra_key_invalidate_reserved(ctx->se, rctx->key_id, ctx->alg);
+
out_finalize:
crypto_finalize_aead_request(ctx->se->engine, req, ret);
@@ -1301,6 +1371,7 @@ static int tegra_aead_cra_init(struct crypto_aead *tfm)
ctx->se = se_alg->se_dev;
ctx->key_id = 0;
+ ctx->keylen = 0;
ret = se_algname_to_algid(algname);
if (ret < 0) {
@@ -1382,13 +1453,20 @@ static int tegra_aead_setkey(struct crypto_aead *tfm,
const u8 *key, u32 keylen)
{
struct tegra_aead_ctx *ctx = crypto_aead_ctx(tfm);
+ int ret;
if (aes_check_keylen(keylen)) {
dev_dbg(ctx->se->dev, "invalid key length (%d)\n", keylen);
return -EINVAL;
}
- return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
+ ret = tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
+ if (ret) {
+ ctx->keylen = keylen;
+ memcpy(ctx->key, key, keylen);
+ }
+
+ return 0;
}
static unsigned int tegra_cmac_prep_cmd(struct tegra_cmac_ctx *ctx,
@@ -1473,6 +1551,7 @@ static int tegra_cmac_do_init(struct ahash_request *req)
rctx->total_len = 0;
rctx->datbuf.size = 0;
rctx->residue.size = 0;
+ rctx->key_id = ctx->key_id;
rctx->task |= SHA_FIRST;
rctx->blk_size = crypto_ahash_blocksize(tfm);
@@ -1517,7 +1596,7 @@ static int tegra_cmac_do_update(struct ahash_request *req)
rctx->datbuf.size = (req->nbytes + rctx->residue.size) - nresidue;
rctx->total_len += rctx->datbuf.size;
rctx->config = tegra234_aes_cfg(SE_ALG_CMAC, 0);
- rctx->crypto_config = SE_AES_KEY_INDEX(ctx->key_id);
+ rctx->crypto_config = SE_AES_KEY_INDEX(rctx->key_id);
/*
* Keep one block and residue bytes in residue and
@@ -1643,6 +1722,13 @@ static int tegra_cmac_do_one_req(struct crypto_engine *engine, void *areq)
rctx->task &= ~SHA_INIT;
}
+ if (!ctx->key_id) {
+ ret = tegra_key_submit_reserved_aes(ctx->se, ctx->key,
+ ctx->keylen, ctx->alg, &rctx->key_id);
+ if (ret)
+ goto out;
+ }
+
if (rctx->task & SHA_UPDATE) {
ret = tegra_cmac_do_update(req);
if (ret)
@@ -1659,6 +1745,9 @@ static int tegra_cmac_do_one_req(struct crypto_engine *engine, void *areq)
rctx->task &= ~SHA_FINAL;
}
out:
+ if (tegra_key_is_reserved(rctx->key_id))
+ tegra_key_invalidate_reserved(ctx->se, rctx->key_id, ctx->alg);
+
crypto_finalize_hash_request(se->engine, req, ret);
return 0;
@@ -1699,6 +1788,7 @@ static int tegra_cmac_cra_init(struct crypto_tfm *tfm)
ctx->se = se_alg->se_dev;
ctx->key_id = 0;
+ ctx->keylen = 0;
ret = se_algname_to_algid(algname);
if (ret < 0) {
@@ -1727,6 +1817,7 @@ static int tegra_cmac_setkey(struct crypto_ahash *tfm, const u8 *key,
unsigned int keylen)
{
struct tegra_cmac_ctx *ctx = crypto_ahash_ctx(tfm);
+ int ret;
if (aes_check_keylen(keylen)) {
dev_dbg(ctx->se->dev, "invalid key length (%d)\n", keylen);
@@ -1736,7 +1827,13 @@ static int tegra_cmac_setkey(struct crypto_ahash *tfm, const u8 *key,
if (ctx->fallback_tfm)
crypto_shash_setkey(ctx->fallback_tfm, key, keylen);
- return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
+ ret = tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
+ if (ret) {
+ ctx->keylen = keylen;
+ memcpy(ctx->key, key, keylen);
+ }
+
+ return 0;
}
static int tegra_cmac_init(struct ahash_request *req)
diff --git a/drivers/crypto/tegra/tegra-se-key.c b/drivers/crypto/tegra/tegra-se-key.c
index 276b261fb6df..bf265514b04c 100644
--- a/drivers/crypto/tegra/tegra-se-key.c
+++ b/drivers/crypto/tegra/tegra-se-key.c
@@ -141,6 +141,23 @@ void tegra_key_invalidate(struct tegra_se *se, u32 keyid, u32 alg)
tegra_keyslot_free(keyid);
}
+void tegra_key_invalidate_reserved(struct tegra_se *se, u32 keyid, u32 alg)
+{
+ u8 zkey[AES_MAX_KEY_SIZE] = {0};
+
+ if (!keyid)
+ return;
+
+ /* Overwrite the key with 0s */
+ tegra_key_insert(se, zkey, AES_MAX_KEY_SIZE, keyid, alg);
+}
+
+inline int tegra_key_submit_reserved(struct tegra_se *se, const u8 *key,
+ u32 keylen, u32 alg, u32 *keyid)
+{
+ return tegra_key_insert(se, key, keylen, *keyid, alg);
+}
+
int tegra_key_submit(struct tegra_se *se, const u8 *key, u32 keylen, u32 alg, u32 *keyid)
{
int ret;
diff --git a/drivers/crypto/tegra/tegra-se.h b/drivers/crypto/tegra/tegra-se.h
index 0f5bcf27358b..5e997b04a8e8 100644
--- a/drivers/crypto/tegra/tegra-se.h
+++ b/drivers/crypto/tegra/tegra-se.h
@@ -342,6 +342,9 @@
#define SE_MAX_KEYSLOT 15
#define SE_MAX_MEM_ALLOC SZ_4M
+#define TEGRA_AES_RESERVED_KSLT 14
+#define TEGRA_XTS_RESERVED_KSLT 15
+
#define SHA_FIRST BIT(0)
#define SHA_INIT BIT(1)
#define SHA_UPDATE BIT(2)
@@ -502,9 +505,34 @@ void tegra_deinit_aes(struct tegra_se *se);
void tegra_deinit_hash(struct tegra_se *se);
int tegra_key_submit(struct tegra_se *se, const u8 *key,
u32 keylen, u32 alg, u32 *keyid);
+
+inline int tegra_key_submit_reserved(struct tegra_se *se, const u8 *key,
+ u32 keylen, u32 alg, u32 *keyid);
+
void tegra_key_invalidate(struct tegra_se *se, u32 keyid, u32 alg);
+void tegra_key_invalidate_reserved(struct tegra_se *se, u32 keyid, u32 alg);
int tegra_se_host1x_submit(struct tegra_se *se, struct tegra_se_cmdbuf *cmdbuf, u32 size);
+static inline int tegra_key_submit_reserved_aes(struct tegra_se *se, const u8 *key,
+ u32 keylen, u32 alg, u32 *keyid)
+{
+ *keyid = TEGRA_AES_RESERVED_KSLT;
+ return tegra_key_submit_reserved(se, key, keylen, alg, keyid);
+}
+
+static inline int tegra_key_submit_reserved_xts(struct tegra_se *se, const u8 *key,
+ u32 keylen, u32 alg, u32 *keyid)
+{
+ *keyid = TEGRA_XTS_RESERVED_KSLT;
+ return tegra_key_submit_reserved(se, key, keylen, alg, keyid);
+}
+
+static inline bool tegra_key_is_reserved(u32 keyid)
+{
+ return ((keyid == TEGRA_AES_RESERVED_KSLT) ||
+ (keyid == TEGRA_XTS_RESERVED_KSLT));
+}
+
/* HOST1x OPCODES */
static inline u32 host1x_opcode_setpayload(unsigned int payload)
{
--
2.43.2
^ permalink raw reply related
* [PATCH v2 08/10] crypto: tegra: Set IV to NULL explicitly for AES ECB
From: Akhil R @ 2025-02-11 17:17 UTC (permalink / raw)
To: herbert, davem, thierry.reding, jonathanh, linux-crypto,
linux-tegra, linux-kernel
Cc: Akhil R
In-Reply-To: <20250211171713.65770-1-akhilrajeev@nvidia.com>
It may happen that the variable req->iv may have stale values or
zero sized buffer by default and may end up getting used during
encryption/decryption. This inturn may corrupt the results or break the
operation. Set the req->iv variable to NULL explicitly for algorithms
like AES-ECB where IV is not used.
Fixes: 0880bb3b00c8 ("crypto: tegra - Add Tegra Security Engine driver")
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
---
drivers/crypto/tegra/tegra-se-aes.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/crypto/tegra/tegra-se-aes.c b/drivers/crypto/tegra/tegra-se-aes.c
index c97dc2043b3d..196f3b7ad7bb 100644
--- a/drivers/crypto/tegra/tegra-se-aes.c
+++ b/drivers/crypto/tegra/tegra-se-aes.c
@@ -446,6 +446,9 @@ static int tegra_aes_crypt(struct skcipher_request *req, bool encrypt)
if (!req->cryptlen)
return 0;
+ if (ctx->alg == SE_ALG_ECB)
+ req->iv = NULL;
+
rctx->encrypt = encrypt;
rctx->config = tegra234_aes_cfg(ctx->alg, encrypt);
rctx->crypto_config = tegra234_aes_crypto_cfg(ctx->alg, encrypt);
--
2.43.2
^ permalink raw reply related
* [PATCH v2 07/10] crypto: tegra: Fix CMAC intermediate result handling
From: Akhil R @ 2025-02-11 17:17 UTC (permalink / raw)
To: herbert, davem, thierry.reding, jonathanh, linux-crypto,
linux-tegra, linux-kernel
Cc: Akhil R
In-Reply-To: <20250211171713.65770-1-akhilrajeev@nvidia.com>
Saving and restoring of the intermediate results are needed if there is
context switch caused by another ongoing request on the same engine.
This is therefore not only to support import/export functionality.
Hence, save and restore the intermediate result for every non-first task.
Fixes: 0880bb3b00c8 ("crypto: tegra - Add Tegra Security Engine driver")
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
---
drivers/crypto/tegra/tegra-se-aes.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/crypto/tegra/tegra-se-aes.c b/drivers/crypto/tegra/tegra-se-aes.c
index 2d5a59f0b249..c97dc2043b3d 100644
--- a/drivers/crypto/tegra/tegra-se-aes.c
+++ b/drivers/crypto/tegra/tegra-se-aes.c
@@ -1547,9 +1547,8 @@ static int tegra_cmac_do_update(struct ahash_request *req)
rctx->residue.size = nresidue;
/*
- * If this is not the first 'update' call, paste the previous copied
+ * If this is not the first task, paste the previous copied
* intermediate results to the registers so that it gets picked up.
- * This is to support the import/export functionality.
*/
if (!(rctx->task & SHA_FIRST))
tegra_cmac_paste_result(ctx->se, rctx);
@@ -1557,13 +1556,7 @@ static int tegra_cmac_do_update(struct ahash_request *req)
cmdlen = tegra_cmac_prep_cmd(ctx, rctx);
ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen);
- /*
- * If this is not the final update, copy the intermediate results
- * from the registers so that it can be used in the next 'update'
- * call. This is to support the import/export functionality.
- */
- if (!(rctx->task & SHA_FINAL))
- tegra_cmac_copy_result(ctx->se, rctx);
+ tegra_cmac_copy_result(ctx->se, rctx);
dma_free_coherent(ctx->se->dev, rctx->datbuf.size,
rctx->datbuf.buf, rctx->datbuf.addr);
@@ -1600,6 +1593,13 @@ static int tegra_cmac_do_final(struct ahash_request *req)
rctx->total_len += rctx->residue.size;
rctx->config = tegra234_aes_cfg(SE_ALG_CMAC, 0);
+ /*
+ * If this is not the first task, paste the previous copied
+ * intermediate results to the registers so that it gets picked up.
+ */
+ if (!(rctx->task & SHA_FIRST))
+ tegra_cmac_paste_result(ctx->se, rctx);
+
/* Prepare command and submit */
cmdlen = tegra_cmac_prep_cmd(ctx, rctx);
ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen);
--
2.43.2
^ permalink raw reply related
* [PATCH v2 06/10] crypto: tegra: Fix HASH intermediate result handling
From: Akhil R @ 2025-02-11 17:17 UTC (permalink / raw)
To: herbert, davem, thierry.reding, jonathanh, linux-crypto,
linux-tegra, linux-kernel
Cc: Akhil R
In-Reply-To: <20250211171713.65770-1-akhilrajeev@nvidia.com>
The intermediate hash values generated during an update task were
handled incorrectly in the driver. The values have a defined format for
each algorithm. Copying and pasting from the HASH_RESULT register
balantly would not work for all the supported algorithms. This incorrect
handling causes failures when there is a context switch between multiple
operations.
To handle the expected format correctly, add a separate buffer for
storing the intermediate results for each request. Remove the previous
copy/paste functions which read/wrote to the registers directly. Instead
configure the hardware to get the intermediate result copied to the
buffer and use host1x path to restore the intermediate hash results.
Fixes: 0880bb3b00c8 ("crypto: tegra - Add Tegra Security Engine driver")
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
---
drivers/crypto/tegra/tegra-se-hash.c | 148 +++++++++++++++++----------
drivers/crypto/tegra/tegra-se.h | 1 +
2 files changed, 97 insertions(+), 52 deletions(-)
diff --git a/drivers/crypto/tegra/tegra-se-hash.c b/drivers/crypto/tegra/tegra-se-hash.c
index 6da18f0f7ce9..89c1e1a0016b 100644
--- a/drivers/crypto/tegra/tegra-se-hash.c
+++ b/drivers/crypto/tegra/tegra-se-hash.c
@@ -34,6 +34,7 @@ struct tegra_sha_reqctx {
struct tegra_se_datbuf datbuf;
struct tegra_se_datbuf residue;
struct tegra_se_datbuf digest;
+ struct tegra_se_datbuf intr_res;
unsigned int alg;
unsigned int config;
unsigned int total_len;
@@ -211,9 +212,61 @@ static int tegra_sha_fallback_export(struct ahash_request *req, void *out)
return crypto_ahash_export(&rctx->fallback_req, out);
}
-static int tegra_sha_prep_cmd(struct tegra_se *se, u32 *cpuvaddr,
+static int tegra_se_insert_hash_result(struct tegra_sha_ctx *ctx, u32 *cpuvaddr,
struct tegra_sha_reqctx *rctx)
{
+ u32 *res = (u32 *)rctx->intr_res.buf;
+ int i = 0, j;
+
+ cpuvaddr[i++] = 0;
+ cpuvaddr[i++] = host1x_opcode_setpayload(HASH_RESULT_REG_COUNT);
+ cpuvaddr[i++] = se_host1x_opcode_incr_w(SE_SHA_HASH_RESULT);
+
+ for (j = 0; j < HASH_RESULT_REG_COUNT; j++) {
+ int idx = j;
+
+ /*
+ * The initial, intermediate and final hash value of SHA-384, SHA-512
+ * in SHA_HASH_RESULT registers follow the below layout of bytes.
+ *
+ * +---------------+------------+
+ * | HASH_RESULT_0 | B4...B7 |
+ * +---------------+------------+
+ * | HASH_RESULT_1 | B0...B3 |
+ * +---------------+------------+
+ * | HASH_RESULT_2 | B12...B15 |
+ * +---------------+------------+
+ * | HASH_RESULT_3 | B8...B11 |
+ * +---------------+------------+
+ * | ...... |
+ * +---------------+------------+
+ * | HASH_RESULT_14| B60...B63 |
+ * +---------------+------------+
+ * | HASH_RESULT_15| B56...B59 |
+ * +---------------+------------+
+ *
+ */
+ if (ctx->alg == SE_ALG_SHA384 || ctx->alg == SE_ALG_SHA512)
+ idx = (j % 2) ? j - 1 : j + 1;
+
+ /* For SHA-1, SHA-224, SHA-256, SHA-384, SHA-512 the initial
+ * intermediate and final hash value when stored in
+ * SHA_HASH_RESULT registers, the byte order is NOT in
+ * little-endian.
+ */
+ if (ctx->alg <= SE_ALG_SHA512)
+ cpuvaddr[i++] = be32_to_cpu(res[idx]);
+ else
+ cpuvaddr[i++] = res[idx];
+ }
+
+ return i;
+}
+
+static int tegra_sha_prep_cmd(struct tegra_sha_ctx *ctx, u32 *cpuvaddr,
+ struct tegra_sha_reqctx *rctx)
+{
+ struct tegra_se *se = ctx->se;
u64 msg_len, msg_left;
int i = 0;
@@ -241,7 +294,7 @@ static int tegra_sha_prep_cmd(struct tegra_se *se, u32 *cpuvaddr,
cpuvaddr[i++] = upper_32_bits(msg_left);
cpuvaddr[i++] = 0;
cpuvaddr[i++] = 0;
- cpuvaddr[i++] = host1x_opcode_setpayload(6);
+ cpuvaddr[i++] = host1x_opcode_setpayload(2);
cpuvaddr[i++] = se_host1x_opcode_incr_w(SE_SHA_CFG);
cpuvaddr[i++] = rctx->config;
@@ -249,15 +302,29 @@ static int tegra_sha_prep_cmd(struct tegra_se *se, u32 *cpuvaddr,
cpuvaddr[i++] = SE_SHA_TASK_HASH_INIT;
rctx->task &= ~SHA_FIRST;
} else {
- cpuvaddr[i++] = 0;
+ /*
+ * If it isn't the first task, program the HASH_RESULT register
+ * with the intermediate result from the previous task
+ */
+ i += tegra_se_insert_hash_result(ctx, cpuvaddr + i, rctx);
}
+ cpuvaddr[i++] = host1x_opcode_setpayload(4);
+ cpuvaddr[i++] = se_host1x_opcode_incr_w(SE_SHA_IN_ADDR);
cpuvaddr[i++] = rctx->datbuf.addr;
cpuvaddr[i++] = (u32)(SE_ADDR_HI_MSB(upper_32_bits(rctx->datbuf.addr)) |
SE_ADDR_HI_SZ(rctx->datbuf.size));
- cpuvaddr[i++] = rctx->digest.addr;
- cpuvaddr[i++] = (u32)(SE_ADDR_HI_MSB(upper_32_bits(rctx->digest.addr)) |
- SE_ADDR_HI_SZ(rctx->digest.size));
+
+ if (rctx->task & SHA_UPDATE) {
+ cpuvaddr[i++] = rctx->intr_res.addr;
+ cpuvaddr[i++] = (u32)(SE_ADDR_HI_MSB(upper_32_bits(rctx->intr_res.addr)) |
+ SE_ADDR_HI_SZ(rctx->intr_res.size));
+ } else {
+ cpuvaddr[i++] = rctx->digest.addr;
+ cpuvaddr[i++] = (u32)(SE_ADDR_HI_MSB(upper_32_bits(rctx->digest.addr)) |
+ SE_ADDR_HI_SZ(rctx->digest.size));
+ }
+
if (rctx->key_id) {
cpuvaddr[i++] = host1x_opcode_setpayload(1);
cpuvaddr[i++] = se_host1x_opcode_nonincr_w(SE_SHA_CRYPTO_CFG);
@@ -266,36 +333,18 @@ static int tegra_sha_prep_cmd(struct tegra_se *se, u32 *cpuvaddr,
cpuvaddr[i++] = host1x_opcode_setpayload(1);
cpuvaddr[i++] = se_host1x_opcode_nonincr_w(SE_SHA_OPERATION);
- cpuvaddr[i++] = SE_SHA_OP_WRSTALL |
- SE_SHA_OP_START |
+ cpuvaddr[i++] = SE_SHA_OP_WRSTALL | SE_SHA_OP_START |
SE_SHA_OP_LASTBUF;
cpuvaddr[i++] = se_host1x_opcode_nonincr(host1x_uclass_incr_syncpt_r(), 1);
cpuvaddr[i++] = host1x_uclass_incr_syncpt_cond_f(1) |
host1x_uclass_incr_syncpt_indx_f(se->syncpt_id);
- dev_dbg(se->dev, "msg len %llu msg left %llu cfg %#x",
- msg_len, msg_left, rctx->config);
+ dev_dbg(se->dev, "msg len %llu msg left %llu sz %lu cfg %#x",
+ msg_len, msg_left, rctx->datbuf.size, rctx->config);
return i;
}
-static void tegra_sha_copy_hash_result(struct tegra_se *se, struct tegra_sha_reqctx *rctx)
-{
- int i;
-
- for (i = 0; i < HASH_RESULT_REG_COUNT; i++)
- rctx->result[i] = readl(se->base + se->hw->regs->result + (i * 4));
-}
-
-static void tegra_sha_paste_hash_result(struct tegra_se *se, struct tegra_sha_reqctx *rctx)
-{
- int i;
-
- for (i = 0; i < HASH_RESULT_REG_COUNT; i++)
- writel(rctx->result[i],
- se->base + se->hw->regs->result + (i * 4));
-}
-
static int tegra_sha_do_init(struct ahash_request *req)
{
struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
@@ -325,8 +374,17 @@ static int tegra_sha_do_init(struct ahash_request *req)
if (!rctx->residue.buf)
goto resbuf_fail;
+ rctx->intr_res.size = HASH_RESULT_REG_COUNT * 4;
+ rctx->intr_res.buf = dma_alloc_coherent(se->dev, rctx->intr_res.size,
+ &rctx->intr_res.addr, GFP_KERNEL);
+ if (!rctx->intr_res.buf)
+ goto intr_res_fail;
+
return 0;
+intr_res_fail:
+ dma_free_coherent(se->dev, rctx->residue.size, rctx->residue.buf,
+ rctx->residue.addr);
resbuf_fail:
dma_free_coherent(se->dev, rctx->digest.size, rctx->digest.buf,
rctx->digest.addr);
@@ -356,7 +414,6 @@ static int tegra_sha_do_update(struct ahash_request *req)
rctx->src_sg = req->src;
rctx->datbuf.size = (req->nbytes + rctx->residue.size) - nresidue;
- rctx->total_len += rctx->datbuf.size;
/*
* If nbytes are less than a block size, copy it residue and
@@ -365,12 +422,12 @@ static int tegra_sha_do_update(struct ahash_request *req)
if (nblks < 1) {
scatterwalk_map_and_copy(rctx->residue.buf + rctx->residue.size,
rctx->src_sg, 0, req->nbytes, 0);
-
rctx->residue.size += req->nbytes;
+
return 0;
}
- rctx->datbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->datbuf.size,
+ rctx->datbuf.buf = dma_alloc_coherent(se->dev, rctx->datbuf.size,
&rctx->datbuf.addr, GFP_KERNEL);
if (!rctx->datbuf.buf)
return -ENOMEM;
@@ -387,31 +444,15 @@ static int tegra_sha_do_update(struct ahash_request *req)
/* Update residue value with the residue after current block */
rctx->residue.size = nresidue;
+ rctx->total_len += rctx->datbuf.size;
rctx->config = tegra_sha_get_config(rctx->alg) |
- SE_SHA_DST_HASH_REG;
-
- /*
- * If this is not the first 'update' call, paste the previous copied
- * intermediate results to the registers so that it gets picked up.
- * This is to support the import/export functionality.
- */
- if (!(rctx->task & SHA_FIRST))
- tegra_sha_paste_hash_result(se, rctx);
-
- size = tegra_sha_prep_cmd(se, cpuvaddr, rctx);
+ SE_SHA_DST_MEMORY;
+ size = tegra_sha_prep_cmd(ctx, cpuvaddr, rctx);
ret = tegra_se_host1x_submit(se, se->cmdbuf, size);
- /*
- * If this is not the final update, copy the intermediate results
- * from the registers so that it can be used in the next 'update'
- * call. This is to support the import/export functionality.
- */
- if (!(rctx->task & SHA_FINAL))
- tegra_sha_copy_hash_result(se, rctx);
-
- dma_free_coherent(ctx->se->dev, rctx->datbuf.size,
+ dma_free_coherent(se->dev, rctx->datbuf.size,
rctx->datbuf.buf, rctx->datbuf.addr);
return ret;
@@ -443,8 +484,7 @@ static int tegra_sha_do_final(struct ahash_request *req)
rctx->config = tegra_sha_get_config(rctx->alg) |
SE_SHA_DST_MEMORY;
- size = tegra_sha_prep_cmd(se, cpuvaddr, rctx);
-
+ size = tegra_sha_prep_cmd(ctx, cpuvaddr, rctx);
ret = tegra_se_host1x_submit(se, se->cmdbuf, size);
if (ret)
goto out;
@@ -461,6 +501,10 @@ static int tegra_sha_do_final(struct ahash_request *req)
rctx->residue.buf, rctx->residue.addr);
dma_free_coherent(se->dev, rctx->digest.size, rctx->digest.buf,
rctx->digest.addr);
+
+ dma_free_coherent(se->dev, rctx->intr_res.size, rctx->intr_res.buf,
+ rctx->intr_res.addr);
+
return ret;
}
diff --git a/drivers/crypto/tegra/tegra-se.h b/drivers/crypto/tegra/tegra-se.h
index e1ec37bfb80a..0f5bcf27358b 100644
--- a/drivers/crypto/tegra/tegra-se.h
+++ b/drivers/crypto/tegra/tegra-se.h
@@ -24,6 +24,7 @@
#define SE_STREAM_ID 0x90
#define SE_SHA_CFG 0x4004
+#define SE_SHA_IN_ADDR 0x400c
#define SE_SHA_KEY_ADDR 0x4094
#define SE_SHA_KEY_DATA 0x4098
#define SE_SHA_KEYMANIFEST 0x409c
--
2.43.2
^ permalink raw reply related
* [PATCH v2 05/10] crypto: tegra: Transfer HASH init function to crypto engine
From: Akhil R @ 2025-02-11 17:17 UTC (permalink / raw)
To: herbert, davem, thierry.reding, jonathanh, linux-crypto,
linux-tegra, linux-kernel
Cc: Akhil R
In-Reply-To: <20250211171713.65770-1-akhilrajeev@nvidia.com>
Ahash init() function was called asynchronous to the crypto engine queue.
This could corrupt the request context if there is any ongoing operation
for the same request. Queue the init function as well to the crypto
engine queue so that this scenario can be avoided.
Fixes: 0880bb3b00c8 ("crypto: tegra - Add Tegra Security Engine driver")
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
---
drivers/crypto/tegra/tegra-se-aes.c | 80 ++++++++++++---------
drivers/crypto/tegra/tegra-se-hash.c | 100 ++++++++++++++++-----------
drivers/crypto/tegra/tegra-se.h | 5 +-
3 files changed, 109 insertions(+), 76 deletions(-)
diff --git a/drivers/crypto/tegra/tegra-se-aes.c b/drivers/crypto/tegra/tegra-se-aes.c
index 5ca7996ecc6d..2d5a59f0b249 100644
--- a/drivers/crypto/tegra/tegra-se-aes.c
+++ b/drivers/crypto/tegra/tegra-se-aes.c
@@ -1459,6 +1459,34 @@ static void tegra_cmac_paste_result(struct tegra_se *se, struct tegra_cmac_reqct
se->base + se->hw->regs->result + (i * 4));
}
+static int tegra_cmac_do_init(struct ahash_request *req)
+{
+ struct tegra_cmac_reqctx *rctx = ahash_request_ctx(req);
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct tegra_cmac_ctx *ctx = crypto_ahash_ctx(tfm);
+ struct tegra_se *se = ctx->se;
+ int i;
+
+ rctx->total_len = 0;
+ rctx->datbuf.size = 0;
+ rctx->residue.size = 0;
+ rctx->task |= SHA_FIRST;
+ rctx->blk_size = crypto_ahash_blocksize(tfm);
+
+ rctx->residue.buf = dma_alloc_coherent(se->dev, rctx->blk_size * 2,
+ &rctx->residue.addr, GFP_KERNEL);
+ if (!rctx->residue.buf)
+ return -ENOMEM;
+
+ rctx->residue.size = 0;
+
+ /* Clear any previous result */
+ for (i = 0; i < CMAC_RESULT_REG_COUNT; i++)
+ writel(0, se->base + se->hw->regs->result + (i * 4));
+
+ return 0;
+}
+
static int tegra_cmac_do_update(struct ahash_request *req)
{
struct tegra_cmac_reqctx *rctx = ahash_request_ctx(req);
@@ -1604,6 +1632,14 @@ static int tegra_cmac_do_one_req(struct crypto_engine *engine, void *areq)
struct tegra_se *se = ctx->se;
int ret = 0;
+ if (rctx->task & SHA_INIT) {
+ ret = tegra_cmac_do_init(req);
+ if (ret)
+ goto out;
+
+ rctx->task &= ~SHA_INIT;
+ }
+
if (rctx->task & SHA_UPDATE) {
ret = tegra_cmac_do_update(req);
if (ret)
@@ -1684,34 +1720,6 @@ static void tegra_cmac_cra_exit(struct crypto_tfm *tfm)
tegra_key_invalidate(ctx->se, ctx->key_id, ctx->alg);
}
-static int tegra_cmac_init(struct ahash_request *req)
-{
- struct tegra_cmac_reqctx *rctx = ahash_request_ctx(req);
- struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
- struct tegra_cmac_ctx *ctx = crypto_ahash_ctx(tfm);
- struct tegra_se *se = ctx->se;
- int i;
-
- rctx->total_len = 0;
- rctx->datbuf.size = 0;
- rctx->residue.size = 0;
- rctx->task = SHA_FIRST;
- rctx->blk_size = crypto_ahash_blocksize(tfm);
-
- rctx->residue.buf = dma_alloc_coherent(se->dev, rctx->blk_size * 2,
- &rctx->residue.addr, GFP_KERNEL);
- if (!rctx->residue.buf)
- return -ENOMEM;
-
- rctx->residue.size = 0;
-
- /* Clear any previous result */
- for (i = 0; i < CMAC_RESULT_REG_COUNT; i++)
- writel(0, se->base + se->hw->regs->result + (i * 4));
-
- return 0;
-}
-
static int tegra_cmac_setkey(struct crypto_ahash *tfm, const u8 *key,
unsigned int keylen)
{
@@ -1728,6 +1736,17 @@ static int tegra_cmac_setkey(struct crypto_ahash *tfm, const u8 *key,
return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
}
+static int tegra_cmac_init(struct ahash_request *req)
+{
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct tegra_cmac_ctx *ctx = crypto_ahash_ctx(tfm);
+ struct tegra_cmac_reqctx *rctx = ahash_request_ctx(req);
+
+ rctx->task = SHA_INIT;
+
+ return crypto_transfer_hash_request_to_engine(ctx->se->engine, req);
+}
+
static int tegra_cmac_update(struct ahash_request *req)
{
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
@@ -1768,11 +1787,8 @@ static int tegra_cmac_digest(struct ahash_request *req)
struct tegra_cmac_reqctx *rctx = ahash_request_ctx(req);
int ret;
- ret = tegra_cmac_init(req);
- if (ret)
- return ret;
+ rctx->task |= SHA_INIT | SHA_UPDATE | SHA_FINAL;
- rctx->task |= SHA_UPDATE | SHA_FINAL;
return crypto_transfer_hash_request_to_engine(ctx->se->engine, req);
}
diff --git a/drivers/crypto/tegra/tegra-se-hash.c b/drivers/crypto/tegra/tegra-se-hash.c
index 0ae5ce67bdd0..6da18f0f7ce9 100644
--- a/drivers/crypto/tegra/tegra-se-hash.c
+++ b/drivers/crypto/tegra/tegra-se-hash.c
@@ -296,6 +296,44 @@ static void tegra_sha_paste_hash_result(struct tegra_se *se, struct tegra_sha_re
se->base + se->hw->regs->result + (i * 4));
}
+static int tegra_sha_do_init(struct ahash_request *req)
+{
+ struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
+ struct tegra_se *se = ctx->se;
+
+ if (ctx->fallback)
+ return tegra_sha_fallback_init(req);
+
+ rctx->total_len = 0;
+ rctx->datbuf.size = 0;
+ rctx->residue.size = 0;
+ rctx->key_id = ctx->key_id;
+ rctx->task |= SHA_FIRST;
+ rctx->alg = ctx->alg;
+ rctx->blk_size = crypto_ahash_blocksize(tfm);
+ rctx->digest.size = crypto_ahash_digestsize(tfm);
+
+ rctx->digest.buf = dma_alloc_coherent(se->dev, rctx->digest.size,
+ &rctx->digest.addr, GFP_KERNEL);
+ if (!rctx->digest.buf)
+ goto digbuf_fail;
+
+ rctx->residue.buf = dma_alloc_coherent(se->dev, rctx->blk_size,
+ &rctx->residue.addr, GFP_KERNEL);
+ if (!rctx->residue.buf)
+ goto resbuf_fail;
+
+ return 0;
+
+resbuf_fail:
+ dma_free_coherent(se->dev, rctx->digest.size, rctx->digest.buf,
+ rctx->digest.addr);
+digbuf_fail:
+ return -ENOMEM;
+}
+
static int tegra_sha_do_update(struct ahash_request *req)
{
struct tegra_sha_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
@@ -435,6 +473,14 @@ static int tegra_sha_do_one_req(struct crypto_engine *engine, void *areq)
struct tegra_se *se = ctx->se;
int ret = 0;
+ if (rctx->task & SHA_INIT) {
+ ret = tegra_sha_do_init(req);
+ if (ret)
+ goto out;
+
+ rctx->task &= ~SHA_INIT;
+ }
+
if (rctx->task & SHA_UPDATE) {
ret = tegra_sha_do_update(req);
if (ret)
@@ -525,44 +571,6 @@ static void tegra_sha_cra_exit(struct crypto_tfm *tfm)
tegra_key_invalidate(ctx->se, ctx->key_id, ctx->alg);
}
-static int tegra_sha_init(struct ahash_request *req)
-{
- struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
- struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
- struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
- struct tegra_se *se = ctx->se;
-
- if (ctx->fallback)
- return tegra_sha_fallback_init(req);
-
- rctx->total_len = 0;
- rctx->datbuf.size = 0;
- rctx->residue.size = 0;
- rctx->key_id = ctx->key_id;
- rctx->task = SHA_FIRST;
- rctx->alg = ctx->alg;
- rctx->blk_size = crypto_ahash_blocksize(tfm);
- rctx->digest.size = crypto_ahash_digestsize(tfm);
-
- rctx->digest.buf = dma_alloc_coherent(se->dev, rctx->digest.size,
- &rctx->digest.addr, GFP_KERNEL);
- if (!rctx->digest.buf)
- goto digbuf_fail;
-
- rctx->residue.buf = dma_alloc_coherent(se->dev, rctx->blk_size,
- &rctx->residue.addr, GFP_KERNEL);
- if (!rctx->residue.buf)
- goto resbuf_fail;
-
- return 0;
-
-resbuf_fail:
- dma_free_coherent(se->dev, rctx->digest.size, rctx->digest.buf,
- rctx->digest.addr);
-digbuf_fail:
- return -ENOMEM;
-}
-
static int tegra_hmac_fallback_setkey(struct tegra_sha_ctx *ctx, const u8 *key,
unsigned int keylen)
{
@@ -588,6 +596,17 @@ static int tegra_hmac_setkey(struct crypto_ahash *tfm, const u8 *key,
return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
}
+static int tegra_sha_init(struct ahash_request *req)
+{
+ struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
+
+ rctx->task = SHA_INIT;
+
+ return crypto_transfer_hash_request_to_engine(ctx->se->engine, req);
+}
+
static int tegra_sha_update(struct ahash_request *req)
{
struct tegra_sha_reqctx *rctx = ahash_request_ctx(req);
@@ -640,11 +659,8 @@ static int tegra_sha_digest(struct ahash_request *req)
if (ctx->fallback)
return tegra_sha_fallback_digest(req);
- ret = tegra_sha_init(req);
- if (ret)
- return ret;
+ rctx->task |= SHA_INIT | SHA_UPDATE | SHA_FINAL;
- rctx->task |= SHA_UPDATE | SHA_FINAL;
return crypto_transfer_hash_request_to_engine(ctx->se->engine, req);
}
diff --git a/drivers/crypto/tegra/tegra-se.h b/drivers/crypto/tegra/tegra-se.h
index e196a90eedb9..e1ec37bfb80a 100644
--- a/drivers/crypto/tegra/tegra-se.h
+++ b/drivers/crypto/tegra/tegra-se.h
@@ -342,8 +342,9 @@
#define SE_MAX_MEM_ALLOC SZ_4M
#define SHA_FIRST BIT(0)
-#define SHA_UPDATE BIT(1)
-#define SHA_FINAL BIT(2)
+#define SHA_INIT BIT(1)
+#define SHA_UPDATE BIT(2)
+#define SHA_FINAL BIT(3)
/* Security Engine operation modes */
enum se_aes_alg {
--
2.43.2
^ permalink raw reply related
* [PATCH v2 04/10] crypto: tegra: check return value for hash do_one_req
From: Akhil R @ 2025-02-11 17:17 UTC (permalink / raw)
To: herbert, davem, thierry.reding, jonathanh, linux-crypto,
linux-tegra, linux-kernel
Cc: Akhil R, kernel test robot, Dan Carpenter
In-Reply-To: <20250211171713.65770-1-akhilrajeev@nvidia.com>
Initialize and check the return value in hash *do_one_req() functions
and exit the function if there is an error. This fixes the
'uninitialized variable' warnings reported by testbots.
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Closes: https://lore.kernel.org/r/202412071747.flPux4oB-lkp@intel.com/
Fixes: 0880bb3b00c8 ("crypto: tegra - Add Tegra Security Engine driver")
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
---
drivers/crypto/tegra/tegra-se-aes.c | 10 ++++++++--
drivers/crypto/tegra/tegra-se-hash.c | 7 +++++++
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/drivers/crypto/tegra/tegra-se-aes.c b/drivers/crypto/tegra/tegra-se-aes.c
index c7bb6f951a84..5ca7996ecc6d 100644
--- a/drivers/crypto/tegra/tegra-se-aes.c
+++ b/drivers/crypto/tegra/tegra-se-aes.c
@@ -1602,18 +1602,24 @@ static int tegra_cmac_do_one_req(struct crypto_engine *engine, void *areq)
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct tegra_cmac_ctx *ctx = crypto_ahash_ctx(tfm);
struct tegra_se *se = ctx->se;
- int ret;
+ int ret = 0;
if (rctx->task & SHA_UPDATE) {
ret = tegra_cmac_do_update(req);
+ if (ret)
+ goto out;
+
rctx->task &= ~SHA_UPDATE;
}
if (rctx->task & SHA_FINAL) {
ret = tegra_cmac_do_final(req);
+ if (ret)
+ goto out;
+
rctx->task &= ~SHA_FINAL;
}
-
+out:
crypto_finalize_hash_request(se->engine, req, ret);
return 0;
diff --git a/drivers/crypto/tegra/tegra-se-hash.c b/drivers/crypto/tegra/tegra-se-hash.c
index b4a179a8febd..0ae5ce67bdd0 100644
--- a/drivers/crypto/tegra/tegra-se-hash.c
+++ b/drivers/crypto/tegra/tegra-se-hash.c
@@ -437,14 +437,21 @@ static int tegra_sha_do_one_req(struct crypto_engine *engine, void *areq)
if (rctx->task & SHA_UPDATE) {
ret = tegra_sha_do_update(req);
+ if (ret)
+ goto out;
+
rctx->task &= ~SHA_UPDATE;
}
if (rctx->task & SHA_FINAL) {
ret = tegra_sha_do_final(req);
+ if (ret)
+ goto out;
+
rctx->task &= ~SHA_FINAL;
}
+out:
crypto_finalize_hash_request(se->engine, req, ret);
return 0;
--
2.43.2
^ permalink raw reply related
* [PATCH v2 03/10] crypto: tegra: finalize crypto req on error
From: Akhil R @ 2025-02-11 17:17 UTC (permalink / raw)
To: herbert, davem, thierry.reding, jonathanh, linux-crypto,
linux-tegra, linux-kernel
Cc: Akhil R
In-Reply-To: <20250211171713.65770-1-akhilrajeev@nvidia.com>
Call the crypto finalize function before exiting *do_one_req() functions.
This allows the driver to take up further requests even if the previous
one fails.
Fixes: 0880bb3b00c8 ("crypto: tegra - Add Tegra Security Engine driver")
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
---
drivers/crypto/tegra/tegra-se-aes.c | 28 +++++++++++++++++-----------
1 file changed, 17 insertions(+), 11 deletions(-)
diff --git a/drivers/crypto/tegra/tegra-se-aes.c b/drivers/crypto/tegra/tegra-se-aes.c
index c2b8891a905d..c7bb6f951a84 100644
--- a/drivers/crypto/tegra/tegra-se-aes.c
+++ b/drivers/crypto/tegra/tegra-se-aes.c
@@ -275,8 +275,10 @@ static int tegra_aes_do_one_req(struct crypto_engine *engine, void *areq)
rctx->datbuf.size = rctx->len;
rctx->datbuf.buf = dma_alloc_coherent(se->dev, rctx->datbuf.size,
&rctx->datbuf.addr, GFP_KERNEL);
- if (!rctx->datbuf.buf)
- return -ENOMEM;
+ if (!rctx->datbuf.buf) {
+ ret = -ENOMEM;
+ goto out_finalize;
+ }
scatterwalk_map_and_copy(rctx->datbuf.buf, req->src, 0, req->cryptlen, 0);
@@ -292,6 +294,7 @@ static int tegra_aes_do_one_req(struct crypto_engine *engine, void *areq)
dma_free_coherent(ctx->se->dev, rctx->datbuf.size,
rctx->datbuf.buf, rctx->datbuf.addr);
+out_finalize:
crypto_finalize_skcipher_request(se->engine, req, ret);
return 0;
@@ -1152,21 +1155,21 @@ static int tegra_ccm_do_one_req(struct crypto_engine *engine, void *areq)
ret = tegra_ccm_crypt_init(req, se, rctx);
if (ret)
- return ret;
+ goto out_finalize;
/* Allocate buffers required */
rctx->inbuf.size = rctx->assoclen + rctx->authsize + rctx->cryptlen + 100;
rctx->inbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->inbuf.size,
&rctx->inbuf.addr, GFP_KERNEL);
if (!rctx->inbuf.buf)
- return -ENOMEM;
+ goto out_finalize;
rctx->outbuf.size = rctx->assoclen + rctx->authsize + rctx->cryptlen + 100;
rctx->outbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->outbuf.size,
&rctx->outbuf.addr, GFP_KERNEL);
if (!rctx->outbuf.buf) {
ret = -ENOMEM;
- goto outbuf_err;
+ goto out_free_inbuf;
}
if (rctx->encrypt) {
@@ -1195,10 +1198,11 @@ static int tegra_ccm_do_one_req(struct crypto_engine *engine, void *areq)
dma_free_coherent(ctx->se->dev, rctx->inbuf.size,
rctx->outbuf.buf, rctx->outbuf.addr);
-outbuf_err:
+out_free_inbuf:
dma_free_coherent(ctx->se->dev, rctx->outbuf.size,
rctx->inbuf.buf, rctx->inbuf.addr);
+out_finalize:
crypto_finalize_aead_request(ctx->se->engine, req, ret);
return 0;
@@ -1229,15 +1233,17 @@ static int tegra_gcm_do_one_req(struct crypto_engine *engine, void *areq)
rctx->inbuf.size = rctx->assoclen + rctx->authsize + rctx->cryptlen;
rctx->inbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->inbuf.size,
&rctx->inbuf.addr, GFP_KERNEL);
- if (!rctx->inbuf.buf)
- return -ENOMEM;
+ if (!rctx->inbuf.buf) {
+ ret = -ENOMEM;
+ goto out_finalize;
+ }
rctx->outbuf.size = rctx->assoclen + rctx->authsize + rctx->cryptlen;
rctx->outbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->outbuf.size,
&rctx->outbuf.addr, GFP_KERNEL);
if (!rctx->outbuf.buf) {
ret = -ENOMEM;
- goto outbuf_err;
+ goto out_free_inbuf;
}
/* If there is associated data perform GMAC operation */
@@ -1266,11 +1272,11 @@ static int tegra_gcm_do_one_req(struct crypto_engine *engine, void *areq)
dma_free_coherent(ctx->se->dev, rctx->outbuf.size,
rctx->outbuf.buf, rctx->outbuf.addr);
-outbuf_err:
+out_free_inbuf:
dma_free_coherent(ctx->se->dev, rctx->inbuf.size,
rctx->inbuf.buf, rctx->inbuf.addr);
- /* Finalize the request if there are no errors */
+out_finalize:
crypto_finalize_aead_request(ctx->se->engine, req, ret);
return 0;
--
2.43.2
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox