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 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/ddi.h>
     30 #include <sys/sunddi.h>
     31 #include <sys/systm.h>
     32 #include <sys/kstat.h>
     33 #include <sys/crypto/common.h>
     34 #include <sys/crypto/spi.h>
     35 #include <sys/n2rng.h>
     36 
     37 /*
     38  * Kernel statistics.
     39  */
     40 static int n2rng_ksupdate(kstat_t *, int);
     41 
     42 /*
     43  * Initialize Kstats.
     44  */
     45 void
     46 n2rng_ksinit(n2rng_t *n2rng)
     47 {
     48 	int	instance;
     49 	int	i;
     50 	int	j;
     51 	char	buf[64];
     52 
     53 	if (ddi_getprop(DDI_DEV_T_ANY, n2rng->n_dip,
     54 	    DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "nostats", 0) != 0) {
     55 		/*
     56 		 * sysadmin has explicity disabled stats to prevent
     57 		 * covert channel.
     58 		 */
     59 		return;
     60 	}
     61 
     62 	instance = ddi_get_instance(n2rng->n_dip);
     63 
     64 	/*
     65 	 * Named kstats.
     66 	 */
     67 	n2rng->n_ksp = kstat_create(DRIVER, instance, NULL, "misc",
     68 	    KSTAT_TYPE_NAMED,
     69 	    sizeof (n2rng_stat_t) / sizeof (kstat_named_t),
     70 	    KSTAT_FLAG_WRITABLE);
     71 	if (n2rng->n_ksp == NULL) {
     72 		n2rng_error(n2rng, "unable to create kstats");
     73 	} else {
     74 		n2rng_stat_t *dkp = (n2rng_stat_t *)n2rng->n_ksp->ks_data;
     75 
     76 		kstat_named_init(&dkp->ns_status, "status", KSTAT_DATA_CHAR);
     77 
     78 		kstat_named_init(&dkp->ns_algs[DS_RNGJOBS], "rngjobs",
     79 		    KSTAT_DATA_ULONGLONG);
     80 		kstat_named_init(&dkp->ns_algs[DS_RNGBYTES], "rngbytes",
     81 		    KSTAT_DATA_ULONGLONG);
     82 
     83 		if (n2rng_iscontrol(n2rng)) {
     84 
     85 			for (i = 0; i < n2rng->n_ctl_data->n_num_rngs; i++) {
     86 				(void) sprintf(buf, "rng%d-state", i);
     87 				kstat_named_init(&dkp->ns_rngstate[i],
     88 				    buf, KSTAT_DATA_CHAR);
     89 				for (j = 0; j < N2RNG_NOSC; j++) {
     90 					(void) sprintf(buf,
     91 					    "rng%d-cell%d-bias", i, j);
     92 					kstat_named_init
     93 					    (&dkp->ns_rngbias[i][j],
     94 					    buf, KSTAT_DATA_ULONGLONG);
     95 					(void) sprintf(buf,
     96 					    "rng%d-cell%d-entropy", i, j);
     97 					kstat_named_init
     98 					    (&dkp->ns_rngentropy[i][j],
     99 					    buf, KSTAT_DATA_ULONGLONG);
    100 				}
    101 			}
    102 		}
    103 		n2rng->n_ksp->ks_update = n2rng_ksupdate;
    104 		n2rng->n_ksp->ks_private = n2rng;
    105 
    106 		kstat_install(n2rng->n_ksp);
    107 	}
    108 }
    109 
    110 /*
    111  * Deinitialize Kstats.
    112  */
    113 void
    114 n2rng_ksdeinit(n2rng_t *n2rng)
    115 {
    116 
    117 	if (n2rng->n_ksp != NULL) {
    118 		kstat_delete(n2rng->n_ksp);
    119 		n2rng->n_ksp = NULL;
    120 	}
    121 }
    122 
    123 /*
    124  * Update Kstats.
    125  */
    126 int
    127 n2rng_ksupdate(kstat_t *ksp, int rw)
    128 {
    129 	n2rng_t		*n2rng;
    130 	n2rng_stat_t	*dkp;
    131 	int		i;
    132 	int		j;
    133 
    134 	n2rng = (n2rng_t *)ksp->ks_private;
    135 	dkp = (n2rng_stat_t *)ksp->ks_data;
    136 
    137 	if (rw == KSTAT_WRITE) {
    138 		for (i = 0; i < DS_MAX; i++) {
    139 			n2rng->n_stats[i] = dkp->ns_algs[i].value.ull;
    140 		}
    141 	} else {
    142 		/* handy status value */
    143 		if (n2rng_isfailed(n2rng)) {
    144 			/* device has failed */
    145 			(void) strcpy(dkp->ns_status.value.c, "failed");
    146 		} else if (!n2rng_isconfigured(n2rng)) {
    147 			/* device is not configured */
    148 			(void) strcpy(dkp->ns_status.value.c, "offline");
    149 		} else {
    150 			/* everything looks good */
    151 			(void) strcpy(dkp->ns_status.value.c, "online");
    152 		}
    153 
    154 		for (i = 0; i < DS_MAX; i++) {
    155 			dkp->ns_algs[i].value.ull = n2rng->n_stats[i];
    156 		}
    157 
    158 		if (n2rng_iscontrol(n2rng)) {
    159 			rng_entry_t *rng;
    160 
    161 			for (i = 0; i < n2rng->n_ctl_data->n_num_rngs; i++) {
    162 
    163 				rng = &n2rng->n_ctl_data->n_rngs[i];
    164 
    165 				switch (rng->n_rng_state) {
    166 				case CTL_STATE_ERROR:
    167 					(void) strcpy(
    168 					    dkp->ns_rngstate[i].value.c,
    169 					    "error");
    170 					break;
    171 				case CTL_STATE_HEALTHCHECK:
    172 					(void) strcpy(
    173 					    dkp->ns_rngstate[i].value.c,
    174 					    "healthcheck");
    175 					break;
    176 				case CTL_STATE_CONFIGURED:
    177 					(void) strcpy(
    178 					    dkp->ns_rngstate[i].value.c,
    179 					    "online");
    180 					break;
    181 				case CTL_STATE_UNCONFIGURED:
    182 					(void) strcpy(
    183 					    dkp->ns_rngstate[i].value.c,
    184 					    "offline");
    185 					break;
    186 				default:
    187 					(void) strcpy(
    188 					    dkp->ns_rngstate[i].value.c,
    189 					    "unknown");
    190 					break;
    191 				}
    192 				for (j = 0; j < N2RNG_NOSC; j++) {
    193 					dkp->ns_rngbias[i][j].value.ull =
    194 					    rng->n_bias_info[j].bias;
    195 					dkp->ns_rngentropy[i][j].value.ull =
    196 					    rng->n_bias_info[j].entropy;
    197 				}
    198 			}
    199 		}
    200 	}
    201 
    202 	return (0);
    203 }
    204