1b14959daSJustin Hibbits /*- 2b14959daSJustin Hibbits * Copyright (c) 2018 Justin Hibbits 3b14959daSJustin Hibbits * Copyright (c) 2013 The FreeBSD Foundation 4b14959daSJustin Hibbits * Copyright (c) 2013 David E. O'Brien <obrien@NUXI.org> 5b14959daSJustin Hibbits * Copyright (c) 2012 Konstantin Belousov <kib@FreeBSD.org> 6b14959daSJustin Hibbits * All rights reserved. 7b14959daSJustin Hibbits * 8b14959daSJustin Hibbits * Portions of this software were developed by Konstantin Belousov 9b14959daSJustin Hibbits * under sponsorship from the FreeBSD Foundation. 10b14959daSJustin Hibbits * 11b14959daSJustin Hibbits * Redistribution and use in source and binary forms, with or without 12b14959daSJustin Hibbits * modification, are permitted provided that the following conditions 13b14959daSJustin Hibbits * are met: 14b14959daSJustin Hibbits * 1. Redistributions of source code must retain the above copyright 15b14959daSJustin Hibbits * notice, this list of conditions and the following disclaimer 16b14959daSJustin Hibbits * in this position and unchanged. 17b14959daSJustin Hibbits * 2. Redistributions in binary form must reproduce the above copyright 18b14959daSJustin Hibbits * notice, this list of conditions and the following disclaimer in the 19b14959daSJustin Hibbits * documentation and/or other materials provided with the distribution. 20b14959daSJustin Hibbits * 21b14959daSJustin Hibbits * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22b14959daSJustin Hibbits * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23b14959daSJustin Hibbits * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24b14959daSJustin Hibbits * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25b14959daSJustin Hibbits * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26b14959daSJustin Hibbits * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27b14959daSJustin Hibbits * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28b14959daSJustin Hibbits * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29b14959daSJustin Hibbits * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30b14959daSJustin Hibbits * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31b14959daSJustin Hibbits * 32b14959daSJustin Hibbits */ 33b14959daSJustin Hibbits 34b14959daSJustin Hibbits #include <sys/cdefs.h> 35b14959daSJustin Hibbits __FBSDID("$FreeBSD$"); 36b14959daSJustin Hibbits 37b14959daSJustin Hibbits #include <sys/param.h> 38b14959daSJustin Hibbits #include <sys/kernel.h> 39b14959daSJustin Hibbits #include <sys/conf.h> 40b14959daSJustin Hibbits #include <sys/lock.h> 41b14959daSJustin Hibbits #include <sys/malloc.h> 42b14959daSJustin Hibbits #include <sys/module.h> 43b14959daSJustin Hibbits #include <sys/random.h> 44b14959daSJustin Hibbits #include <sys/systm.h> 45b14959daSJustin Hibbits 46b14959daSJustin Hibbits #include <machine/cpu.h> 47b14959daSJustin Hibbits #include <machine/md_var.h> 48b14959daSJustin Hibbits 49b14959daSJustin Hibbits #include <dev/random/randomdev.h> 50b14959daSJustin Hibbits 51b14959daSJustin Hibbits /* 52b14959daSJustin Hibbits * Power ISA 3.0 adds a "darn" instruction (Deliver A Random Number). The RNG 53b14959daSJustin Hibbits * backing this instruction conforms to NIST SP800-90B and SP800-90C at the 54b14959daSJustin Hibbits * point of hardware design, and provides a minimum of 0.5 bits of entropy per 55b14959daSJustin Hibbits * bit. 56b14959daSJustin Hibbits */ 57b14959daSJustin Hibbits 58b14959daSJustin Hibbits #define RETRY_COUNT 10 59b14959daSJustin Hibbits 60b14959daSJustin Hibbits static u_int random_darn_read(void *, u_int); 61b14959daSJustin Hibbits 62b14959daSJustin Hibbits static struct random_source random_darn = { 63b14959daSJustin Hibbits .rs_ident = "PowerISA DARN random number generator", 64b14959daSJustin Hibbits .rs_source = RANDOM_PURE_DARN, 65b14959daSJustin Hibbits .rs_read = random_darn_read 66b14959daSJustin Hibbits }; 67b14959daSJustin Hibbits 68b14959daSJustin Hibbits static inline int 69b14959daSJustin Hibbits darn_rng_store(u_long *buf) 70b14959daSJustin Hibbits { 71b14959daSJustin Hibbits u_long rndval; 72b14959daSJustin Hibbits int retry; 73b14959daSJustin Hibbits 74b14959daSJustin Hibbits for (retry = RETRY_COUNT; retry > 0; --retry) { 75b14959daSJustin Hibbits /* "DARN %rN, 1" instruction */ 76b14959daSJustin Hibbits /* 77b14959daSJustin Hibbits * Arguments for DARN: rN and "L", where "L" can be one of: 78b14959daSJustin Hibbits * 0 - 32-bit conditional random number 79b14959daSJustin Hibbits * 1 - Conditional random number (conditioned to remove bias) 80b14959daSJustin Hibbits * 2 - Raw random number (unprocessed, may include bias) 81b14959daSJustin Hibbits * 3 - Reserved 82b14959daSJustin Hibbits */ 83b14959daSJustin Hibbits __asm __volatile(".long 0x7c0105e6 | (%0 << 21)" : 84b14959daSJustin Hibbits "+r"(rndval)); 85b14959daSJustin Hibbits if (rndval != ~0) 86b14959daSJustin Hibbits break; 87b14959daSJustin Hibbits } 88b14959daSJustin Hibbits 89b14959daSJustin Hibbits *buf = rndval; 90b14959daSJustin Hibbits return (retry); 91b14959daSJustin Hibbits } 92b14959daSJustin Hibbits 93b14959daSJustin Hibbits /* It is required that buf length is a multiple of sizeof(u_long). */ 94b14959daSJustin Hibbits static u_int 95b14959daSJustin Hibbits random_darn_read(void *buf, u_int c) 96b14959daSJustin Hibbits { 97b14959daSJustin Hibbits u_long *b, rndval; 98b14959daSJustin Hibbits u_int count; 99b14959daSJustin Hibbits 100b14959daSJustin Hibbits KASSERT(c % sizeof(*b) == 0, ("partial read %d", c)); 101b14959daSJustin Hibbits b = buf; 102b14959daSJustin Hibbits for (count = c; count > 0; count -= sizeof(*b)) { 103b14959daSJustin Hibbits if (darn_rng_store(&rndval) == 0) 104b14959daSJustin Hibbits break; 105b14959daSJustin Hibbits *b++ = rndval; 106b14959daSJustin Hibbits } 107b14959daSJustin Hibbits return (c - count); 108b14959daSJustin Hibbits } 109b14959daSJustin Hibbits 110b14959daSJustin Hibbits static int 111b14959daSJustin Hibbits darn_modevent(module_t mod, int type, void *unused) 112b14959daSJustin Hibbits { 113b14959daSJustin Hibbits int error = 0; 114b14959daSJustin Hibbits 115b14959daSJustin Hibbits switch (type) { 116b14959daSJustin Hibbits case MOD_LOAD: 117b14959daSJustin Hibbits if (cpu_features2 & PPC_FEATURE2_DARN) { 118b14959daSJustin Hibbits random_source_register(&random_darn); 119b14959daSJustin Hibbits printf("random: fast provider: \"%s\"\n", random_darn.rs_ident); 120b14959daSJustin Hibbits } 121b14959daSJustin Hibbits break; 122b14959daSJustin Hibbits 123b14959daSJustin Hibbits case MOD_UNLOAD: 124b14959daSJustin Hibbits if (cpu_features2 & PPC_FEATURE2_DARN) 125b14959daSJustin Hibbits random_source_deregister(&random_darn); 126b14959daSJustin Hibbits break; 127b14959daSJustin Hibbits 128b14959daSJustin Hibbits case MOD_SHUTDOWN: 129b14959daSJustin Hibbits break; 130b14959daSJustin Hibbits 131b14959daSJustin Hibbits default: 132b14959daSJustin Hibbits error = EOPNOTSUPP; 133b14959daSJustin Hibbits break; 134b14959daSJustin Hibbits 135b14959daSJustin Hibbits } 136b14959daSJustin Hibbits 137b14959daSJustin Hibbits return (error); 138b14959daSJustin Hibbits } 139b14959daSJustin Hibbits 140*7384206aSConrad Meyer static moduledata_t darn_mod = { 141*7384206aSConrad Meyer "darn", 142*7384206aSConrad Meyer darn_modevent, 143*7384206aSConrad Meyer 0 144*7384206aSConrad Meyer }; 145*7384206aSConrad Meyer 146*7384206aSConrad Meyer DECLARE_MODULE(darn, darn_mod, SI_SUB_RANDOM, SI_ORDER_FOURTH); 147b14959daSJustin Hibbits MODULE_VERSION(darn, 1); 148*7384206aSConrad Meyer MODULE_DEPEND(darn, random_harvestq, 1, 1, 1); 149