mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-14 18:46:45 +07:00
966f53e750
The arch_get_random_seed_long() invocation done by the random device driver is done in interrupt context and may be invoked very very frequently. The existing s390 arch_get_random_seed*() implementation uses the PRNO(TRNG) instruction which produces excellent high quality entropy but is relatively slow and thus expensive. This fix reworks the arch_get_random_seed* implementation. It introduces a buffer concept to decouple the delivery of random data via arch_get_random_seed*() from the generation of new random bytes. The buffer of random data is filled asynchronously by a workqueue thread. If there are enough bytes in the buffer the s390_arch_random_generate() just delivers these bytes. Otherwise false is returned until the worker thread refills the buffer. The worker fills the rng buffer by pulling fresh entropy from the high quality (but slow) true hardware random generator. This entropy is then spread over the buffer with an pseudo random generator. As the arch_get_random_seed_long() fetches 8 bytes and the calling function add_interrupt_randomness() counts this as 1 bit entropy the distribution needs to make sure there is in fact 1 bit entropy contained in 8 bytes of the buffer. The current values pull 32 byte entropy and scatter this into a 2048 byte buffer. So 8 byte in the buffer will contain 1 bit of entropy. The worker thread is rescheduled based on the charge level of the buffer but at least with 500 ms delay to avoid too much cpu consumption. So the max. amount of rng data delivered via arch_get_random_seed is limited to 4Kb per second. Signed-off-by: Harald Freudenberger <freude@de.ibm.com> Reviewed-by: Patrick Steuer <patrick.steuer@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
64 lines
1.3 KiB
C
64 lines
1.3 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Kernel interface for the s390 arch_random_* functions
|
|
*
|
|
* Copyright IBM Corp. 2017
|
|
*
|
|
* Author: Harald Freudenberger <freude@de.ibm.com>
|
|
*
|
|
*/
|
|
|
|
#ifndef _ASM_S390_ARCHRANDOM_H
|
|
#define _ASM_S390_ARCHRANDOM_H
|
|
|
|
#ifdef CONFIG_ARCH_RANDOM
|
|
|
|
#include <linux/static_key.h>
|
|
#include <linux/atomic.h>
|
|
|
|
DECLARE_STATIC_KEY_FALSE(s390_arch_random_available);
|
|
extern atomic64_t s390_arch_random_counter;
|
|
|
|
bool s390_arch_random_generate(u8 *buf, unsigned int nbytes);
|
|
|
|
static inline bool arch_has_random(void)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static inline bool arch_has_random_seed(void)
|
|
{
|
|
if (static_branch_likely(&s390_arch_random_available))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
static inline bool arch_get_random_long(unsigned long *v)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static inline bool arch_get_random_int(unsigned int *v)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static inline bool arch_get_random_seed_long(unsigned long *v)
|
|
{
|
|
if (static_branch_likely(&s390_arch_random_available)) {
|
|
return s390_arch_random_generate((u8 *)v, sizeof(*v));
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static inline bool arch_get_random_seed_int(unsigned int *v)
|
|
{
|
|
if (static_branch_likely(&s390_arch_random_available)) {
|
|
return s390_arch_random_generate((u8 *)v, sizeof(*v));
|
|
}
|
|
return false;
|
|
}
|
|
|
|
#endif /* CONFIG_ARCH_RANDOM */
|
|
#endif /* _ASM_S390_ARCHRANDOM_H */
|