1 From e2849410757919ff26a7731a8fef17227d080600 Mon Sep 17 00:00:00 2001
2 From: Thomas Gleixner <tglx@linutronix.de>
3 Date: Tue, 21 Aug 2012 20:38:50 +0200
4 Subject: [PATCH 216/365] random: Make it work on rt
6 Delegate the random insertion to the forced threaded interrupt
7 handler. Store the return IP of the hard interrupt handler in the irq
8 descriptor and feed it into the random generator as a source of
11 Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
13 drivers/char/random.c | 11 +++++------
14 include/linux/irqdesc.h | 1 +
15 include/linux/random.h | 2 +-
16 kernel/irq/handle.c | 8 +++++++-
17 kernel/irq/manage.c | 6 ++++++
18 5 files changed, 20 insertions(+), 8 deletions(-)
20 diff --git a/drivers/char/random.c b/drivers/char/random.c
21 index dd5346c..afffbc7 100644
22 --- a/drivers/char/random.c
23 +++ b/drivers/char/random.c
24 @@ -891,28 +891,27 @@ static __u32 get_reg(struct fast_pool *f, struct pt_regs *regs)
25 return *(ptr + f->reg_idx++);
28 -void add_interrupt_randomness(int irq, int irq_flags)
29 +void add_interrupt_randomness(int irq, int irq_flags, __u64 ip)
31 struct entropy_store *r;
32 struct fast_pool *fast_pool = this_cpu_ptr(&irq_randomness);
33 - struct pt_regs *regs = get_irq_regs();
34 unsigned long now = jiffies;
35 cycles_t cycles = random_get_entropy();
42 - cycles = get_reg(fast_pool, regs);
43 + cycles = get_reg(fast_pool, NULL);
44 c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0;
45 j_high = (sizeof(now) > 4) ? now >> 32 : 0;
46 fast_pool->pool[0] ^= cycles ^ j_high ^ irq;
47 fast_pool->pool[1] ^= now ^ c_high;
48 - ip = regs ? instruction_pointer(regs) : _RET_IP_;
51 fast_pool->pool[2] ^= ip;
52 fast_pool->pool[3] ^= (sizeof(ip) > 4) ? ip >> 32 :
53 - get_reg(fast_pool, regs);
54 + get_reg(fast_pool, NULL);
57 add_interrupt_bench(cycles);
58 diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h
59 index a587a33..ad57402 100644
60 --- a/include/linux/irqdesc.h
61 +++ b/include/linux/irqdesc.h
62 @@ -61,6 +61,7 @@ struct irq_desc {
63 unsigned int irqs_unhandled;
64 atomic_t threads_handled;
65 int threads_handled_last;
68 struct cpumask *percpu_enabled;
70 diff --git a/include/linux/random.h b/include/linux/random.h
71 index 9c29122..e7f2f86 100644
72 --- a/include/linux/random.h
73 +++ b/include/linux/random.h
74 @@ -20,7 +20,7 @@ struct random_ready_callback {
75 extern void add_device_randomness(const void *, unsigned int);
76 extern void add_input_randomness(unsigned int type, unsigned int code,
78 -extern void add_interrupt_randomness(int irq, int irq_flags);
79 +extern void add_interrupt_randomness(int irq, int irq_flags, __u64 ip);
81 extern void get_random_bytes(void *buf, int nbytes);
82 extern int add_random_ready_callback(struct random_ready_callback *rdy);
83 diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
84 index 57bff78..6c65c92 100644
85 --- a/kernel/irq/handle.c
86 +++ b/kernel/irq/handle.c
87 @@ -134,6 +134,8 @@ void __irq_wake_thread(struct irq_desc *desc, struct irqaction *action)
89 irqreturn_t handle_irq_event_percpu(struct irq_desc *desc)
91 + struct pt_regs *regs = get_irq_regs();
92 + u64 ip = regs ? instruction_pointer(regs) : 0;
93 irqreturn_t retval = IRQ_NONE;
94 unsigned int flags = 0, irq = desc->irq_data.irq;
95 struct irqaction *action = desc->action;
96 @@ -176,7 +178,11 @@ irqreturn_t handle_irq_event_percpu(struct irq_desc *desc)
97 action = action->next;
100 - add_interrupt_randomness(irq, flags);
101 +#ifdef CONFIG_PREEMPT_RT_FULL
102 + desc->random_ip = ip;
104 + add_interrupt_randomness(irq, flags, ip);
108 note_interrupt(desc, retval);
109 diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
110 index 5b1ad63..ba2a42a 100644
111 --- a/kernel/irq/manage.c
112 +++ b/kernel/irq/manage.c
113 @@ -1045,6 +1045,12 @@ static int irq_thread(void *data)
114 if (action_ret == IRQ_WAKE_THREAD)
115 irq_wake_secondary(desc, action);
117 +#ifdef CONFIG_PREEMPT_RT_FULL
119 + add_interrupt_randomness(action->irq, 0,
120 + desc->random_ip ^ (unsigned long) action);
123 wake_threads_waitq(desc);