hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I9K8D1
--------------------------------
A performance degrade is observed on boards with certain chips. Debugging shows that degrade is caused by the two line in drivers/char/random.c. The root cause of why these two lines would cause such degrade is still unknown.
This patch is meant to be a workaround for said issue.
Fixes: 6c315cc252ce ("random: use first 128 bits of input as fast init") Signed-off-by: GUO Zihua guozihua@huawei.com --- drivers/char/Kconfig | 9 +++ drivers/char/random.c | 163 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 171 insertions(+), 1 deletion(-)
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 677e16195d32..872e6f661998 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -513,4 +513,13 @@ config RANDOM_TRUST_BOOTLOADER believe its RNG facilities may be faulty. This may also be configured at boot time with "random.trust_bootloader=on/off".
+config RTOS_FIX_RANDOM_PERFORMANCE + bool "Fix random performance degrade on certain platform" + depends on ARM + default n + help + It's observed that there is a performance degrade related to random on + system with certain chip. The root cause is unknown and this config is + meant to be a workaround for that issue. + endmenu diff --git a/drivers/char/random.c b/drivers/char/random.c index 6aa1c013a2b7..6c0ff6a5a524 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -347,8 +347,10 @@ static void crng_make_state(u32 chacha_state[CHACHA_STATE_WORDS], spin_lock_irqsave(&base_crng.lock, flags); ready = crng_ready(); if (!ready) { +#ifndef CONFIG_RTOS_FIX_RANDOM_PERFORMANCE if (crng_init == CRNG_EMPTY) extract_entropy(base_crng.key, sizeof(base_crng.key)); +#endif crng_fast_key_erasure(base_crng.key, chacha_state, random_data, random_data_len); } @@ -392,6 +394,129 @@ static void crng_make_state(u32 chacha_state[CHACHA_STATE_WORDS], local_unlock_irqrestore(&crngs.lock, flags); }
+#ifdef CONFIG_RTOS_FIX_RANDOM_PERFORMANCE +/* + * Dummy function acting as a placeholder to 1380 performance degrade. + * It contains 112 nops, which is exactly the instruction count of the original + * function crng_pre_init_inject. + */ +static void __used dummy(const void *input, size_t len, bool account) +{ + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); +} +#endif // CONFIG_RTOS_FIX_RANDOM_PERFORMANCE + static void _get_random_bytes(void *buf, size_t len) { u32 chacha_state[CHACHA_STATE_WORDS]; @@ -860,6 +985,14 @@ void add_device_randomness(const void *buf, size_t len) _mix_pool_bytes(&entropy, sizeof(entropy)); _mix_pool_bytes(buf, len); spin_unlock_irqrestore(&input_pool.lock, flags); + +#ifdef CONFIG_RTOS_FIX_RANDOM_PERFORMANCE + if (crng_init == CRNG_EMPTY && len) { + spin_lock_irqsave(&base_crng.lock, flags); + extract_entropy(base_crng.key, sizeof(base_crng.key)); + spin_unlock_irqrestore(&base_crng.lock, flags); + } +#endif } EXPORT_SYMBOL(add_device_randomness);
@@ -870,7 +1003,17 @@ EXPORT_SYMBOL(add_device_randomness); */ void add_hwgenerator_randomness(const void *buf, size_t len, size_t entropy) { +#ifdef CONFIG_RTOS_FIX_RANDOM_PERFORMANCE + unsigned long flags; +#endif mix_pool_bytes(buf, len); +#ifdef CONFIG_RTOS_FIX_RANDOM_PERFORMANCE + if (crng_init == CRNG_EMPTY) { + spin_lock_irqsave(&base_crng.lock, flags); + extract_entropy(base_crng.key, sizeof(base_crng.key)); + spin_unlock_irqrestore(&base_crng.lock, flags); + } +#endif credit_init_bits(entropy);
/* @@ -965,6 +1108,9 @@ static void mix_interrupt_randomness(struct timer_list *work) */ unsigned long pool[2]; unsigned int count; +#ifdef CONFIG_RTOS_FIX_RANDOM_PERFORMANCE + unsigned long flags; +#endif
/* Check to see if we're running on the wrong CPU due to hotplug. */ local_irq_disable(); @@ -984,6 +1130,13 @@ static void mix_interrupt_randomness(struct timer_list *work) local_irq_enable();
mix_pool_bytes(pool, sizeof(pool)); +#ifdef CONFIG_RTOS_FIX_RANDOM_PERFORMANCE + if (crng_init == CRNG_EMPTY) { + spin_lock_irqsave(&base_crng.lock, flags); + extract_entropy(base_crng.key, sizeof(base_crng.key)); + spin_unlock_irqrestore(&base_crng.lock, flags); + } +#endif credit_init_bits(clamp_t(unsigned int, (count & U16_MAX) / 64, 1, sizeof(pool) * 8));
memzero_explicit(pool, sizeof(pool)); @@ -1090,8 +1243,16 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned int nu */ if (in_irq()) this_cpu_ptr(&irq_randomness)->count += max(1u, bits * 64) - 1; - else + else { +#ifdef CONFIG_RTOS_FIX_RANDOM_PERFORMANCE + if (crng_init == CRNG_EMPTY) { + spin_lock_irqsave(&base_crng.lock, flags); + extract_entropy(base_crng.key, sizeof(base_crng.key)); + spin_unlock_irqrestore(&base_crng.lock, flags); + } +#endif _credit_init_bits(bits); + } }
void add_input_randomness(unsigned int type, unsigned int code, unsigned int value)