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
This commit is contained in:
parent
76606fcb9c
commit
41d88b03da
|
@ -832,21 +832,20 @@ 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;
|
||||
cycles_t cycles = random_get_entropy();
|
||||
__u32 input[4], c_high, j_high;
|
||||
__u64 ip;
|
||||
|
||||
c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0;
|
||||
j_high = (sizeof(now) > 4) ? now >> 32 : 0;
|
||||
input[0] = cycles ^ j_high ^ irq;
|
||||
input[1] = now ^ c_high;
|
||||
ip = regs ? instruction_pointer(regs) : _RET_IP_;
|
||||
if (!ip)
|
||||
ip = _RET_IP_;
|
||||
input[2] = ip;
|
||||
input[3] = ip >> 32;
|
||||
|
||||
|
@ -858,7 +857,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
|
||||
|
|
|
@ -56,6 +56,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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -132,6 +132,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;
|
||||
|
||||
|
@ -172,7 +174,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);
|
||||
|
|
|
@ -942,6 +942,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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue