14625Sgm89044 /*
24625Sgm89044 * CDDL HEADER START
34625Sgm89044 *
44625Sgm89044 * The contents of this file are subject to the terms of the
54625Sgm89044 * Common Development and Distribution License (the "License").
64625Sgm89044 * You may not use this file except in compliance with the License.
74625Sgm89044 *
84625Sgm89044 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94625Sgm89044 * or http://www.opensolaris.org/os/licensing.
104625Sgm89044 * See the License for the specific language governing permissions
114625Sgm89044 * and limitations under the License.
124625Sgm89044 *
134625Sgm89044 * When distributing Covered Code, include this CDDL HEADER in each
144625Sgm89044 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154625Sgm89044 * If applicable, add the following below this CDDL HEADER, with the
164625Sgm89044 * fields enclosed by brackets "[]" replaced with your own identifying
174625Sgm89044 * information: Portions Copyright [yyyy] [name of copyright owner]
184625Sgm89044 *
194625Sgm89044 * CDDL HEADER END
204625Sgm89044 */
214625Sgm89044 /*
224625Sgm89044 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
234625Sgm89044 * Use is subject to license terms.
244625Sgm89044 */
254625Sgm89044
264625Sgm89044 #pragma ident "%Z%%M% %I% %E% SMI"
274625Sgm89044
284625Sgm89044 #include <sys/types.h>
294625Sgm89044 #include <sys/ddi.h>
304625Sgm89044 #include <sys/sunddi.h>
314625Sgm89044 #include <sys/systm.h>
324625Sgm89044 #include <sys/kstat.h>
334625Sgm89044 #include <sys/crypto/common.h>
344625Sgm89044 #include <sys/crypto/spi.h>
354625Sgm89044 #include <sys/n2rng.h>
364625Sgm89044
374625Sgm89044 /*
384625Sgm89044 * Kernel statistics.
394625Sgm89044 */
404625Sgm89044 static int n2rng_ksupdate(kstat_t *, int);
414625Sgm89044
424625Sgm89044 /*
434625Sgm89044 * Initialize Kstats.
444625Sgm89044 */
454625Sgm89044 void
n2rng_ksinit(n2rng_t * n2rng)464625Sgm89044 n2rng_ksinit(n2rng_t *n2rng)
474625Sgm89044 {
484625Sgm89044 int instance;
49*5650Stwelke int i;
50*5650Stwelke int j;
51*5650Stwelke char buf[64];
524625Sgm89044
534625Sgm89044 if (ddi_getprop(DDI_DEV_T_ANY, n2rng->n_dip,
544625Sgm89044 DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "nostats", 0) != 0) {
554625Sgm89044 /*
564625Sgm89044 * sysadmin has explicity disabled stats to prevent
574625Sgm89044 * covert channel.
584625Sgm89044 */
594625Sgm89044 return;
604625Sgm89044 }
614625Sgm89044
624625Sgm89044 instance = ddi_get_instance(n2rng->n_dip);
634625Sgm89044
644625Sgm89044 /*
654625Sgm89044 * Named kstats.
664625Sgm89044 */
674625Sgm89044 n2rng->n_ksp = kstat_create(DRIVER, instance, NULL, "misc",
684625Sgm89044 KSTAT_TYPE_NAMED,
694625Sgm89044 sizeof (n2rng_stat_t) / sizeof (kstat_named_t),
704625Sgm89044 KSTAT_FLAG_WRITABLE);
714625Sgm89044 if (n2rng->n_ksp == NULL) {
724625Sgm89044 n2rng_error(n2rng, "unable to create kstats");
734625Sgm89044 } else {
744625Sgm89044 n2rng_stat_t *dkp = (n2rng_stat_t *)n2rng->n_ksp->ks_data;
754625Sgm89044
764625Sgm89044 kstat_named_init(&dkp->ns_status, "status", KSTAT_DATA_CHAR);
774625Sgm89044
784625Sgm89044 kstat_named_init(&dkp->ns_algs[DS_RNGJOBS], "rngjobs",
794625Sgm89044 KSTAT_DATA_ULONGLONG);
804625Sgm89044 kstat_named_init(&dkp->ns_algs[DS_RNGBYTES], "rngbytes",
814625Sgm89044 KSTAT_DATA_ULONGLONG);
824625Sgm89044
83*5650Stwelke if (n2rng_iscontrol(n2rng)) {
84*5650Stwelke
85*5650Stwelke for (i = 0; i < n2rng->n_ctl_data->n_num_rngs; i++) {
86*5650Stwelke (void) sprintf(buf, "rng%d-state", i);
87*5650Stwelke kstat_named_init(&dkp->ns_rngstate[i],
88*5650Stwelke buf, KSTAT_DATA_CHAR);
89*5650Stwelke for (j = 0; j < N2RNG_NOSC; j++) {
90*5650Stwelke (void) sprintf(buf,
91*5650Stwelke "rng%d-cell%d-bias", i, j);
92*5650Stwelke kstat_named_init
93*5650Stwelke (&dkp->ns_rngbias[i][j],
94*5650Stwelke buf, KSTAT_DATA_ULONGLONG);
95*5650Stwelke (void) sprintf(buf,
96*5650Stwelke "rng%d-cell%d-entropy", i, j);
97*5650Stwelke kstat_named_init
98*5650Stwelke (&dkp->ns_rngentropy[i][j],
99*5650Stwelke buf, KSTAT_DATA_ULONGLONG);
100*5650Stwelke }
101*5650Stwelke }
102*5650Stwelke }
1034625Sgm89044 n2rng->n_ksp->ks_update = n2rng_ksupdate;
1044625Sgm89044 n2rng->n_ksp->ks_private = n2rng;
1054625Sgm89044
1064625Sgm89044 kstat_install(n2rng->n_ksp);
1074625Sgm89044 }
1084625Sgm89044 }
1094625Sgm89044
1104625Sgm89044 /*
1114625Sgm89044 * Deinitialize Kstats.
1124625Sgm89044 */
1134625Sgm89044 void
n2rng_ksdeinit(n2rng_t * n2rng)1144625Sgm89044 n2rng_ksdeinit(n2rng_t *n2rng)
1154625Sgm89044 {
1164625Sgm89044
1174625Sgm89044 if (n2rng->n_ksp != NULL) {
1184625Sgm89044 kstat_delete(n2rng->n_ksp);
1194625Sgm89044 n2rng->n_ksp = NULL;
1204625Sgm89044 }
1214625Sgm89044 }
1224625Sgm89044
1234625Sgm89044 /*
1244625Sgm89044 * Update Kstats.
1254625Sgm89044 */
1264625Sgm89044 int
n2rng_ksupdate(kstat_t * ksp,int rw)1274625Sgm89044 n2rng_ksupdate(kstat_t *ksp, int rw)
1284625Sgm89044 {
1294625Sgm89044 n2rng_t *n2rng;
1304625Sgm89044 n2rng_stat_t *dkp;
1314625Sgm89044 int i;
132*5650Stwelke int j;
1334625Sgm89044
1344625Sgm89044 n2rng = (n2rng_t *)ksp->ks_private;
1354625Sgm89044 dkp = (n2rng_stat_t *)ksp->ks_data;
1364625Sgm89044
1374625Sgm89044 if (rw == KSTAT_WRITE) {
1384625Sgm89044 for (i = 0; i < DS_MAX; i++) {
1394625Sgm89044 n2rng->n_stats[i] = dkp->ns_algs[i].value.ull;
1404625Sgm89044 }
1414625Sgm89044 } else {
1424625Sgm89044 /* handy status value */
143*5650Stwelke if (n2rng_isfailed(n2rng)) {
1444625Sgm89044 /* device has failed */
145*5650Stwelke (void) strcpy(dkp->ns_status.value.c, "failed");
146*5650Stwelke } else if (!n2rng_isconfigured(n2rng)) {
147*5650Stwelke /* device is not configured */
148*5650Stwelke (void) strcpy(dkp->ns_status.value.c, "offline");
1494625Sgm89044 } else {
1504625Sgm89044 /* everything looks good */
1514625Sgm89044 (void) strcpy(dkp->ns_status.value.c, "online");
1524625Sgm89044 }
1534625Sgm89044
1544625Sgm89044 for (i = 0; i < DS_MAX; i++) {
1554625Sgm89044 dkp->ns_algs[i].value.ull = n2rng->n_stats[i];
1564625Sgm89044 }
157*5650Stwelke
158*5650Stwelke if (n2rng_iscontrol(n2rng)) {
159*5650Stwelke rng_entry_t *rng;
160*5650Stwelke
161*5650Stwelke for (i = 0; i < n2rng->n_ctl_data->n_num_rngs; i++) {
162*5650Stwelke
163*5650Stwelke rng = &n2rng->n_ctl_data->n_rngs[i];
164*5650Stwelke
165*5650Stwelke switch (rng->n_rng_state) {
166*5650Stwelke case CTL_STATE_ERROR:
167*5650Stwelke (void) strcpy(
168*5650Stwelke dkp->ns_rngstate[i].value.c,
169*5650Stwelke "error");
170*5650Stwelke break;
171*5650Stwelke case CTL_STATE_HEALTHCHECK:
172*5650Stwelke (void) strcpy(
173*5650Stwelke dkp->ns_rngstate[i].value.c,
174*5650Stwelke "healthcheck");
175*5650Stwelke break;
176*5650Stwelke case CTL_STATE_CONFIGURED:
177*5650Stwelke (void) strcpy(
178*5650Stwelke dkp->ns_rngstate[i].value.c,
179*5650Stwelke "online");
180*5650Stwelke break;
181*5650Stwelke case CTL_STATE_UNCONFIGURED:
182*5650Stwelke (void) strcpy(
183*5650Stwelke dkp->ns_rngstate[i].value.c,
184*5650Stwelke "offline");
185*5650Stwelke break;
186*5650Stwelke default:
187*5650Stwelke (void) strcpy(
188*5650Stwelke dkp->ns_rngstate[i].value.c,
189*5650Stwelke "unknown");
190*5650Stwelke break;
191*5650Stwelke }
192*5650Stwelke for (j = 0; j < N2RNG_NOSC; j++) {
193*5650Stwelke dkp->ns_rngbias[i][j].value.ull =
194*5650Stwelke rng->n_bias_info[j].bias;
195*5650Stwelke dkp->ns_rngentropy[i][j].value.ull =
196*5650Stwelke rng->n_bias_info[j].entropy;
197*5650Stwelke }
198*5650Stwelke }
199*5650Stwelke }
2004625Sgm89044 }
2014625Sgm89044
2024625Sgm89044 return (0);
2034625Sgm89044 }
204