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