1*ef9461baSKonstantin Belousov /*- 2*ef9461baSKonstantin Belousov * Copyright (c) 2012 Konstantin Belousov <kib@FreeBSD.org> 3*ef9461baSKonstantin Belousov * All rights reserved. 4*ef9461baSKonstantin Belousov * 5*ef9461baSKonstantin Belousov * Redistribution and use in source and binary forms, with or without 6*ef9461baSKonstantin Belousov * modification, are permitted provided that the following conditions 7*ef9461baSKonstantin Belousov * are met: 8*ef9461baSKonstantin Belousov * 1. Redistributions of source code must retain the above copyright 9*ef9461baSKonstantin Belousov * notice, this list of conditions and the following disclaimer 10*ef9461baSKonstantin Belousov * in this position and unchanged. 11*ef9461baSKonstantin Belousov * 2. Redistributions in binary form must reproduce the above copyright 12*ef9461baSKonstantin Belousov * notice, this list of conditions and the following disclaimer in the 13*ef9461baSKonstantin Belousov * documentation and/or other materials provided with the distribution. 14*ef9461baSKonstantin Belousov * 15*ef9461baSKonstantin Belousov * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16*ef9461baSKonstantin Belousov * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17*ef9461baSKonstantin Belousov * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18*ef9461baSKonstantin Belousov * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19*ef9461baSKonstantin Belousov * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20*ef9461baSKonstantin Belousov * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21*ef9461baSKonstantin Belousov * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22*ef9461baSKonstantin Belousov * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23*ef9461baSKonstantin Belousov * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24*ef9461baSKonstantin Belousov * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25*ef9461baSKonstantin Belousov * 26*ef9461baSKonstantin Belousov */ 27*ef9461baSKonstantin Belousov 28*ef9461baSKonstantin Belousov #include <sys/cdefs.h> 29*ef9461baSKonstantin Belousov __FBSDID("$FreeBSD$"); 30*ef9461baSKonstantin Belousov 31*ef9461baSKonstantin Belousov #include "opt_cpu.h" 32*ef9461baSKonstantin Belousov 33*ef9461baSKonstantin Belousov #ifdef IVY_RNG 34*ef9461baSKonstantin Belousov 35*ef9461baSKonstantin Belousov #include <sys/param.h> 36*ef9461baSKonstantin Belousov #include <sys/time.h> 37*ef9461baSKonstantin Belousov #include <sys/lock.h> 38*ef9461baSKonstantin Belousov #include <sys/mutex.h> 39*ef9461baSKonstantin Belousov #include <sys/selinfo.h> 40*ef9461baSKonstantin Belousov #include <sys/systm.h> 41*ef9461baSKonstantin Belousov #include <dev/random/randomdev.h> 42*ef9461baSKonstantin Belousov 43*ef9461baSKonstantin Belousov #define RETRY_COUNT 10 44*ef9461baSKonstantin Belousov 45*ef9461baSKonstantin Belousov static void random_ivy_init(void); 46*ef9461baSKonstantin Belousov static void random_ivy_deinit(void); 47*ef9461baSKonstantin Belousov static int random_ivy_read(void *, int); 48*ef9461baSKonstantin Belousov 49*ef9461baSKonstantin Belousov struct random_systat random_ivy = { 50*ef9461baSKonstantin Belousov .ident = "Hardware, Intel IvyBridge+ RNG", 51*ef9461baSKonstantin Belousov .init = random_ivy_init, 52*ef9461baSKonstantin Belousov .deinit = random_ivy_deinit, 53*ef9461baSKonstantin Belousov .read = random_ivy_read, 54*ef9461baSKonstantin Belousov .write = (random_write_func_t *)random_null_func, 55*ef9461baSKonstantin Belousov .reseed = (random_reseed_func_t *)random_null_func, 56*ef9461baSKonstantin Belousov .seeded = 1, 57*ef9461baSKonstantin Belousov }; 58*ef9461baSKonstantin Belousov 59*ef9461baSKonstantin Belousov static inline int 60*ef9461baSKonstantin Belousov ivy_rng_store(long *tmp) 61*ef9461baSKonstantin Belousov { 62*ef9461baSKonstantin Belousov #ifdef __GNUCLIKE_ASM 63*ef9461baSKonstantin Belousov uint32_t count; 64*ef9461baSKonstantin Belousov 65*ef9461baSKonstantin Belousov __asm __volatile( 66*ef9461baSKonstantin Belousov #ifdef __amd64__ 67*ef9461baSKonstantin Belousov ".byte\t0x48,0x0f,0xc7,0xf0\n\t" /* rdrand %rax */ 68*ef9461baSKonstantin Belousov "jnc\t1f\n\t" 69*ef9461baSKonstantin Belousov "movq\t%%rax,%1\n\t" 70*ef9461baSKonstantin Belousov "movl\t$8,%%eax\n" 71*ef9461baSKonstantin Belousov #else /* i386 */ 72*ef9461baSKonstantin Belousov ".byte\t0x0f,0xc7,0xf0\n\t" /* rdrand %eax */ 73*ef9461baSKonstantin Belousov "jnc\t1f\n\t" 74*ef9461baSKonstantin Belousov "movl\t%%eax,%1\n\t" 75*ef9461baSKonstantin Belousov "movl\t$4,%%eax\n" 76*ef9461baSKonstantin Belousov #endif 77*ef9461baSKonstantin Belousov "1:\n" /* %eax is cleared by processor on failure */ 78*ef9461baSKonstantin Belousov : "=a" (count), "=g" (*tmp) : "a" (0) : "cc"); 79*ef9461baSKonstantin Belousov return (count); 80*ef9461baSKonstantin Belousov #else /* __GNUCLIKE_ASM */ 81*ef9461baSKonstantin Belousov return (0); 82*ef9461baSKonstantin Belousov #endif 83*ef9461baSKonstantin Belousov } 84*ef9461baSKonstantin Belousov 85*ef9461baSKonstantin Belousov static void 86*ef9461baSKonstantin Belousov random_ivy_init(void) 87*ef9461baSKonstantin Belousov { 88*ef9461baSKonstantin Belousov } 89*ef9461baSKonstantin Belousov 90*ef9461baSKonstantin Belousov void 91*ef9461baSKonstantin Belousov random_ivy_deinit(void) 92*ef9461baSKonstantin Belousov { 93*ef9461baSKonstantin Belousov } 94*ef9461baSKonstantin Belousov 95*ef9461baSKonstantin Belousov static int 96*ef9461baSKonstantin Belousov random_ivy_read(void *buf, int c) 97*ef9461baSKonstantin Belousov { 98*ef9461baSKonstantin Belousov char *b; 99*ef9461baSKonstantin Belousov long tmp; 100*ef9461baSKonstantin Belousov int count, res, retry; 101*ef9461baSKonstantin Belousov 102*ef9461baSKonstantin Belousov for (count = c, b = buf; count > 0; count -= res, b += res) { 103*ef9461baSKonstantin Belousov for (retry = 0; retry < RETRY_COUNT; retry++) { 104*ef9461baSKonstantin Belousov res = ivy_rng_store(&tmp); 105*ef9461baSKonstantin Belousov if (res != 0) 106*ef9461baSKonstantin Belousov break; 107*ef9461baSKonstantin Belousov } 108*ef9461baSKonstantin Belousov if (res == 0) 109*ef9461baSKonstantin Belousov break; 110*ef9461baSKonstantin Belousov if (res > count) 111*ef9461baSKonstantin Belousov res = count; 112*ef9461baSKonstantin Belousov memcpy(b, &tmp, res); 113*ef9461baSKonstantin Belousov } 114*ef9461baSKonstantin Belousov return (c - count); 115*ef9461baSKonstantin Belousov } 116*ef9461baSKonstantin Belousov 117*ef9461baSKonstantin Belousov #endif 118