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 50 if (ddi_getprop(DDI_DEV_T_ANY, n2rng->n_dip, 51 DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "nostats", 0) != 0) { 52 /* 53 * sysadmin has explicity disabled stats to prevent 54 * covert channel. 55 */ 56 return; 57 } 58 59 instance = ddi_get_instance(n2rng->n_dip); 60 61 62 /* 63 * Named kstats. 64 */ 65 n2rng->n_ksp = kstat_create(DRIVER, instance, NULL, "misc", 66 KSTAT_TYPE_NAMED, 67 sizeof (n2rng_stat_t) / sizeof (kstat_named_t), 68 KSTAT_FLAG_WRITABLE); 69 if (n2rng->n_ksp == NULL) { 70 n2rng_error(n2rng, "unable to create kstats"); 71 } else { 72 n2rng_stat_t *dkp = (n2rng_stat_t *)n2rng->n_ksp->ks_data; 73 74 kstat_named_init(&dkp->ns_status, "status", KSTAT_DATA_CHAR); 75 76 kstat_named_init(&dkp->ns_algs[DS_RNGJOBS], "rngjobs", 77 KSTAT_DATA_ULONGLONG); 78 kstat_named_init(&dkp->ns_algs[DS_RNGBYTES], "rngbytes", 79 KSTAT_DATA_ULONGLONG); 80 81 n2rng->n_ksp->ks_update = n2rng_ksupdate; 82 n2rng->n_ksp->ks_private = n2rng; 83 84 kstat_install(n2rng->n_ksp); 85 } 86 } 87 88 /* 89 * Deinitialize Kstats. 90 */ 91 void 92 n2rng_ksdeinit(n2rng_t *n2rng) 93 { 94 95 if (n2rng->n_ksp != NULL) { 96 kstat_delete(n2rng->n_ksp); 97 n2rng->n_ksp = NULL; 98 } 99 } 100 101 /* 102 * Update Kstats. 103 */ 104 int 105 n2rng_ksupdate(kstat_t *ksp, int rw) 106 { 107 n2rng_t *n2rng; 108 n2rng_stat_t *dkp; 109 int i; 110 111 n2rng = (n2rng_t *)ksp->ks_private; 112 dkp = (n2rng_stat_t *)ksp->ks_data; 113 114 if (rw == KSTAT_WRITE) { 115 for (i = 0; i < DS_MAX; i++) { 116 n2rng->n_stats[i] = dkp->ns_algs[i].value.ull; 117 } 118 } else { 119 /* handy status value */ 120 if (n2rng->n_flags & N2RNG_FAILED) { 121 /* device has failed */ 122 (void) strcpy(dkp->ns_status.value.c, "fail"); 123 } else { 124 /* everything looks good */ 125 (void) strcpy(dkp->ns_status.value.c, "online"); 126 } 127 128 for (i = 0; i < DS_MAX; i++) { 129 dkp->ns_algs[i].value.ull = n2rng->n_stats[i]; 130 } 131 } 132 133 return (0); 134 } 135