]> rtime.felk.cvut.cz Git - zynq/linux.git/commitdiff
random: Make it work on rt
authorThomas Gleixner <tglx@linutronix.de>
Tue, 21 Aug 2012 18:38:50 +0000 (20:38 +0200)
committerMichal Sojka <sojka@merica.cz>
Sun, 13 Sep 2015 07:47:38 +0000 (09:47 +0200)
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
drivers/char/random.c
include/linux/irqdesc.h
include/linux/random.h
kernel/irq/handle.c
kernel/irq/manage.c

index 9a07ef22fab16e8c82336cf63df9d79f3808193f..eb47efec2506ccfb76f00440e639c7d1d29b59e4 100644 (file)
@@ -868,28 +868,27 @@ static __u32 get_reg(struct fast_pool *f, struct pt_regs *regs)
        return *(ptr + f->reg_idx++);
 }
 
-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 = this_cpu_ptr(&irq_randomness);
-       struct pt_regs          *regs = get_irq_regs();
        unsigned long           now = jiffies;
        cycles_t                cycles = random_get_entropy();
        __u32                   c_high, j_high;
-       __u64                   ip;
        unsigned long           seed;
        int                     credit = 0;
 
        if (cycles == 0)
-               cycles = get_reg(fast_pool, regs);
+               cycles = get_reg(fast_pool, NULL);
        c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0;
        j_high = (sizeof(now) > 4) ? now >> 32 : 0;
        fast_pool->pool[0] ^= cycles ^ j_high ^ irq;
        fast_pool->pool[1] ^= now ^ c_high;
-       ip = regs ? instruction_pointer(regs) : _RET_IP_;
+       if (!ip)
+               ip = _RET_IP_;
        fast_pool->pool[2] ^= ip;
        fast_pool->pool[3] ^= (sizeof(ip) > 4) ? ip >> 32 :
-               get_reg(fast_pool, regs);
+               get_reg(fast_pool, NULL);
 
        fast_mix(fast_pool);
        add_interrupt_bench(cycles);
index dd1109fb241e42263e5851ddbc325f469c42a87c..9d97cd5bb7c7998ffc54dcb54557c1a940997289 100644 (file)
@@ -63,6 +63,7 @@ struct irq_desc {
        unsigned int            irqs_unhandled;
        atomic_t                threads_handled;
        int                     threads_handled_last;
+       u64                     random_ip;
        raw_spinlock_t          lock;
        struct cpumask          *percpu_enabled;
 #ifdef CONFIG_SMP
index b05856e16b75be8b7dea5015a5a6ff6afcb021eb..4a64ad52dcb749b30e7cc078d7d750f9e8f6fa12 100644 (file)
@@ -11,7 +11,7 @@
 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);
index 635480270858448064b1afa54bf616f074744d60..26a63672c26307ab3682291fb549a33c886536e3 100644 (file)
@@ -133,6 +133,8 @@ 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;
 
@@ -173,7 +175,11 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
                action = action->next;
        } while (action);
 
-       add_interrupt_randomness(irq, flags);
+#ifndef CONFIG_PREEMPT_RT_FULL
+       add_interrupt_randomness(irq, flags, ip);
+#else
+       desc->random_ip = ip;
+#endif
 
        if (!noirqdebug)
                note_interrupt(irq, desc, retval);
index 440543e03bb86ad527cca8cb4badb1642df1939d..00093fc0c7115b87f4a01cf4aa7c2671cf3cc2f8 100644 (file)
@@ -959,6 +959,12 @@ static int irq_thread(void *data)
                if (action_ret == IRQ_HANDLED)
                        atomic_inc(&desc->threads_handled);
 
+#ifdef CONFIG_PREEMPT_RT_FULL
+               migrate_disable();
+               add_interrupt_randomness(action->irq, 0,
+                                desc->random_ip ^ (unsigned long) action);
+               migrate_enable();
+#endif
                wake_threads_waitq(desc);
        }