832 need Intel 82579 Gigabit Ethernet PHY support in e1000g
[illumos-gate.git] / usr / src / uts / common / io / kstat.c
blob00d13f3ef3bd639c1f12a59fd1f40cf0f2cef55d
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
28 * kernel statistics driver
31 #include <sys/types.h>
32 #include <sys/time.h>
33 #include <sys/param.h>
34 #include <sys/sysmacros.h>
35 #include <sys/file.h>
36 #include <sys/cmn_err.h>
37 #include <sys/t_lock.h>
38 #include <sys/proc.h>
39 #include <sys/fcntl.h>
40 #include <sys/uio.h>
41 #include <sys/kmem.h>
42 #include <sys/cred.h>
43 #include <sys/mman.h>
44 #include <sys/errno.h>
45 #include <sys/ioccom.h>
46 #include <sys/cpuvar.h>
47 #include <sys/stat.h>
48 #include <sys/conf.h>
49 #include <sys/ddi.h>
50 #include <sys/sunddi.h>
51 #include <sys/modctl.h>
52 #include <sys/kobj.h>
53 #include <sys/kstat.h>
54 #include <sys/atomic.h>
55 #include <sys/policy.h>
56 #include <sys/zone.h>
58 static dev_info_t *kstat_devi;
60 static int
61 read_kstat_data(int *rvalp, void *user_ksp, int flag)
63 kstat_t user_kstat, *ksp;
64 #ifdef _MULTI_DATAMODEL
65 kstat32_t user_kstat32;
66 #endif
67 void *kbuf = NULL;
68 size_t kbufsize, ubufsize, copysize;
69 int error = 0;
70 uint_t model;
72 switch (model = ddi_model_convert_from(flag & FMODELS)) {
73 #ifdef _MULTI_DATAMODEL
74 case DDI_MODEL_ILP32:
75 if (copyin(user_ksp, &user_kstat32, sizeof (kstat32_t)) != 0)
76 return (EFAULT);
77 user_kstat.ks_kid = user_kstat32.ks_kid;
78 user_kstat.ks_data = (void *)(uintptr_t)user_kstat32.ks_data;
79 user_kstat.ks_data_size = (size_t)user_kstat32.ks_data_size;
80 break;
81 #endif
82 default:
83 case DDI_MODEL_NONE:
84 if (copyin(user_ksp, &user_kstat, sizeof (kstat_t)) != 0)
85 return (EFAULT);
88 ksp = kstat_hold_bykid(user_kstat.ks_kid, getzoneid());
89 if (ksp == NULL) {
91 * There is no kstat with the specified KID
93 return (ENXIO);
95 if (ksp->ks_flags & KSTAT_FLAG_INVALID) {
97 * The kstat exists, but is momentarily in some
98 * indeterminate state (e.g. the data section is not
99 * yet initialized). Try again in a few milliseconds.
101 kstat_rele(ksp);
102 return (EAGAIN);
106 * If it's a fixed-size kstat, allocate the buffer now, so we
107 * don't have to do it under the kstat's data lock. (If it's a
108 * var-size kstat, we don't know the size until after the update
109 * routine is called, so we can't do this optimization.)
110 * The allocator relies on this behavior to prevent recursive
111 * mutex_enter in its (fixed-size) kstat update routine.
112 * It's a zalloc to prevent unintentional exposure of random
113 * juicy morsels of (old) kernel data.
115 if (!(ksp->ks_flags & KSTAT_FLAG_VAR_SIZE)) {
116 kbufsize = ksp->ks_data_size;
117 kbuf = kmem_zalloc(kbufsize + 1, KM_NOSLEEP);
118 if (kbuf == NULL) {
119 kstat_rele(ksp);
120 return (EAGAIN);
123 KSTAT_ENTER(ksp);
124 if ((error = KSTAT_UPDATE(ksp, KSTAT_READ)) != 0) {
125 KSTAT_EXIT(ksp);
126 kstat_rele(ksp);
127 if (kbuf != NULL)
128 kmem_free(kbuf, kbufsize + 1);
129 return (error);
132 kbufsize = ksp->ks_data_size;
133 ubufsize = user_kstat.ks_data_size;
135 if (ubufsize < kbufsize) {
136 error = ENOMEM;
137 } else {
138 if (kbuf == NULL)
139 kbuf = kmem_zalloc(kbufsize + 1, KM_NOSLEEP);
140 if (kbuf == NULL) {
141 error = EAGAIN;
142 } else {
143 error = KSTAT_SNAPSHOT(ksp, kbuf, KSTAT_READ);
148 * The following info must be returned to user level,
149 * even if the the update or snapshot failed. This allows
150 * kstat readers to get a handle on variable-size kstats,
151 * detect dormant kstats, etc.
153 user_kstat.ks_ndata = ksp->ks_ndata;
154 user_kstat.ks_data_size = kbufsize;
155 user_kstat.ks_flags = ksp->ks_flags;
156 user_kstat.ks_snaptime = ksp->ks_snaptime;
158 *rvalp = kstat_chain_id;
159 KSTAT_EXIT(ksp);
160 kstat_rele(ksp);
163 * Copy the buffer containing the kstat back to userland.
165 copysize = kbufsize;
166 if (kbuf != NULL) {
167 #ifdef _MULTI_DATAMODEL
168 kstat32_t *k32;
169 kstat_t *k;
170 #endif
171 int i;
173 switch (model) {
174 #ifdef _MULTI_DATAMODEL
175 case DDI_MODEL_ILP32:
177 if (ksp->ks_type == KSTAT_TYPE_NAMED) {
178 kstat_named_t *kn = kbuf;
180 for (i = 0; i < user_kstat.ks_ndata; kn++, i++)
181 switch (kn->data_type) {
183 * Named statistics have fields of type
184 * 'long'. For a 32-bit application
185 * looking at a 64-bit kernel,
186 * forcibly truncate these 64-bit
187 * quantities to 32-bit values.
189 case KSTAT_DATA_LONG:
190 kn->value.i32 =
191 (int32_t)kn->value.l;
192 kn->data_type =
193 KSTAT_DATA_INT32;
194 break;
195 case KSTAT_DATA_ULONG:
196 kn->value.ui32 =
197 (uint32_t)kn->value.ul;
198 kn->data_type =
199 KSTAT_DATA_UINT32;
200 break;
202 * Long strings must be massaged before
203 * being copied out to userland. Do
204 * that here.
206 case KSTAT_DATA_STRING:
207 if (KSTAT_NAMED_STR_PTR(kn)
208 == NULL)
209 break;
211 * The offsets within the
212 * buffers are the same, so add
213 * the offset to the beginning
214 * of the new buffer to fix the
215 * pointer.
217 KSTAT_NAMED_STR_PTR(kn) =
218 (char *)user_kstat.ks_data +
219 (KSTAT_NAMED_STR_PTR(kn) -
220 (char *)kbuf);
222 * Make sure the string pointer
223 * lies within the allocated
224 * buffer.
226 ASSERT(KSTAT_NAMED_STR_PTR(kn) +
227 KSTAT_NAMED_STR_BUFLEN(kn)
229 ((char *)
230 user_kstat.ks_data +
231 ubufsize));
232 ASSERT(KSTAT_NAMED_STR_PTR(kn)
234 (char *)
235 ((kstat_named_t *)
236 user_kstat.ks_data +
237 user_kstat.ks_ndata));
239 * Cast 64-bit ptr to 32-bit.
241 kn->value.str.addr.ptr32 =
242 (caddr32_t)(uintptr_t)
243 KSTAT_NAMED_STR_PTR(kn);
244 break;
245 default:
246 break;
250 if (user_kstat.ks_kid != 0)
251 break;
254 * This is the special case of the kstat header
255 * list for the entire system. Reshape the
256 * array in place, then copy it out.
258 k32 = kbuf;
259 k = kbuf;
260 for (i = 0; i < user_kstat.ks_ndata; k32++, k++, i++) {
261 k32->ks_crtime = k->ks_crtime;
262 k32->ks_next = 0;
263 k32->ks_kid = k->ks_kid;
264 (void) strcpy(k32->ks_module, k->ks_module);
265 k32->ks_resv = k->ks_resv;
266 k32->ks_instance = k->ks_instance;
267 (void) strcpy(k32->ks_name, k->ks_name);
268 k32->ks_type = k->ks_type;
269 (void) strcpy(k32->ks_class, k->ks_class);
270 k32->ks_flags = k->ks_flags;
271 k32->ks_data = 0;
272 k32->ks_ndata = k->ks_ndata;
273 if (k->ks_data_size > UINT32_MAX) {
274 error = EOVERFLOW;
275 break;
277 k32->ks_data_size = (size32_t)k->ks_data_size;
278 k32->ks_snaptime = k->ks_snaptime;
282 * XXX In this case we copy less data than is
283 * claimed in the header.
285 copysize = user_kstat.ks_ndata * sizeof (kstat32_t);
286 break;
287 #endif /* _MULTI_DATAMODEL */
288 default:
289 case DDI_MODEL_NONE:
290 if (ksp->ks_type == KSTAT_TYPE_NAMED) {
291 kstat_named_t *kn = kbuf;
293 for (i = 0; i < user_kstat.ks_ndata; kn++, i++)
294 switch (kn->data_type) {
295 #ifdef _LP64
296 case KSTAT_DATA_LONG:
297 kn->data_type =
298 KSTAT_DATA_INT64;
299 break;
300 case KSTAT_DATA_ULONG:
301 kn->data_type =
302 KSTAT_DATA_UINT64;
303 break;
304 #endif /* _LP64 */
305 case KSTAT_DATA_STRING:
306 if (KSTAT_NAMED_STR_PTR(kn)
307 == NULL)
308 break;
309 KSTAT_NAMED_STR_PTR(kn) =
310 (char *)user_kstat.ks_data +
311 (KSTAT_NAMED_STR_PTR(kn) -
312 (char *)kbuf);
313 ASSERT(KSTAT_NAMED_STR_PTR(kn) +
314 KSTAT_NAMED_STR_BUFLEN(kn)
316 ((char *)
317 user_kstat.ks_data +
318 ubufsize));
319 ASSERT(KSTAT_NAMED_STR_PTR(kn)
321 (char *)
322 ((kstat_named_t *)
323 user_kstat.ks_data +
324 user_kstat.ks_ndata));
325 break;
326 default:
327 break;
330 break;
333 if (error == 0 &&
334 copyout(kbuf, user_kstat.ks_data, copysize))
335 error = EFAULT;
336 kmem_free(kbuf, kbufsize + 1);
340 * We have modified the ks_ndata, ks_data_size, ks_flags, and
341 * ks_snaptime fields of the user kstat; now copy it back to userland.
343 switch (model) {
344 #ifdef _MULTI_DATAMODEL
345 case DDI_MODEL_ILP32:
346 if (kbufsize > UINT32_MAX) {
347 error = EOVERFLOW;
348 break;
350 user_kstat32.ks_ndata = user_kstat.ks_ndata;
351 user_kstat32.ks_data_size = (size32_t)kbufsize;
352 user_kstat32.ks_flags = user_kstat.ks_flags;
353 user_kstat32.ks_snaptime = user_kstat.ks_snaptime;
354 if (copyout(&user_kstat32, user_ksp, sizeof (kstat32_t)) &&
355 error == 0)
356 error = EFAULT;
357 break;
358 #endif
359 default:
360 case DDI_MODEL_NONE:
361 if (copyout(&user_kstat, user_ksp, sizeof (kstat_t)) &&
362 error == 0)
363 error = EFAULT;
364 break;
367 return (error);
370 static int
371 write_kstat_data(int *rvalp, void *user_ksp, int flag, cred_t *cred)
373 kstat_t user_kstat, *ksp;
374 void *buf = NULL;
375 size_t bufsize;
376 int error = 0;
378 if (secpolicy_sys_config(cred, B_FALSE) != 0)
379 return (EPERM);
381 switch (ddi_model_convert_from(flag & FMODELS)) {
382 #ifdef _MULTI_DATAMODEL
383 kstat32_t user_kstat32;
385 case DDI_MODEL_ILP32:
386 if (copyin(user_ksp, &user_kstat32, sizeof (kstat32_t)))
387 return (EFAULT);
389 * These are the only fields we actually look at.
391 user_kstat.ks_kid = user_kstat32.ks_kid;
392 user_kstat.ks_data = (void *)(uintptr_t)user_kstat32.ks_data;
393 user_kstat.ks_data_size = (size_t)user_kstat32.ks_data_size;
394 user_kstat.ks_ndata = user_kstat32.ks_ndata;
395 break;
396 #endif
397 default:
398 case DDI_MODEL_NONE:
399 if (copyin(user_ksp, &user_kstat, sizeof (kstat_t)))
400 return (EFAULT);
403 bufsize = user_kstat.ks_data_size;
404 buf = kmem_alloc(bufsize + 1, KM_NOSLEEP);
405 if (buf == NULL)
406 return (EAGAIN);
408 if (copyin(user_kstat.ks_data, buf, bufsize)) {
409 kmem_free(buf, bufsize + 1);
410 return (EFAULT);
413 ksp = kstat_hold_bykid(user_kstat.ks_kid, getzoneid());
414 if (ksp == NULL) {
415 kmem_free(buf, bufsize + 1);
416 return (ENXIO);
418 if (ksp->ks_flags & KSTAT_FLAG_INVALID) {
419 kstat_rele(ksp);
420 kmem_free(buf, bufsize + 1);
421 return (EAGAIN);
423 if (!(ksp->ks_flags & KSTAT_FLAG_WRITABLE)) {
424 kstat_rele(ksp);
425 kmem_free(buf, bufsize + 1);
426 return (EACCES);
430 * With KSTAT_FLAG_VARIABLE, one must call the kstat's update callback
431 * routine to ensure ks_data_size is up to date.
432 * In this case it makes sense to do it anyhow, as it will be shortly
433 * followed by a KSTAT_SNAPSHOT().
435 KSTAT_ENTER(ksp);
436 error = KSTAT_UPDATE(ksp, KSTAT_READ);
437 if (error || user_kstat.ks_data_size != ksp->ks_data_size ||
438 user_kstat.ks_ndata != ksp->ks_ndata) {
439 KSTAT_EXIT(ksp);
440 kstat_rele(ksp);
441 kmem_free(buf, bufsize + 1);
442 return (error ? error : EINVAL);
446 * We have to ensure that we don't accidentally change the type of
447 * existing kstat_named statistics when writing over them.
448 * Since read_kstat_data() modifies some of the types on their way
449 * out, we need to be sure to handle these types seperately.
451 if (ksp->ks_type == KSTAT_TYPE_NAMED) {
452 void *kbuf;
453 kstat_named_t *kold;
454 kstat_named_t *knew = buf;
455 int i;
457 #ifdef _MULTI_DATAMODEL
458 int model = ddi_model_convert_from(flag & FMODELS);
459 #endif
462 * Since ksp->ks_data may be NULL, we need to take a snapshot
463 * of the published data to look at the types.
465 kbuf = kmem_alloc(bufsize + 1, KM_NOSLEEP);
466 if (kbuf == NULL) {
467 KSTAT_EXIT(ksp);
468 kstat_rele(ksp);
469 kmem_free(buf, bufsize + 1);
470 return (EAGAIN);
472 error = KSTAT_SNAPSHOT(ksp, kbuf, KSTAT_READ);
473 if (error) {
474 KSTAT_EXIT(ksp);
475 kstat_rele(ksp);
476 kmem_free(kbuf, bufsize + 1);
477 kmem_free(buf, bufsize + 1);
478 return (error);
480 kold = kbuf;
483 * read_kstat_data() changes the types of
484 * KSTAT_DATA_LONG / KSTAT_DATA_ULONG, so we need to
485 * make sure that these (modified) types are considered
486 * valid.
488 for (i = 0; i < ksp->ks_ndata; i++, kold++, knew++) {
489 switch (kold->data_type) {
490 #ifdef _MULTI_DATAMODEL
491 case KSTAT_DATA_LONG:
492 switch (model) {
493 case DDI_MODEL_ILP32:
494 if (knew->data_type ==
495 KSTAT_DATA_INT32) {
496 knew->value.l =
497 (long)knew->value.i32;
498 knew->data_type =
499 KSTAT_DATA_LONG;
501 break;
502 default:
503 case DDI_MODEL_NONE:
504 #ifdef _LP64
505 if (knew->data_type ==
506 KSTAT_DATA_INT64) {
507 knew->value.l =
508 (long)knew->value.i64;
509 knew->data_type =
510 KSTAT_DATA_LONG;
512 #endif /* _LP64 */
513 break;
515 break;
516 case KSTAT_DATA_ULONG:
517 switch (model) {
518 case DDI_MODEL_ILP32:
519 if (knew->data_type ==
520 KSTAT_DATA_UINT32) {
521 knew->value.ul =
522 (ulong_t)knew->value.ui32;
523 knew->data_type =
524 KSTAT_DATA_ULONG;
526 break;
527 default:
528 case DDI_MODEL_NONE:
529 #ifdef _LP64
530 if (knew->data_type ==
531 KSTAT_DATA_UINT64) {
532 knew->value.ul =
533 (ulong_t)knew->value.ui64;
534 knew->data_type =
535 KSTAT_DATA_ULONG;
537 #endif /* _LP64 */
538 break;
540 break;
541 #endif /* _MULTI_DATAMODEL */
542 case KSTAT_DATA_STRING:
543 if (knew->data_type != KSTAT_DATA_STRING) {
544 KSTAT_EXIT(ksp);
545 kstat_rele(ksp);
546 kmem_free(kbuf, bufsize + 1);
547 kmem_free(buf, bufsize + 1);
548 return (EINVAL);
551 #ifdef _MULTI_DATAMODEL
552 if (model == DDI_MODEL_ILP32)
553 KSTAT_NAMED_STR_PTR(knew) =
554 (char *)(uintptr_t)
555 knew->value.str.addr.ptr32;
556 #endif
558 * Nothing special for NULL
560 if (KSTAT_NAMED_STR_PTR(knew) == NULL)
561 break;
564 * Check to see that the pointers all point
565 * to within the buffer and after the array
566 * of kstat_named_t's.
568 if (KSTAT_NAMED_STR_PTR(knew) <
569 (char *)
570 ((kstat_named_t *)user_kstat.ks_data +
571 ksp->ks_ndata)) {
572 KSTAT_EXIT(ksp);
573 kstat_rele(ksp);
574 kmem_free(kbuf, bufsize + 1);
575 kmem_free(buf, bufsize + 1);
576 return (EINVAL);
578 if (KSTAT_NAMED_STR_PTR(knew) +
579 KSTAT_NAMED_STR_BUFLEN(knew) >
580 ((char *)user_kstat.ks_data +
581 ksp->ks_data_size)) {
582 KSTAT_EXIT(ksp);
583 kstat_rele(ksp);
584 kmem_free(kbuf, bufsize + 1);
585 kmem_free(buf, bufsize + 1);
586 return (EINVAL);
590 * Update the pointers within the buffer
592 KSTAT_NAMED_STR_PTR(knew) =
593 (char *)buf +
594 (KSTAT_NAMED_STR_PTR(knew) -
595 (char *)user_kstat.ks_data);
596 break;
597 default:
598 break;
602 kold = kbuf;
603 knew = buf;
606 * Now make sure the types are what we expected them to be.
608 for (i = 0; i < ksp->ks_ndata; i++, kold++, knew++)
609 if (kold->data_type != knew->data_type) {
610 KSTAT_EXIT(ksp);
611 kstat_rele(ksp);
612 kmem_free(kbuf, bufsize + 1);
613 kmem_free(buf, bufsize + 1);
614 return (EINVAL);
617 kmem_free(kbuf, bufsize + 1);
620 error = KSTAT_SNAPSHOT(ksp, buf, KSTAT_WRITE);
621 if (!error)
622 error = KSTAT_UPDATE(ksp, KSTAT_WRITE);
623 *rvalp = kstat_chain_id;
624 KSTAT_EXIT(ksp);
625 kstat_rele(ksp);
626 kmem_free(buf, bufsize + 1);
627 return (error);
630 /*ARGSUSED*/
631 static int
632 kstat_ioctl(dev_t dev, int cmd, intptr_t data, int flag, cred_t *cr, int *rvalp)
634 int rc = 0;
636 switch (cmd) {
638 case KSTAT_IOC_CHAIN_ID:
639 *rvalp = kstat_chain_id;
640 break;
642 case KSTAT_IOC_READ:
643 rc = read_kstat_data(rvalp, (void *)data, flag);
644 break;
646 case KSTAT_IOC_WRITE:
647 rc = write_kstat_data(rvalp, (void *)data, flag, cr);
648 break;
650 default:
651 /* invalid request */
652 rc = EINVAL;
654 return (rc);
657 /* ARGSUSED */
658 static int
659 kstat_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
660 void **result)
662 switch (infocmd) {
663 case DDI_INFO_DEVT2DEVINFO:
664 *result = kstat_devi;
665 return (DDI_SUCCESS);
666 case DDI_INFO_DEVT2INSTANCE:
667 *result = NULL;
668 return (DDI_SUCCESS);
670 return (DDI_FAILURE);
673 static int
674 kstat_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
676 if (cmd != DDI_ATTACH)
677 return (DDI_FAILURE);
679 if (ddi_create_minor_node(devi, "kstat", S_IFCHR,
680 0, DDI_PSEUDO, NULL) == DDI_FAILURE) {
681 ddi_remove_minor_node(devi, NULL);
682 return (DDI_FAILURE);
684 kstat_devi = devi;
685 return (DDI_SUCCESS);
688 static int
689 kstat_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
691 if (cmd != DDI_DETACH)
692 return (DDI_FAILURE);
694 ddi_remove_minor_node(devi, NULL);
695 return (DDI_SUCCESS);
698 static struct cb_ops kstat_cb_ops = {
699 nulldev, /* open */
700 nulldev, /* close */
701 nodev, /* strategy */
702 nodev, /* print */
703 nodev, /* dump */
704 nodev, /* read */
705 nodev, /* write */
706 kstat_ioctl, /* ioctl */
707 nodev, /* devmap */
708 nodev, /* mmap */
709 nodev, /* segmap */
710 nochpoll, /* poll */
711 ddi_prop_op, /* prop_op */
712 0, /* streamtab */
713 D_NEW | D_MP /* Driver compatibility flag */
716 static struct dev_ops kstat_ops = {
717 DEVO_REV, /* devo_rev, */
718 0, /* refcnt */
719 kstat_info, /* get_dev_info */
720 nulldev, /* identify */
721 nulldev, /* probe */
722 kstat_attach, /* attach */
723 kstat_detach, /* detach */
724 nodev, /* reset */
725 &kstat_cb_ops, /* driver operations */
726 (struct bus_ops *)0, /* no bus operations */
727 NULL, /* power */
728 ddi_quiesce_not_needed, /* quiesce */
731 static struct modldrv modldrv = {
732 &mod_driverops, "kernel statistics driver", &kstat_ops,
735 static struct modlinkage modlinkage = {
736 MODREV_1, &modldrv, NULL
740 _init(void)
742 return (mod_install(&modlinkage));
746 _fini(void)
748 return (mod_remove(&modlinkage));
752 _info(struct modinfo *modinfop)
754 return (mod_info(&modlinkage, modinfop));