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