xref: /illumos-gate/usr/src/uts/sun4v/io/n2rng/n2rng.c (revision c2aa8c918a0c67f7fd93724a31efac84968fc12c)
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 /*
29  * Niagara 2 Random Number Generator (RNG) driver
30  */
31 
32 #include <sys/types.h>
33 #include <sys/sysmacros.h>
34 #include <sys/modctl.h>
35 #include <sys/conf.h>
36 #include <sys/devops.h>
37 #include <sys/cmn_err.h>
38 #include <sys/ksynch.h>
39 #include <sys/kmem.h>
40 #include <sys/stat.h>
41 #include <sys/open.h>
42 #include <sys/file.h>
43 #include <sys/ddi.h>
44 #include <sys/sunddi.h>
45 #include <sys/param.h>
46 #include <sys/cpuvar.h>
47 #include <sys/disp.h>
48 #include <sys/hsvc.h>
49 #include <sys/machsystm.h>
50 #include <sys/hypervisor_api.h>
51 #include <sys/n2rng.h>
52 
53 
54 static int	n2rng_attach(dev_info_t *, ddi_attach_cmd_t);
55 static int	n2rng_detach(dev_info_t *, ddi_detach_cmd_t);
56 static int	n2rng_suspend(n2rng_t *);
57 static int	n2rng_resume(n2rng_t *);
58 int	n2rng_herr2kerr(uint64_t);
59 int	n2rng_logic_test(n2rng_t *);
60 int	n2rng_noise_gen_test_set(void);
61 int	n2rng_init(n2rng_t *n2rng);
62 int	n2rng_uninit(n2rng_t *n2rng);
63 
64 static uint64_t sticks_per_usec(void);
65 u_longlong_t gettick(void);
66 
67 /*
68  * Device operations.
69  */
70 
71 static struct dev_ops devops = {
72 	DEVO_REV,		/* devo_rev */
73 	0,			/* devo_refcnt */
74 	nodev,			/* devo_getinfo */
75 	nulldev,		/* devo_identify */
76 	nulldev,		/* devo_probe */
77 	n2rng_attach,		/* devo_attach */
78 	n2rng_detach,		/* devo_detach */
79 	nodev,			/* devo_reset */
80 	NULL,			/* devo_cb_ops */
81 	NULL,			/* devo_bus_ops */
82 	ddi_power		/* devo_power */
83 };
84 
85 /*
86  * Module linkage.
87  */
88 static struct modldrv modldrv = {
89 	&mod_driverops,			/* drv_modops */
90 	"N2 RNG Driver v%I%",		/* drv_linkinfo */
91 	&devops,			/* drv_dev_ops */
92 };
93 
94 static struct modlinkage modlinkage = {
95 	MODREV_1,			/* ml_rev */
96 	&modldrv,			/* ml_linkage */
97 	NULL
98 };
99 
100 /*
101  * Driver globals Soft state.
102  */
103 static void	*n2rng_softstate = NULL;
104 
105 /*
106  * Hypervisor RNG information.
107  */
108 static uint64_t	rng_min_ver;	/* negotiated RNG API minor version */
109 static boolean_t rng_hsvc_available = B_FALSE;
110 
111 static hsvc_info_t rng_hsvc = {
112 	HSVC_REV_1, NULL, HSVC_GROUP_RNG, RNG_MAJOR_VER,
113 	RNG_MINOR_VER, "n2rng"
114 };
115 
116 /*
117  * DDI entry points.
118  */
119 int
120 _init(void)
121 {
122 	int	rv;
123 
124 	rv = ddi_soft_state_init(&n2rng_softstate, sizeof (n2rng_t), 1);
125 	if (rv != 0) {
126 		/* this should *never* happen! */
127 		return (rv);
128 	}
129 
130 	if ((rv = mod_install(&modlinkage)) != 0) {
131 		/* cleanup here */
132 		ddi_soft_state_fini(&n2rng_softstate);
133 		return (rv);
134 	}
135 
136 	return (0);
137 }
138 
139 int
140 _fini(void)
141 {
142 	int	rv;
143 
144 	rv = mod_remove(&modlinkage);
145 	if (rv == 0) {
146 		/* cleanup here */
147 		ddi_soft_state_fini(&n2rng_softstate);
148 	}
149 
150 	return (rv);
151 }
152 
153 int
154 _info(struct modinfo *modinfop)
155 {
156 	return (mod_info(&modlinkage, modinfop));
157 }
158 
159 static int
160 n2rng_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
161 {
162 	n2rng_t		*n2rng = NULL;
163 	int		instance;
164 	int		rv;
165 
166 	instance = ddi_get_instance(dip);
167 	DBG1(NULL, DATTACH, "n2rng_attach called, instance %d", instance);
168 	/*
169 	 * Only instance 0 of n2rng driver is allowed.
170 	 */
171 	if (instance != 0) {
172 		n2rng_diperror(dip, "only one instance (0) allowed");
173 		return (DDI_FAILURE);
174 	}
175 
176 	switch (cmd) {
177 	case DDI_RESUME:
178 		n2rng = (n2rng_t *)ddi_get_soft_state(n2rng_softstate,
179 		    instance);
180 		if (n2rng == NULL) {
181 			n2rng_diperror(dip, "no soft state in attach");
182 			return (DDI_FAILURE);
183 		}
184 		return (n2rng_resume(n2rng));
185 
186 	case DDI_ATTACH:
187 		break;
188 	default:
189 		return (DDI_FAILURE);
190 	}
191 
192 	rv = ddi_soft_state_zalloc(n2rng_softstate, instance);
193 	if (rv != DDI_SUCCESS) {
194 		n2rng_diperror(dip, "unable to allocate soft state");
195 		return (DDI_FAILURE);
196 	}
197 	n2rng = (n2rng_t *)ddi_get_soft_state(n2rng_softstate, instance);
198 	ASSERT(n2rng != NULL);
199 	n2rng->n_dip = dip;
200 
201 	mutex_init(&n2rng->n_health_check_mutex, NULL, MUTEX_DRIVER, NULL);
202 
203 	if ((rv = hsvc_register(&rng_hsvc, &rng_min_ver)) != 0) {
204 		cmn_err(CE_WARN, "%s: cannot negotiate hypervisor services "
205 		    "group: 0x%lx major: 0x%lx minor: 0x%lx errno: %d",
206 		    rng_hsvc.hsvc_modname, rng_hsvc.hsvc_group,
207 		    rng_hsvc.hsvc_major, rng_hsvc.hsvc_minor, rv);
208 		ddi_soft_state_free(n2rng_softstate, instance);
209 		mutex_destroy(&n2rng->n_health_check_mutex);
210 		return (DDI_FAILURE);
211 	}
212 	rng_hsvc_available = B_TRUE;
213 	/* No locking, but it is okay */
214 	n2rng->n_sticks_per_usec = sticks_per_usec();
215 	/*
216 	 * The first product will likely be around 4 billion, so we
217 	 * use uint64_t to avoid integer overflow.
218 	 */
219 	n2rng->n_anlg_settle_cycles = (uint64_t)RNG_CTL_SETTLE_NS *
220 	    n2rng->n_sticks_per_usec / 1000;
221 
222 	/*
223 	 * Set some plausible state into the preferred
224 	 * configuration. The intent is that the health check, below,
225 	 * will immediately overwrite it.  If we are not in a control
226 	 * domain, this stuff will have no effect.
227 	 */
228 	n2rng->n_preferred_config.ctlwds[0].word = 0;
229 	n2rng->n_preferred_config.ctlwds[0].fields.rnc_anlg_sel =
230 	    N2RNG_NOANALOGOUT;
231 	n2rng->n_preferred_config.ctlwds[0].fields.rnc_cnt =
232 	    RNG_DEFAULT_ACCUMULATE_CYCLES;
233 	n2rng->n_preferred_config.ctlwds[0].fields.rnc_mode =
234 	    RNG_MODE_NORMAL;
235 	n2rng->n_preferred_config.ctlwds[1].word =
236 	    n2rng->n_preferred_config.ctlwds[0].word;
237 	n2rng->n_preferred_config.ctlwds[2].word =
238 	    n2rng->n_preferred_config.ctlwds[0].word;
239 	n2rng->n_preferred_config.ctlwds[3].word =
240 	    n2rng->n_preferred_config.ctlwds[0].word;
241 	n2rng->n_preferred_config.ctlwds[0].fields.rnc_vcoctl = 1;
242 	n2rng->n_preferred_config.ctlwds[0].fields.rnc_selbits = 1;
243 	n2rng->n_preferred_config.ctlwds[1].fields.rnc_vcoctl = 2;
244 	n2rng->n_preferred_config.ctlwds[1].fields.rnc_selbits = 2;
245 	n2rng->n_preferred_config.ctlwds[2].fields.rnc_vcoctl = 3;
246 	n2rng->n_preferred_config.ctlwds[2].fields.rnc_selbits = 4;
247 	n2rng->n_preferred_config.ctlwds[3].fields.rnc_vcoctl = 0;
248 	n2rng->n_preferred_config.ctlwds[3].fields.rnc_selbits = 7;
249 
250 	rv = n2rng_do_health_check(n2rng);
251 
252 	switch (rv) {
253 	case 0:
254 		/* We are a control domain.  Success. */
255 		break;
256 	case EPERM:
257 		/* We must not be a control domain, declare success. */
258 		rv = 0;
259 		break;
260 	default:
261 		goto errorexit;
262 	}
263 
264 	/* Register with KCF---also sets up FIPS state */
265 	rv = n2rng_init(n2rng);
266 	if (rv != DDI_SUCCESS) {
267 		goto errorexit;
268 	}
269 
270 	n2rng->n_flags &= ~N2RNG_FAILED;
271 
272 	return (DDI_SUCCESS);
273 
274 errorexit:
275 	if (rng_hsvc_available == B_TRUE) {
276 		(void) hsvc_unregister(&rng_hsvc);
277 		rng_hsvc_available = B_FALSE;
278 	}
279 	mutex_destroy(&n2rng->n_health_check_mutex);
280 	ddi_soft_state_free(n2rng_softstate, instance);
281 
282 	return (DDI_FAILURE);
283 }
284 
285 static int
286 n2rng_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
287 {
288 	int		instance;
289 	int		rv;
290 	n2rng_t		*n2rng;
291 
292 	instance = ddi_get_instance(dip);
293 	n2rng = (n2rng_t *)ddi_get_soft_state(n2rng_softstate, instance);
294 	if (n2rng == NULL) {
295 		n2rng_diperror(dip, "no soft state in detach");
296 		return (DDI_FAILURE);
297 	}
298 
299 	switch (cmd) {
300 	case DDI_SUSPEND:
301 		return (n2rng_suspend(n2rng));
302 	case DDI_DETACH:
303 		break;
304 	default:
305 		return (DDI_FAILURE);
306 	}
307 
308 
309 	/* unregister with KCF---also tears down FIPS state */
310 	rv = n2rng_uninit(n2rng) ? DDI_FAILURE : DDI_SUCCESS;
311 
312 	if (rng_hsvc_available == B_TRUE) {
313 		(void) hsvc_unregister(&rng_hsvc);
314 		rng_hsvc_available = B_FALSE;
315 	}
316 
317 	mutex_destroy(&n2rng->n_health_check_mutex);
318 
319 	ddi_soft_state_free(n2rng_softstate, instance);
320 
321 	return (rv);
322 }
323 
324 /*ARGSUSED*/
325 static int
326 n2rng_suspend(n2rng_t *n2rng)
327 {
328 	return (DDI_SUCCESS);
329 }
330 
331 /*ARGSUSED*/
332 static int
333 n2rng_resume(n2rng_t *n2rng)
334 {
335 	int		rv;
336 
337 	/* assume clock is same speed, all data structures intact.  */
338 	rv = n2rng_do_health_check(n2rng);
339 	switch (rv) {
340 	case 0:
341 	case EPERM:
342 		break;
343 	default:
344 		cmn_err(CE_WARN, "n2rng: n2rng_resume: health check failed. "
345 		    "Unregistering from encryption framework");
346 		n2rng->n_flags |= N2RNG_FAILED;
347 		(void) n2rng_uninit(n2rng);
348 		break;
349 	}
350 
351 	return (DDI_SUCCESS);
352 }
353 
354 /*
355  * Map hypervisor error code to solaris. Only
356  * H_ENORADDR, H_EBADALIGN, H_EWOULDBLOCK, and EIO
357  * are meaningful to this device. Any other error
358  * codes are mapped EINVAL.
359  */
360 int
361 n2rng_herr2kerr(uint64_t hv_errcode)
362 {
363 	int	s_errcode;
364 
365 	switch (hv_errcode) {
366 	case H_EWOULDBLOCK:
367 		s_errcode = EWOULDBLOCK;
368 		break;
369 	case H_ENORADDR:
370 	case H_EBADALIGN:
371 	case H_EIO:
372 		s_errcode = EIO;
373 		break;
374 	case H_EOK:
375 		s_errcode = 0;
376 		break;
377 	case H_ENOACCESS:
378 		s_errcode = EPERM;
379 		break;
380 	default:
381 		s_errcode = EINVAL;
382 		break;
383 	}
384 	return (s_errcode);
385 }
386 
387 /*
388  * Waits approximately delay_sticks counts of the stick register.
389  * Times shorter than one sys clock tick (10ms on most systems) are
390  * done by busy waiting.
391  */
392 void
393 cyclesleep(n2rng_t *n2rng, uint64_t delay_sticks)
394 {
395 	uint64_t	end_stick = gettick() + delay_sticks;
396 	int64_t		sticks_to_wait;
397 	clock_t		sys_ticks_to_wait;
398 	clock_t		usecs_to_wait;
399 
400 	/*CONSTCOND*/
401 	while (1) {
402 		sticks_to_wait = end_stick - gettick();
403 		if (sticks_to_wait <= 0) {
404 			return;
405 		}
406 
407 		usecs_to_wait = sticks_to_wait / n2rng->n_sticks_per_usec;
408 		sys_ticks_to_wait = drv_usectohz(usecs_to_wait);
409 
410 		if (sys_ticks_to_wait > 0) {
411 			/* sleep */
412 			delay(sys_ticks_to_wait);
413 		} else if (usecs_to_wait > 0) {
414 			/* busy wait */
415 			drv_usecwait(usecs_to_wait);
416 		}
417 	}
418 }
419 
420 static void
421 log_internal_errors(uint64_t hverr, char *fname)
422 {
423 	switch (hverr) {
424 	case H_EBADALIGN:
425 		cmn_err(CE_WARN,
426 		    "n2rng: internal alignment "
427 		    "problem");
428 		break;
429 	case H_ENORADDR:
430 		cmn_err(CE_WARN, "n2rng: internal "
431 		    "invalid address");
432 		break;
433 	default:
434 		cmn_err(CE_NOTE,
435 		    "n2rng: %s "
436 		    "unexpectedly "
437 		    "returned hverr %ld", fname, hverr);
438 		break;
439 	}
440 }
441 
442 /*
443  * Collects a buffer full of bits, using the specified setup. numbytes
444  * must be a multiple of 8. If a sub-operation fails with EIO (handle
445  * mismatch), returns EIO.  If collect_setupp is NULL, the current
446  * setup is used.  If exit_setupp is NULL, the control configuratin
447  * and state are not set at exit.  WARNING: the buffer must be 8-byte
448  * aligned and in contiguous physical addresses.  Contiguousness is
449  * not checked!
450  */
451 int
452 n2rng_collect_diag_bits(n2rng_t *n2rng, n2rng_setup_t *collect_setupp,
453     void *buffer, int numbytes, n2rng_setup_t *exit_setupp,
454     uint64_t exitstate)
455 {
456 	int		rv;
457 	int		override_rv = 0;
458 	uint64_t	hverr;
459 	int		i;
460 	uint64_t	tdelta;
461 	n2rng_setup_t	setupbuffer[2];
462 	n2rng_setup_t	*setupcontigp;
463 	uint64_t	setupphys;
464 	int		numchunks;
465 	boolean_t	rnglooping;
466 
467 	if (numbytes % sizeof (uint64_t)) {
468 		return (EINVAL);
469 	}
470 
471 	if ((uint64_t)buffer % sizeof (uint64_t) != 0) {
472 		return (EINVAL);
473 	}
474 
475 	numchunks = ((numbytes / sizeof (uint64_t)) + RNG_DIAG_CHUNK_SIZE - 1)
476 	    / RNG_DIAG_CHUNK_SIZE;
477 	/*
478 	 * Use setupbuffer[0] if it is contiguous, otherwise
479 	 * setupbuffer[1].
480 	 */
481 	setupcontigp = &setupbuffer[
482 	    CONTIGUOUS(&setupbuffer[0], n2rng_setup_t) ? 0 : 1];
483 	setupphys = va_to_pa(setupcontigp);
484 
485 	/*
486 	 * If a non-null collect_setupp pointer has been provided,
487 	 * push the specified setup into the hardware.
488 	 */
489 	if (collect_setupp != NULL) {
490 		/* copy the specified state to the aligned buffer */
491 		*setupcontigp = *collect_setupp;
492 		rnglooping = B_TRUE;
493 		while (rnglooping) {
494 			hverr = hv_rng_ctl_write(setupphys,
495 			    CTL_STATE_HEALTHCHECK,
496 			    n2rng->n_anlg_settle_cycles, &tdelta);
497 			rv = n2rng_herr2kerr(hverr);
498 			switch (hverr) {
499 			case 0:
500 				rnglooping = B_FALSE;
501 				break;
502 			case H_EIO: /* control yanked from us */
503 			case H_ENOACCESS: /* We are not control domain */
504 				return (rv);
505 			case H_EWOULDBLOCK:
506 				cyclesleep(n2rng, tdelta);
507 				break;
508 			default:
509 				log_internal_errors(hverr, "hv_rng_ctl_write");
510 				override_rv = rv;
511 				goto restore_state;
512 			}
513 		} /* while (rnglooping) */
514 	} /* if (collect_setupp != NULL) */
515 
516 	/* If the caller asks for some bytes, collect the data */
517 	if (numbytes > 0) {
518 		for (i = 0; i < numchunks; i++) {
519 			size_t thisnumbytes = (i == numchunks - 1) ?
520 			    numbytes - i * (RNG_DIAG_CHUNK_SIZE *
521 			    sizeof (uint64_t)) :
522 			    RNG_DIAG_CHUNK_SIZE * sizeof (uint64_t);
523 			/* try until we successfully read a word of data */
524 			rnglooping = B_TRUE;
525 			while (rnglooping) {
526 				hverr = hv_rng_data_read_diag(
527 				    va_to_pa((uint64_t *)buffer +
528 				    RNG_DIAG_CHUNK_SIZE * i),
529 				    thisnumbytes, &tdelta);
530 				rv = n2rng_herr2kerr(hverr);
531 				switch (hverr) {
532 				case 0:
533 					rnglooping = B_FALSE;
534 					break;
535 				case H_EIO:
536 				case H_ENOACCESS:
537 					return (rv);
538 				case H_EWOULDBLOCK:
539 					cyclesleep(n2rng, tdelta);
540 					break;
541 				default:
542 					log_internal_errors(hverr,
543 					    "hv_rng_data_read_diag");
544 					override_rv = rv;
545 					goto restore_state;
546 				}
547 			} /* while (!rnglooping) */
548 		} /* for */
549 	} /* if */
550 
551 restore_state:
552 
553 	/* restore the preferred configuration and set exit state */
554 	if (exit_setupp != NULL) {
555 
556 		*setupcontigp = *exit_setupp;
557 		rnglooping = B_TRUE;
558 		while (rnglooping) {
559 			hverr = hv_rng_ctl_write(setupphys, exitstate,
560 			    n2rng->n_anlg_settle_cycles, &tdelta);
561 			rv = n2rng_herr2kerr(hverr);
562 			switch (hverr) {
563 			case 0:
564 			case H_EIO: /* control yanked from us */
565 			case H_EINVAL: /* some external error, probably */
566 			case H_ENOACCESS: /* We are not control domain */
567 				rnglooping = B_FALSE;
568 				break;
569 			case H_EWOULDBLOCK:
570 				cyclesleep(n2rng, tdelta);
571 				break;
572 
573 			default:
574 				rnglooping = B_FALSE;
575 				log_internal_errors(hverr, "hv_rng_ctl_write");
576 				break;
577 			}
578 		} /* while */
579 	} /* if */
580 
581 	/*
582 	 * override_rv takes care of the case where we abort becuase
583 	 * of some error, but still want to restore the peferred state
584 	 * and return the first error, even if other error occur.
585 	 */
586 	return (override_rv ? override_rv : rv);
587 }
588 
589 int
590 n2rng_getentropy(n2rng_t *n2rng, void *buffer, size_t size)
591 {
592 	int		i, rv = 0;  /* so it works if size is zero */
593 	uint64_t	hverr;
594 	uint64_t	*buffer_w = (uint64_t *)buffer;
595 	int		num_w = size / sizeof (uint64_t);
596 	uint64_t	randval;
597 	uint64_t	randvalphys = va_to_pa(&randval);
598 	uint64_t	tdelta;
599 	int		failcount = 0;
600 	boolean_t	rnglooping;
601 
602 	for (i = 0; i < num_w; i++) {
603 		rnglooping = B_TRUE;
604 		while (rnglooping) {
605 			hverr = hv_rng_data_read(randvalphys, &tdelta);
606 			rv = n2rng_herr2kerr(hverr);
607 			switch (hverr) {
608 			case H_EOK:
609 				buffer_w[i] = randval;
610 				failcount = 0;
611 				rnglooping = B_FALSE;
612 				break;
613 			case H_EIO:
614 				/*
615 				 * A health check is in progress.
616 				 * Wait RNG_RETRY_HLCHK_USECS and fail
617 				 * after RNG_MAX_DATA_READ_ATTEMPTS
618 				 * failures.
619 				 */
620 				if (++failcount > RNG_MAX_DATA_READ_ATTEMPTS) {
621 					goto exitpoint;
622 				} else {
623 					delay(drv_usectohz(
624 					    RNG_RETRY_HLCHK_USECS));
625 				}
626 				break;
627 			case H_EWOULDBLOCK:
628 				cyclesleep(n2rng, tdelta);
629 				break;
630 			default:
631 				log_internal_errors(hverr, "hv_rng_data_read");
632 				goto exitpoint;
633 			}
634 		} /* while */
635 	} /* for */
636 
637 exitpoint:
638 
639 	return (rv);
640 }
641 
642 static uint64_t
643 sticks_per_usec(void)
644 {
645 	uint64_t starttick = gettick();
646 	hrtime_t starttime = gethrtime();
647 	uint64_t endtick;
648 	hrtime_t endtime;
649 
650 	delay(2);
651 
652 	endtick = gettick();
653 	endtime = gethrtime();
654 
655 	return ((1000 * (endtick - starttick)) / (endtime - starttime));
656 }
657