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