xref: /titanic_50/usr/src/uts/sun4v/io/n2rng/n2rng_entp_setup.c (revision 6e6cd25b8e73b6af1141b2f34fb186474fe7b9db)
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
lfsr64_adv_seq(uint64_t poly,uint64_t in,uint64_t exp,uint64_t * out)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
n2rng_logic_test(n2rng_t * n2rng,int rngid)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
n2rng_collect_metrics(n2rng_t * n2rng,int rngid,n2rng_setup_t * setupp,n2rng_setup_t * exit_setupp,uint64_t exit_state,n2rng_osc_perf_t * metricp)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
collect_rng_perf(n2rng_t * n2rng,int rngid,n2rng_osc_perf_table_t ptable)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
n2rng_noise_gen_preferred(n2rng_t * n2rng,int rngid)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
n2rng_do_health_check(n2rng_t * n2rng,int rngid)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