Home | History | Annotate | Download | only in n2rng
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include <sys/types.h>
     27 #include <sys/sysmacros.h>
     28 #include <sys/modctl.h>
     29 #include <sys/conf.h>
     30 #include <sys/devops.h>
     31 #include <sys/cmn_err.h>
     32 #include <sys/kmem.h>
     33 #include <sys/stat.h>
     34 #include <sys/open.h>
     35 #include <sys/file.h>
     36 #include <sys/ddi.h>
     37 #include <sys/sunddi.h>
     38 #include <sys/cpuvar.h>
     39 #include <sys/disp.h>
     40 #include <sys/hsvc.h>
     41 #include <sys/machsystm.h>
     42 #include <sys/param.h>
     43 #include <sys/hypervisor_api.h>
     44 #include <sys/n2rng.h>
     45 
     46 /*
     47  * There are 3 noise cells each with its own oscillator, and each
     48  * oscillator can be set to 4 different bias setttings.  The bias
     49  * setting controls the nominal frequency of the oscillator.  The 3
     50  * and 4 and hardcoded throughout this file.
     51  */
     52 
     53 #define	BITS_IN(type) (8 * sizeof (type))
     54 #define	EXTRACTBIT64(val, bit) (((val) >> (bit)) & 1UL)
     55 
     56 /*
     57  * Policy settings
     58  */
     59 /* Log2 of the number of bits */
     60 #define	SETTLECYCLES		1000000
     61 #define	NORMAL_BYPASS		1
     62 #define	NUMOSC			3
     63 #define	LOG2_DATA_WORDS		15
     64 #define	DATA_WORDS		(1 << LOG2_DATA_WORDS)
     65 
     66 #define	ENTROPY_PASS_VALUE	150000000ULL
     67 
     68 /*
     69  * There is a hardware bug that causes the RNG_DATA register to
     70  * occasionally be read one cycle before the specifed time.
     71  * LOGIC_TEST_EXPECTED_M1 is the value one cycle before
     72  * LOGIC_TEST_CYCLES.  And there is a second bug that causes the read
     73  * to be delayed.  We have seen delays of about 150 cycles, but do not
     74  * know that maximum that could possibly occur.
     75  *
     76  * We collect LOGIC_TEST_WORDS words using a diagnostic read with all
     77  * entropy turned off.  The first one we skip, becuase we have no
     78  * knowledge of the time since the last read.  We check that the
     79  * remaining values fall in the window of values that should occur
     80  * between LOGIC_TEST_CYCLES - 1 and LOGIC_TEST_CYCLES +
     81  * LOGIC_TEST_BUG_MAX.  As further protecion against false positives,
     82  * we report success if the the number of mismatches does not exceed
     83  * LOGIC_TEST_ERRORS_ALLOWED.
     84  *
     85  * When running on maramba systems, delays as high as 20000 were observed
     86  * LOGIC_TEST_BUG_MAX was increased to twice this observed value since all
     87  * that matters is that the hardware is indeed generating the expected values
     88  * in diag mode.  The code was also modified to exit as soon as the required
     89  * number of matches is detected.
     90  */
     91 
     92 #define	LOGIC_TEST_CYCLES	  38859
     93 #define	LOGIC_TEST_EXPECTED_M1	  0xb8820c7bd387e32cULL
     94 #define	LOGIC_TEST_BUG_MAX	  40000
     95 #define	LOGIC_TEST_WORDS	  8 /* includes first one, unused */
     96 #define	LOGIC_TEST_ERRORS_ALLOWED 1
     97 #define	LOGIC_TEST_MATCHES_NEEDED (LOGIC_TEST_WORDS - 1 - \
     98 					LOGIC_TEST_ERRORS_ALLOWED)
     99 
    100 #define	RNG_POLY		0x231dcee91262b8a3ULL
    101 #define	ENTDIVISOR		(((1ULL << LOG_VAL_SCALE) + 500ULL) / 1000ULL)
    102 
    103 #define	ENCODEBIAS(osc, bias)	(((bias) & 0x3) << (2 * (osc)))
    104 #define	EXTRACTBIAS(blob, osc)	(((blob) >> (2 * (osc))) & 0x3)
    105 
    106 extern int n2rng_herr2kerr(uint64_t hv_errcode);
    107 
    108 
    109 /*
    110  * Each value is a representation of the polynomail bit_i * x^i, where
    111  * i=0 corresponds to the least significant bit of the word.  The
    112  * modulus polynomial is x^64 + the interpretation of poly.  Out is
    113  * set to in * x^exp mod moduluspolynomial.  This corresponds to
    114  * running the LFSR exp cycles.  This implemenation directly simulates
    115  * the lfsr.  It's running time is O(exp), but the constant is small.
    116  * (This code was taken verbatim from Legion.)
    117  */
    118 static void
    119 lfsr64_adv_seq(uint64_t poly, uint64_t in, uint64_t exp, uint64_t *out)
    120 {
    121 	int		i;
    122 	uint64_t	res = in;
    123 
    124 	for (i = 0; i < exp; i++) {
    125 		if (res & 0x8000000000000000ULL) {
    126 			res = (res << 1) ^ poly;
    127 		} else {
    128 			res <<= 1;
    129 		}
    130 	}
    131 
    132 	*out = res;
    133 }
    134 
    135 int
    136 n2rng_logic_test(n2rng_t *n2rng, int rngid)
    137 {
    138 	n2rng_setup_t	logictest;
    139 	uint64_t	buffer[LOGIC_TEST_WORDS];
    140 	uint64_t	reg;
    141 	int		rv;
    142 	int		i, j;
    143 	int		correctcount = 0;
    144 	rng_entry_t	*rng = &n2rng->n_ctl_data->n_rngs[rngid];
    145 	int		cycles[LOGIC_TEST_WORDS] =
    146 			{0, 0, 0, 0, 0, 0, 0, 0};
    147 
    148 	/*
    149 	 * This test runs the RNG with no entropy for
    150 	 * LOGIC_TEST_CYCLES cycles.  Ideally the value would be be
    151 	 * LOGIC_TEST_RESULT, but because of the RNG bug, the actual
    152 	 * register read may be delayed by upto LOGIC_TEST_BUG_MAX
    153 	 * cycles.  So we simulate over that window, and a match
    154 	 * occurs, we report success.
    155 	 */
    156 
    157 	logictest.ctlwds[0].word = 0;
    158 	logictest.ctlwds[0].fields.rnc_anlg_sel = N2RNG_NOANALOGOUT;
    159 	logictest.ctlwds[1] = logictest.ctlwds[0];
    160 	logictest.ctlwds[2] = logictest.ctlwds[0];
    161 	logictest.ctlwds[3] = logictest.ctlwds[0];
    162 	logictest.ctlwds[3].fields.rnc_mode = 1;
    163 	logictest.ctlwds[3].fields.rnc_cnt = LOGIC_TEST_CYCLES - 2;
    164 
    165 	/* read LOGIC_TEST_WORDS 64-bit words */
    166 	rv = n2rng_collect_diag_bits(n2rng, rngid, &logictest, buffer,
    167 	    LOGIC_TEST_WORDS * sizeof (uint64_t),
    168 	    &rng->n_preferred_config, rng->n_rng_state);
    169 	if (rv) {
    170 		cmn_err(CE_WARN, "n2rng: n2rng_collect_diag_bits failed with "
    171 		    "0x%x on rng(%d)", rv, rngid);
    172 		return (rv);
    173 	}
    174 
    175 	reg = LOGIC_TEST_EXPECTED_M1;
    176 	for (i = 0; i <= LOGIC_TEST_BUG_MAX; i++) {
    177 		for (j = 1; j < LOGIC_TEST_WORDS; ++j) {
    178 			if (buffer[j] == reg) {
    179 				++correctcount;
    180 				cycles[j] = i;
    181 			}
    182 		}
    183 		/* exit loop if we have already found enough matches */
    184 		if (correctcount >= LOGIC_TEST_MATCHES_NEEDED) {
    185 			break;
    186 		}
    187 		/* advance reg by one step */
    188 		lfsr64_adv_seq(RNG_POLY, reg, 1, &reg);
    189 	}
    190 
    191 	if (correctcount < LOGIC_TEST_MATCHES_NEEDED) {
    192 		/*
    193 		 * Don't log a warning here since the calling routine will
    194 		 * retry and log it's own warning if the retry fails.
    195 		 */
    196 		DBG2(n2rng, DHEALTH, "n2rng: logic error on rng(%d), only %d "
    197 		    "matches found", rngid, correctcount);
    198 		for (i = 0; i < LOGIC_TEST_WORDS; i++) {
    199 			DBG3(n2rng, DHEALTH, "buffer[%d] %016llx, cycles = %d",
    200 			    i, buffer[i], cycles[i]);
    201 		}
    202 		return (EIO);
    203 	} else {
    204 		DBG3(n2rng, DHEALTH, "n2rng: rng(%d) logic test passed, "
    205 		    "%d matches in %d cycles", rngid, correctcount, i);
    206 		for (i = 0; i < LOGIC_TEST_WORDS; i++) {
    207 			DBG3(n2rng, DCHATTY, "buffer[%d] %016llx, cycles = %d",
    208 			    i, buffer[i], cycles[i]);
    209 		}
    210 	}
    211 
    212 	return (0);
    213 }
    214 
    215 
    216 /*
    217  * gets the metric for the specified state.
    218  */
    219 int
    220 n2rng_collect_metrics(n2rng_t *n2rng, int rngid, n2rng_setup_t *setupp,
    221     n2rng_setup_t *exit_setupp,
    222     uint64_t exit_state, n2rng_osc_perf_t *metricp)
    223 {
    224 	int		rv;
    225 	int		bufsize;
    226 	uint64_t	*buffer = NULL;
    227 
    228 
    229 	bufsize = DATA_WORDS * sizeof (uint64_t);
    230 	buffer = (uint64_t *)contig_mem_alloc_align(bufsize,
    231 	    CONTIG_ALIGNMENT);
    232 	if (buffer == NULL) {
    233 		return (ENOMEM);
    234 	}
    235 
    236 	rv = n2rng_collect_diag_bits(n2rng, rngid, setupp, buffer, bufsize,
    237 	    exit_setupp, exit_state);
    238 	if (rv) {
    239 		cmn_err(CE_WARN,
    240 		    "n2rng: n2rng_collect_bits returns 0x%x", rv);
    241 	} else {
    242 		n2rng_renyi_entropy(buffer, LOG2_DATA_WORDS, metricp);
    243 	}
    244 
    245 	contig_mem_free(buffer, bufsize);
    246 
    247 	return (rv);
    248 }
    249 
    250 
    251 /*
    252  * Fills in table with the performance of each oscillator at each
    253  * bias setting.  A particular datum goes in table[osc][bias].
    254  */
    255 int
    256 collect_rng_perf(n2rng_t *n2rng, int rngid, n2rng_osc_perf_table_t ptable)
    257 {
    258 	int		bias;
    259 	int		osc;
    260 	n2rng_setup_t	rngstate;
    261 	int		rv;
    262 	rng_entry_t	*rng = &n2rng->n_ctl_data->n_rngs[rngid];
    263 
    264 	rngstate.ctlwds[0].word = 0;
    265 	rngstate.ctlwds[0].fields.rnc_anlg_sel = N2RNG_NOANALOGOUT;
    266 	rngstate.ctlwds[1] = rngstate.ctlwds[0];
    267 	rngstate.ctlwds[2] = rngstate.ctlwds[0];
    268 	rngstate.ctlwds[3] = rngstate.ctlwds[0];
    269 
    270 	for (osc = 0; osc < N2RNG_NOSC; osc++) {
    271 		rngstate.ctlwds[3].fields.rnc_selbits = 1 << osc;
    272 		for (bias = 0; bias < N2RNG_NBIASES; bias++) {
    273 			rngstate.ctlwds[3].fields.rnc_vcoctl = bias;
    274 			rv = n2rng_collect_metrics(n2rng, rngid, &rngstate,
    275 			    &rng->n_preferred_config, rng->n_rng_state,
    276 			    &(ptable[osc][bias]));
    277 			if (rv) {
    278 				return (rv);
    279 			}
    280 		}
    281 	}
    282 
    283 	return (rv);
    284 }
    285 
    286 /*
    287  * The following 2 functions test the performance of each noise cell
    288  * and select the bias settings.  They implement the following
    289  * policies:
    290  *
    291  * 1. No two cells may be set to the same bias. (Cells with the same bias,
    292  *    which controls frequency, may beat together, with long
    293  *    runs of no entropy as a pair when they are nearly synchronized.)
    294  * 2. The entropy of each cell is determined (for now) by the Renyi H2
    295  *    entropy of a collection of samples of raw bits.
    296  * 3. The selected configuration is the one that has the largest total
    297  *    entropy, computed as stated above.
    298  * 4. The delay is hard coded.
    299  */
    300 
    301 
    302 /*
    303  * Finds the preferred configuration from perf data.  Sets the
    304  * preferred configuration in the n2rng structure.
    305  */
    306 int
    307 n2rng_noise_gen_preferred(n2rng_t *n2rng, int rngid)
    308 {
    309 	int			rv;
    310 	int			rventropy = 0; /* EIO if entropy is too low */
    311 	int			b0, b1, b2;
    312 	int			osc;
    313 	int			bset;
    314 	n2rng_osc_perf_t	*candidates[N2RNG_NOSC];
    315 	uint64_t		bestcellentropy[N2RNG_NOSC] = {0};
    316 	uint64_t		bestentropy = 0;
    317 	n2rng_ctl_t		rng_ctl = {0};
    318 	int			i;
    319 	rng_entry_t		*rng = &n2rng->n_ctl_data->n_rngs[rngid];
    320 
    321 	rv = collect_rng_perf(n2rng, rngid, rng->n_perftable);
    322 	if (rv) {
    323 		return (rv);
    324 	}
    325 
    326 	/*
    327 	 * bset is the bias setting of all 3 oscillators packed into a
    328 	 * word, 2 bits for each: b2:b1:b0.  First we set up an
    329 	 * arbitrary assignment, because in an earlier version of
    330 	 * this code, there were cases where the assignment would
    331 	 * never happen.  Also, that way we don't need to prove
    332 	 * assignment to prove we never have uninitalized variables,
    333 	 * and hence it might avoid lint warnings.
    334 	 *
    335 	 * This block of code picks the "best" setting of the biases,
    336 	 * where "best" is defined by the rules in the big comment
    337 	 * block above.
    338 	 *
    339 	 * There are only 24 possible combinations such that no two
    340 	 * oscillators get the same bias.  We just do a brute force
    341 	 * exhaustive search of the entire space.
    342 	 */
    343 	bset = ENCODEBIAS(2, 2) | ENCODEBIAS(1, 1) | ENCODEBIAS(0, 0);
    344 	for (b0 = 0; b0 < N2RNG_NBIASES; b0++) {
    345 		candidates[0] = &rng->n_perftable[0][b0];
    346 		for (b1 = 0; b1 < N2RNG_NBIASES; b1++) {
    347 			if (b0 == b1) continue;
    348 			candidates[1] = &rng->n_perftable[1][b1];
    349 			for (b2 = 0; b2 < N2RNG_NBIASES; b2++) {
    350 				uint64_t totalentropy = 0;
    351 
    352 				if (b0 == b2 || b1 == b2) continue;
    353 				candidates[2] = &rng->n_perftable[2][b2];
    354 				for (i = 0; i < N2RNG_NOSC; i++) {
    355 					totalentropy += candidates[i]->H2;
    356 				}
    357 				if (totalentropy > bestentropy) {
    358 					bestentropy = totalentropy;
    359 					bset = ENCODEBIAS(0, b0) |
    360 					    ENCODEBIAS(1, b1) |
    361 					    ENCODEBIAS(2, b2);
    362 					for (i = 0; i < N2RNG_NOSC; i++) {
    363 						bestcellentropy[i] =
    364 						    candidates[i]->H2;
    365 					}
    366 
    367 				}
    368 
    369 			}
    370 		}
    371 	}
    372 
    373 	if (bestentropy < ENTROPY_PASS_VALUE) {
    374 		cmn_err(CE_WARN,
    375 		    "n2rng: RNG hardware producing insufficient "
    376 		    "entropy (producing %ld, need %lld)",
    377 		    bestentropy, ENTROPY_PASS_VALUE);
    378 		rventropy = EIO;
    379 	}
    380 
    381 	/*
    382 	 * Set up fields of control words that will be the same for all
    383 	 * osciallators and for final value that selects all
    384 	 * oscillators.
    385 	 */
    386 	rng_ctl.fields.rnc_cnt = n2rng->n_ctl_data->n_accumulate_cycles;
    387 	rng_ctl.fields.rnc_mode = 1;  /* set normal mode */
    388 	rng_ctl.fields.rnc_anlg_sel = N2RNG_NOANALOGOUT;
    389 
    390 
    391 	/*
    392 	 * Now set the oscillator biases.
    393 	 */
    394 	for (osc = 0; osc < N2RNG_NOSC; osc++) {
    395 		rng_ctl.fields.rnc_selbits = 1 << osc;
    396 		rng_ctl.fields.rnc_vcoctl = EXTRACTBIAS(bset, osc);
    397 		rng->n_preferred_config.ctlwds[osc] = rng_ctl;
    398 	}
    399 
    400 	rng_ctl.fields.rnc_cnt = n2rng->n_ctl_data->n_accumulate_cycles;
    401 	rng_ctl.fields.rnc_vcoctl = 0;
    402 	rng_ctl.fields.rnc_selbits = 0x7;
    403 	rng->n_preferred_config.ctlwds[3] = rng_ctl;
    404 
    405 	if (rventropy == 0) {
    406 
    407 		/* Save bias and entropy results for kstats */
    408 		for (i = 0; i < N2RNG_NOSC; i++) {
    409 			rng->n_bias_info[i].bias =
    410 			    (uint64_t)EXTRACTBIAS(bset, i);
    411 			rng->n_bias_info[i].entropy =
    412 			    (uint64_t)(bestcellentropy[i] / ENTDIVISOR);
    413 			DBG4(n2rng, DCHATTY,
    414 			    "n2rng_noise_gen_preferred: rng %d cell %d bias "
    415 			    "%ld: %ld", rngid, i, rng->n_bias_info[i].bias,
    416 			    rng->n_bias_info[i].entropy);
    417 		}
    418 	} else {
    419 
    420 		/* Clear bias and entropy results for kstats */
    421 		for (i = 0; i < N2RNG_NOSC; i++) {
    422 			rng->n_bias_info[i].bias = 0;
    423 			rng->n_bias_info[i].entropy = 0;
    424 		}
    425 	}
    426 
    427 	return (rv ? rv : rventropy);
    428 }
    429 
    430 /*
    431  * Do a logic test, then find and set the best bias confuration
    432  * (failing if insufficient entropy is generated, then set state to
    433  * configured.  This function should only be called when running in
    434  * the control domain.
    435  */
    436 int
    437 n2rng_do_health_check(n2rng_t *n2rng, int rngid)
    438 {
    439 	int		rv = EIO;
    440 	rng_entry_t	*rng = &n2rng->n_ctl_data->n_rngs[rngid];
    441 	int		attempts;
    442 
    443 	for (attempts = 0;
    444 	    (attempts < RNG_MAX_LOGIC_TEST_ATTEMPTS) && rv; attempts++) {
    445 		rv = n2rng_logic_test(n2rng, rngid);
    446 	}
    447 
    448 	if (rv) {
    449 		cmn_err(CE_WARN, "n2rng: n2rng_logic_test failed %d attempts",
    450 		    RNG_MAX_LOGIC_TEST_ATTEMPTS);
    451 		goto errorexit;
    452 	} else if (attempts > 1) {
    453 		DBG1(n2rng, DHEALTH,
    454 		    "n2rng: n2rng_logic_test failed %d attempts",
    455 		    attempts - 1);
    456 		goto errorexit;
    457 	}
    458 
    459 	rv = n2rng_noise_gen_preferred(n2rng, rngid);
    460 	if (rv) {
    461 		DBG0(n2rng, DHEALTH,
    462 		    "n2rng: n2rng_noise_gen_preferred failed");
    463 		goto errorexit;
    464 	}
    465 
    466 	/* Push the selected config into HW */
    467 	rv = n2rng_collect_diag_bits(n2rng, rngid, NULL, NULL, 0,
    468 	    &rng->n_preferred_config, CTL_STATE_CONFIGURED);
    469 	if (rv) {
    470 		DBG0(n2rng, DHEALTH,
    471 		    "n2rng: n2rng_collect_diag_bits failed");
    472 		goto errorexit;
    473 	}
    474 
    475 	return (rv);
    476 
    477 errorexit:
    478 	/* Push the selected config into HW with an error state */
    479 	(void) n2rng_collect_diag_bits(n2rng, rngid, NULL, NULL, 0,
    480 	    &rng->n_preferred_config, CTL_STATE_ERROR);
    481 
    482 	return (rv);
    483 }
    484