summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2012-08-21 20:38:50 +0200
committerSteven Rostedt <rostedt@goodmis.org>2012-10-11 15:03:49 -0400
commit92929f426abdd4236fff89482e4a3f34b0a9bae7 (patch)
treed4f72c219c7ced99188219d08c57cd95d13641a0
parentf63de56228644235ba0d0544a59a433b801d141b (diff)
downloadlinux-rt-92929f426abdd4236fff89482e4a3f34b0a9bae7.tar.gz
random: Make it work on rt
Delegate the random insertion to the forced threaded interrupt handler. Store the return IP of the hard interrupt handler in the irq descriptor and feed it into the random generator as a source of entropy. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: stable-rt@vger.kernel.org Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--drivers/char/random.c10
-rw-r--r--include/linux/irqdesc.h1
-rw-r--r--include/linux/random.h2
-rw-r--r--kernel/irq/handle.c7
-rw-r--r--kernel/irq/manage.c6
5 files changed, 19 insertions, 7 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c
index d38af32f5b8e..66c8a0f94369 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -767,18 +767,16 @@ EXPORT_SYMBOL_GPL(add_input_randomness);
static DEFINE_PER_CPU(struct fast_pool, irq_randomness);
-void add_interrupt_randomness(int irq, int irq_flags)
+void add_interrupt_randomness(int irq, int irq_flags, __u64 ip)
{
struct entropy_store *r;
struct fast_pool *fast_pool = &__get_cpu_var(irq_randomness);
- struct pt_regs *regs = get_irq_regs();
unsigned long now = jiffies;
__u32 input[4], cycles = get_cycles();
input[0] = cycles ^ jiffies;
input[1] = irq;
- if (regs) {
- __u64 ip = instruction_pointer(regs);
+ if (ip) {
input[2] = ip;
input[3] = ip >> 32;
}
@@ -792,7 +790,11 @@ void add_interrupt_randomness(int irq, int irq_flags)
fast_pool->last = now;
r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
+#ifndef CONFIG_PREEMPT_RT_FULL
__mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool), NULL);
+#else
+ mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool), NULL);
+#endif
/*
* If we don't have a valid cycle counter, and we see
* back-to-back timer interrupts, then skip giving credit for
diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h
index f1e2527006bd..5f4f0919d888 100644
--- a/include/linux/irqdesc.h
+++ b/include/linux/irqdesc.h
@@ -53,6 +53,7 @@ struct irq_desc {
unsigned int irq_count; /* For detecting broken IRQs */
unsigned long last_unhandled; /* Aging timer for unhandled count */
unsigned int irqs_unhandled;
+ u64 random_ip;
raw_spinlock_t lock;
struct cpumask *percpu_enabled;
#ifdef CONFIG_SMP
diff --git a/include/linux/random.h b/include/linux/random.h
index 29e217a7e6d0..3995b33fbfa0 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -53,7 +53,7 @@ extern void rand_initialize_irq(int irq);
extern void add_device_randomness(const void *, unsigned int);
extern void add_input_randomness(unsigned int type, unsigned int code,
unsigned int value);
-extern void add_interrupt_randomness(int irq, int irq_flags);
+extern void add_interrupt_randomness(int irq, int irq_flags, __u64 ip);
extern void get_random_bytes(void *buf, int nbytes);
extern void get_random_bytes_arch(void *buf, int nbytes);
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index a7688853397e..f6b91bc49f28 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -116,6 +116,8 @@ static void irq_wake_thread(struct irq_desc *desc, struct irqaction *action)
irqreturn_t
handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
{
+ struct pt_regs *regs = get_irq_regs();
+ u64 ip = regs ? instruction_pointer(regs) : 0;
irqreturn_t retval = IRQ_NONE;
unsigned int flags = 0, irq = desc->irq_data.irq;
@@ -157,8 +159,9 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
} while (action);
#ifndef CONFIG_PREEMPT_RT_FULL
- /* FIXME: Can we unbreak that ? */
- add_interrupt_randomness(irq, flags);
+ add_interrupt_randomness(irq, flags, ip);
+#else
+ desc->random_ip = ip;
#endif
if (!noirqdebug)
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 87dc0539cebb..220434039176 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -816,6 +816,12 @@ static int irq_thread(void *data)
action_ret = handler_fn(desc, action);
if (!noirqdebug)
note_interrupt(action->irq, desc, action_ret);
+#ifdef CONFIG_PREEMPT_RT_FULL
+ migrate_disable();
+ add_interrupt_randomness(action->irq, 0,
+ desc->random_ip ^ (u64) action);
+ migrate_enable();
+#endif
}
wake = atomic_dec_and_test(&desc->threads_active);