Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/random/random_harvestq.c
Show First 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/module.h> | #include <sys/module.h> | ||||
#include <sys/mutex.h> | #include <sys/mutex.h> | ||||
#include <sys/random.h> | #include <sys/random.h> | ||||
#include <sys/sbuf.h> | #include <sys/sbuf.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/unistd.h> | #include <sys/unistd.h> | ||||
#if defined(RANDOM_LOADABLE) | |||||
#include <sys/lock.h> | |||||
#include <sys/sx.h> | |||||
#endif | |||||
#include <machine/atomic.h> | #include <machine/atomic.h> | ||||
#include <machine/cpu.h> | #include <machine/cpu.h> | ||||
#include <crypto/rijndael/rijndael-api-fst.h> | #include <crypto/rijndael/rijndael-api-fst.h> | ||||
#include <crypto/sha2/sha256.h> | #include <crypto/sha2/sha256.h> | ||||
#include <dev/random/hash.h> | #include <dev/random/hash.h> | ||||
#include <dev/random/randomdev.h> | #include <dev/random/randomdev.h> | ||||
▲ Show 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | static struct kproc_desc random_proc_kp = { | ||||
random_kthread, | random_kthread, | ||||
&harvest_context.hc_kthread_proc, | &harvest_context.hc_kthread_proc, | ||||
}; | }; | ||||
/* Pass the given event straight through to Fortuna/Whatever. */ | /* Pass the given event straight through to Fortuna/Whatever. */ | ||||
static __inline void | static __inline void | ||||
random_harvestq_fast_process_event(struct harvest_event *event) | random_harvestq_fast_process_event(struct harvest_event *event) | ||||
{ | { | ||||
#if defined(RANDOM_LOADABLE) | |||||
RANDOM_CONFIG_S_LOCK(); | |||||
if (p_random_alg_context) | |||||
#endif | |||||
markm: Seeing these go gives me MUCH pleasure! | |||||
gordonUnsubmitted Not Done Inline ActionsDo we have any notion of how much faster this will be without the locking? gordon: Do we have any notion of how much faster this will be without the locking? | |||||
cemAuthorUnsubmitted Done Inline ActionsHonestly, speed wasn't a factor I'd considered at all. That's not the motivation for the change. GENERIC sets nooption RANDOM_LOADABLE, so it didn't have these locks before this change. cem: Honestly, speed wasn't a factor I'd considered at all. That's not the motivation for the… | |||||
p_random_alg_context->ra_event_processor(event); | p_random_alg_context->ra_event_processor(event); | ||||
#if defined(RANDOM_LOADABLE) | |||||
RANDOM_CONFIG_S_UNLOCK(); | |||||
#endif | |||||
explicit_bzero(event, sizeof(*event)); | explicit_bzero(event, sizeof(*event)); | ||||
} | } | ||||
static void | static void | ||||
random_kthread(void) | random_kthread(void) | ||||
{ | { | ||||
u_int maxloop, ring_out, i; | u_int maxloop, ring_out, i; | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | random_sources_feed(void) | ||||
uint32_t entropy[HARVESTSIZE]; | uint32_t entropy[HARVESTSIZE]; | ||||
struct random_sources *rrs; | struct random_sources *rrs; | ||||
u_int i, n, local_read_rate; | u_int i, n, local_read_rate; | ||||
/* | /* | ||||
* Step over all of live entropy sources, and feed their output | * Step over all of live entropy sources, and feed their output | ||||
* to the system-wide RNG. | * to the system-wide RNG. | ||||
*/ | */ | ||||
#if defined(RANDOM_LOADABLE) | |||||
RANDOM_CONFIG_S_LOCK(); | |||||
if (p_random_alg_context) { | |||||
/* It's an indenting error. Yeah, Yeah. */ | |||||
#endif | |||||
local_read_rate = atomic_readandclear_32(&read_rate); | local_read_rate = atomic_readandclear_32(&read_rate); | ||||
/* Perform at least one read per round */ | /* Perform at least one read per round */ | ||||
local_read_rate = MAX(local_read_rate, 1); | local_read_rate = MAX(local_read_rate, 1); | ||||
/* But not exceeding RANDOM_KEYSIZE_WORDS */ | /* But not exceeding RANDOM_KEYSIZE_WORDS */ | ||||
local_read_rate = MIN(local_read_rate, RANDOM_KEYSIZE_WORDS); | local_read_rate = MIN(local_read_rate, RANDOM_KEYSIZE_WORDS); | ||||
LIST_FOREACH(rrs, &source_list, rrs_entries) { | LIST_FOREACH(rrs, &source_list, rrs_entries) { | ||||
for (i = 0; i < p_random_alg_context->ra_poolcount*local_read_rate; i++) { | for (i = 0; i < p_random_alg_context->ra_poolcount*local_read_rate; i++) { | ||||
n = rrs->rrs_source->rs_read(entropy, sizeof(entropy)); | n = rrs->rrs_source->rs_read(entropy, sizeof(entropy)); | ||||
Show All 10 Lines | for (i = 0; i < p_random_alg_context->ra_poolcount*local_read_rate; i++) { | ||||
* But it's still a better entropy source than RDRAND. | * But it's still a better entropy source than RDRAND. | ||||
*/ | */ | ||||
if (n == 0) | if (n == 0) | ||||
continue; | continue; | ||||
random_harvest_direct(entropy, n, rrs->rrs_source->rs_source); | random_harvest_direct(entropy, n, rrs->rrs_source->rs_source); | ||||
} | } | ||||
} | } | ||||
explicit_bzero(entropy, sizeof(entropy)); | explicit_bzero(entropy, sizeof(entropy)); | ||||
#if defined(RANDOM_LOADABLE) | |||||
} | } | ||||
RANDOM_CONFIG_S_UNLOCK(); | |||||
#endif | |||||
} | |||||
void | void | ||||
read_rate_increment(u_int chunk) | read_rate_increment(u_int chunk) | ||||
{ | { | ||||
atomic_add_32(&read_rate, chunk); | atomic_add_32(&read_rate, chunk); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 114 Lines • ▼ Show 20 Lines | random_harvestq_init(void *unused __unused) | ||||
static const u_int almost_everything_mask = | static const u_int almost_everything_mask = | ||||
(((1 << (RANDOM_ENVIRONMENTAL_END + 1)) - 1) & | (((1 << (RANDOM_ENVIRONMENTAL_END + 1)) - 1) & | ||||
~_RANDOM_HARVEST_ETHER_OFF & ~_RANDOM_HARVEST_UMA_OFF); | ~_RANDOM_HARVEST_ETHER_OFF & ~_RANDOM_HARVEST_UMA_OFF); | ||||
hc_source_mask = almost_everything_mask; | hc_source_mask = almost_everything_mask; | ||||
RANDOM_HARVEST_INIT_LOCK(); | RANDOM_HARVEST_INIT_LOCK(); | ||||
harvest_context.hc_entropy_ring.in = harvest_context.hc_entropy_ring.out = 0; | harvest_context.hc_entropy_ring.in = harvest_context.hc_entropy_ring.out = 0; | ||||
} | } | ||||
SYSINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_SECOND, random_harvestq_init, NULL); | SYSINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_THIRD, random_harvestq_init, NULL); | ||||
gordonUnsubmitted Not Done Inline ActionsAre there any potential problems with this being reordered to THIRD that breaks assumptions about availability? gordon: Are there any potential problems with this being reordered to THIRD that breaks assumptions… | |||||
cemAuthorUnsubmitted Done Inline ActionsI will double check, but I don't believe so. cem: I will double check, but I don't believe so. | |||||
cemAuthorUnsubmitted Done Inline ActionsI don't believe this one is problematic. The most problematic ordering is that algorithms (i.e., Fortuna), and randomdev.c both initialize at SI_SUB_RANDOM:SI_ORDER_SECOND. However, neither actually depends on the other, and SI_SUB_RANDOM is long before SI_SUB_SMP or any concurrency kicks off. So I think we're fine in practice. cem: I don't believe this one is problematic. The most problematic ordering is that algorithms (i.e. | |||||
/* | /* | ||||
* Subroutine to slice up a contiguous chunk of 'entropy' and feed it into the | * Subroutine to slice up a contiguous chunk of 'entropy' and feed it into the | ||||
* underlying algorithm. Returns number of bytes actually fed into underlying | * underlying algorithm. Returns number of bytes actually fed into underlying | ||||
* algorithm. | * algorithm. | ||||
*/ | */ | ||||
static size_t | static size_t | ||||
random_early_prime(char *entropy, size_t len) | random_early_prime(char *entropy, size_t len) | ||||
▲ Show 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | |||||
random_harvestq_deinit(void *unused __unused) | random_harvestq_deinit(void *unused __unused) | ||||
{ | { | ||||
/* Command the hash/reseed thread to end and wait for it to finish */ | /* Command the hash/reseed thread to end and wait for it to finish */ | ||||
random_kthread_control = 0; | random_kthread_control = 0; | ||||
while (random_kthread_control >= 0) | while (random_kthread_control >= 0) | ||||
tsleep(&harvest_context.hc_kthread_proc, 0, "harvqterm", hz/5); | tsleep(&harvest_context.hc_kthread_proc, 0, "harvqterm", hz/5); | ||||
} | } | ||||
SYSUNINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_SECOND, random_harvestq_deinit, NULL); | SYSUNINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_THIRD, random_harvestq_deinit, NULL); | ||||
/*- | /*- | ||||
* Entropy harvesting queue routine. | * Entropy harvesting queue routine. | ||||
* | * | ||||
* This is supposed to be fast; do not do anything slow in here! | * This is supposed to be fast; do not do anything slow in here! | ||||
* It is also illegal (and morally reprehensible) to insert any | * It is also illegal (and morally reprehensible) to insert any | ||||
* high-rate data here. "High-rate" is defined as a data source | * high-rate data here. "High-rate" is defined as a data source | ||||
* that will usually cause lots of failures of the "Lockless read" | * that will usually cause lots of failures of the "Lockless read" | ||||
▲ Show 20 Lines • Show All 144 Lines • Show Last 20 Lines |
Seeing these go gives me MUCH pleasure!