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 | |
| 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')
| -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; |
