From: Holger Dengler <dengler@linux.ibm.com>
To: "Jason A . Donenfeld" <Jason@zx2c4.com>,
Harald Freudenberger <freude@linux.ibm.com>,
Heiko Carstens <hca@linux.ibm.com>,
Vasily Gorbik <gor@linux.ibm.com>,
Alexander Gordeev <agordeev@linux.ibm.com>,
Christian Borntraeger <borntraeger@linux.ibm.com>
Cc: Juergen Christ <jchrist@linux.ibm.com>,
Holger Dengler <dengler@linux.ibm.com>,
linux-crypto@vger.kernel.org, linux-s390@vger.kernel.org
Subject: [PATCH v1 1/1] s390/arch_random: Buffer true random data
Date: Tue, 5 Jul 2022 13:27:12 +0200 [thread overview]
Message-ID: <20220705112712.4433-2-dengler@linux.ibm.com> (raw)
In-Reply-To: <20220705112712.4433-1-dengler@linux.ibm.com>
The trng instruction is very expensive and has a constant runtime for
getting 0 to 32 bytes of (conditioned) true random data. Calling trng for
in arch_get_random_seed_long() for each 8 bytes is too time-consuming,
especially if it is called in interrupt context.
This implementation buffers the trng data and deliver parts of it to the
callers. This reduces the costs by factor 4.
Drop the implementation for arch_get_random_seed_int(), because there are
no callers.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Holger Dengler <dengler@linux.ibm.com>
---
arch/s390/crypto/arch_random.c | 51 +++++++++++++++++++++++++++++-
arch/s390/include/asm/archrandom.h | 17 ++++------
2 files changed, 56 insertions(+), 12 deletions(-)
diff --git a/arch/s390/crypto/arch_random.c b/arch/s390/crypto/arch_random.c
index 1f2d40993c4d..07abd09ec759 100644
--- a/arch/s390/crypto/arch_random.c
+++ b/arch/s390/crypto/arch_random.c
@@ -2,17 +2,66 @@
/*
* s390 arch random implementation.
*
- * Copyright IBM Corp. 2017, 2020
+ * Copyright IBM Corp. 2017, 2022
* Author(s): Harald Freudenberger
+ * Holger Dengler <dengler@linux.ibm.com>
+ *
+ * The trng instruction on s390 is very expensive and has a constant runtime
+ * for up to 32 bytes. Each trng call will get 32 bytes of (conditioned) true
+ * random data, which are buffered in a lock-protected array and delivered to
+ * up to four callers. To avoid long running trng calls in the interrupt
+ * context, a refill is skipped there. Also prevent the blocking of callers in
+ * interrupt context by a refill.
*/
#include <linux/kernel.h>
#include <linux/atomic.h>
#include <linux/random.h>
+#include <linux/spinlock.h>
#include <linux/static_key.h>
#include <asm/cpacf.h>
DEFINE_STATIC_KEY_FALSE(s390_arch_random_available);
+static struct {
+ unsigned long data[BITS_TO_LONGS(32 * BITS_PER_BYTE)];
+ int idx;
+} trngbuf;
+static DEFINE_SPINLOCK(trngbuf_lock);
+
atomic64_t s390_arch_random_counter = ATOMIC64_INIT(0);
EXPORT_SYMBOL(s390_arch_random_counter);
+
+bool s390_get_random_seed_long(unsigned long *v)
+{
+ unsigned long flags;
+
+ if (in_interrupt()) {
+ if (!spin_trylock_irqsave(&trngbuf_lock, flags))
+ return false;
+ } else {
+ spin_lock_irqsave(&trngbuf_lock, flags);
+ }
+ /* trngbuf is locked */
+
+ if (--trngbuf.idx < 0) {
+ /* buffer empty */
+ if (in_interrupt()) {
+ /* delegate refill to another caller */
+ spin_unlock_irqrestore(&trngbuf_lock, flags);
+ return false;
+ }
+
+ /* refill buffer */
+ cpacf_trng(NULL, 0, (u8 *)trngbuf.data, sizeof(trngbuf.data));
+ trngbuf.idx = ARRAY_SIZE(trngbuf.data) - 1;
+ }
+
+ /* deliver buffered random data */
+ *v = trngbuf.data[trngbuf.idx];
+ spin_unlock_irqrestore(&trngbuf_lock, flags);
+
+ atomic64_add(sizeof(long), &s390_arch_random_counter);
+ return true;
+}
+EXPORT_SYMBOL(s390_get_random_seed_long);
diff --git a/arch/s390/include/asm/archrandom.h b/arch/s390/include/asm/archrandom.h
index 2c6e1c6ecbe7..a1e365de6b33 100644
--- a/arch/s390/include/asm/archrandom.h
+++ b/arch/s390/include/asm/archrandom.h
@@ -2,7 +2,7 @@
/*
* Kernel interface for the s390 arch_random_* functions
*
- * Copyright IBM Corp. 2017, 2020
+ * Copyright IBM Corp. 2017, 2022
*
* Author: Harald Freudenberger <freude@de.ibm.com>
*
@@ -20,6 +20,8 @@
DECLARE_STATIC_KEY_FALSE(s390_arch_random_available);
extern atomic64_t s390_arch_random_counter;
+bool s390_get_random_seed_long(unsigned long *v);
+
static inline bool __must_check arch_get_random_long(unsigned long *v)
{
return false;
@@ -32,21 +34,14 @@ static inline bool __must_check arch_get_random_int(unsigned int *v)
static inline bool __must_check arch_get_random_seed_long(unsigned long *v)
{
- if (static_branch_likely(&s390_arch_random_available)) {
- cpacf_trng(NULL, 0, (u8 *)v, sizeof(*v));
- atomic64_add(sizeof(*v), &s390_arch_random_counter);
- return true;
- }
+ if (static_branch_likely(&s390_arch_random_available))
+ return s390_get_random_seed_long(v);
+
return false;
}
static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
{
- if (static_branch_likely(&s390_arch_random_available)) {
- cpacf_trng(NULL, 0, (u8 *)v, sizeof(*v));
- atomic64_add(sizeof(*v), &s390_arch_random_counter);
- return true;
- }
return false;
}
--
2.36.1
next prev parent reply other threads:[~2022-07-05 11:27 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-07-05 11:27 [PATCH v1 0/1] s390/archrandom: use buffered random data Holger Dengler
2022-07-05 11:27 ` Holger Dengler [this message]
2022-07-05 13:18 ` [PATCH v1 1/1] s390/arch_random: Buffer true " Jason A. Donenfeld
2022-07-05 13:42 ` Jason A. Donenfeld
2022-07-05 14:58 ` Holger Dengler
2022-07-05 15:11 ` Jason A. Donenfeld
2022-07-05 16:27 ` Holger Dengler
2022-07-05 16:35 ` Jason A. Donenfeld
2022-07-05 17:47 ` Holger Dengler
2022-07-05 18:19 ` Jason A. Donenfeld
2022-07-05 19:28 ` Holger Dengler
2022-07-06 16:18 ` Harald Freudenberger
2022-07-06 16:26 ` Jason A. Donenfeld
2022-07-06 18:29 ` Christian Borntraeger
2022-07-06 22:34 ` Jason A. Donenfeld
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220705112712.4433-2-dengler@linux.ibm.com \
--to=dengler@linux.ibm.com \
--cc=Jason@zx2c4.com \
--cc=agordeev@linux.ibm.com \
--cc=borntraeger@linux.ibm.com \
--cc=freude@linux.ibm.com \
--cc=gor@linux.ibm.com \
--cc=hca@linux.ibm.com \
--cc=jchrist@linux.ibm.com \
--cc=linux-crypto@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox