diff options
author | Theodore Ts'o <tytso@mit.edu> | 2013-09-22 15:24:02 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2013-10-10 14:32:20 -0400 |
commit | 655b226470b229552ad95b21323864df9bd9fc74 (patch) | |
tree | 9379bc872df3e7e859654a374e23be3fc4248521 /drivers/char/random.c | |
parent | f5c2742c23886e707f062881c5f206c1fc704782 (diff) |
random: speed up the fast_mix function by a factor of four
By mixing the entropy in chunks of 32-bit words instead of byte by
byte, we can speed up the fast_mix function significantly. Since it
is called on every single interrupt, on systems with a very heavy
interrupt load, this can make a noticeable difference.
Also fix a compilation warning in add_interrupt_randomness() and avoid
xor'ing cycles and jiffies together just in case we have an
architecture which tries to define random_get_entropy() by returning
jiffies.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Reported-by: Jörn Engel <joern@logfs.org>
Diffstat (limited to 'drivers/char/random.c')
-rw-r--r-- | drivers/char/random.c | 50 |
1 files changed, 28 insertions, 22 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c index a68b4a093272..74eeec58e779 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -584,21 +584,26 @@ struct fast_pool { | |||
584 | * collector. It's hardcoded for an 128 bit pool and assumes that any | 584 | * collector. It's hardcoded for an 128 bit pool and assumes that any |
585 | * locks that might be needed are taken by the caller. | 585 | * locks that might be needed are taken by the caller. |
586 | */ | 586 | */ |
587 | static void fast_mix(struct fast_pool *f, const void *in, int nbytes) | 587 | static void fast_mix(struct fast_pool *f, __u32 input[4]) |
588 | { | 588 | { |
589 | const char *bytes = in; | ||
590 | __u32 w; | 589 | __u32 w; |
591 | unsigned i = f->count; | ||
592 | unsigned input_rotate = f->rotate; | 590 | unsigned input_rotate = f->rotate; |
593 | 591 | ||
594 | while (nbytes--) { | 592 | w = rol32(input[0], input_rotate) ^ f->pool[0] ^ f->pool[3]; |
595 | w = rol32(*bytes++, input_rotate & 31) ^ f->pool[i & 3] ^ | 593 | f->pool[0] = (w >> 3) ^ twist_table[w & 7]; |
596 | f->pool[(i + 1) & 3]; | 594 | input_rotate = (input_rotate + 14) & 31; |
597 | f->pool[i & 3] = (w >> 3) ^ twist_table[w & 7]; | 595 | w = rol32(input[1], input_rotate) ^ f->pool[1] ^ f->pool[0]; |
598 | input_rotate += (i++ & 3) ? 7 : 14; | 596 | f->pool[1] = (w >> 3) ^ twist_table[w & 7]; |
599 | } | 597 | input_rotate = (input_rotate + 7) & 31; |
600 | f->count = i; | 598 | w = rol32(input[2], input_rotate) ^ f->pool[2] ^ f->pool[1]; |
599 | f->pool[2] = (w >> 3) ^ twist_table[w & 7]; | ||
600 | input_rotate = (input_rotate + 7) & 31; | ||
601 | w = rol32(input[3], input_rotate) ^ f->pool[3] ^ f->pool[2]; | ||
602 | f->pool[3] = (w >> 3) ^ twist_table[w & 7]; | ||
603 | input_rotate = (input_rotate + 7) & 31; | ||
604 | |||
601 | f->rotate = input_rotate; | 605 | f->rotate = input_rotate; |
606 | f->count++; | ||
602 | } | 607 | } |
603 | 608 | ||
604 | /* | 609 | /* |
@@ -828,20 +833,21 @@ void add_interrupt_randomness(int irq, int irq_flags) | |||
828 | struct fast_pool *fast_pool = &__get_cpu_var(irq_randomness); | 833 | struct fast_pool *fast_pool = &__get_cpu_var(irq_randomness); |
829 | struct pt_regs *regs = get_irq_regs(); | 834 | struct pt_regs *regs = get_irq_regs(); |
830 | unsigned long now = jiffies; | 835 | unsigned long now = jiffies; |
831 | __u32 input[4], cycles = random_get_entropy(); | 836 | cycles_t cycles = random_get_entropy(); |
832 | 837 | __u32 input[4], c_high, j_high; | |
833 | input[0] = cycles ^ jiffies; | 838 | __u64 ip; |
834 | input[1] = irq; | 839 | |
835 | if (regs) { | 840 | c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0; |
836 | __u64 ip = instruction_pointer(regs); | 841 | j_high = (sizeof(now) > 4) ? now >> 32 : 0; |
837 | input[2] = ip; | 842 | input[0] = cycles ^ j_high ^ irq; |
838 | input[3] = ip >> 32; | 843 | input[1] = now ^ c_high; |
839 | } | 844 | ip = regs ? instruction_pointer(regs) : _RET_IP_; |
845 | input[2] = ip; | ||
846 | input[3] = ip >> 32; | ||
840 | 847 | ||
841 | fast_mix(fast_pool, input, sizeof(input)); | 848 | fast_mix(fast_pool, input); |
842 | 849 | ||
843 | if ((fast_pool->count & 1023) && | 850 | if ((fast_pool->count & 63) && !time_after(now, fast_pool->last + HZ)) |
844 | !time_after(now, fast_pool->last + HZ)) | ||
845 | return; | 851 | return; |
846 | 852 | ||
847 | fast_pool->last = now; | 853 | fast_pool->last = now; |