Home | History | Annotate | Download | only in os
      1      0    stevel /*
      2      0    stevel  * CDDL HEADER START
      3      0    stevel  *
      4      0    stevel  * The contents of this file are subject to the terms of the
      5   2723       cth  * Common Development and Distribution License (the "License").
      6   2723       cth  * You may not use this file except in compliance with the License.
      7      0    stevel  *
      8      0    stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9      0    stevel  * or http://www.opensolaris.org/os/licensing.
     10      0    stevel  * See the License for the specific language governing permissions
     11      0    stevel  * and limitations under the License.
     12      0    stevel  *
     13      0    stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14      0    stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15      0    stevel  * If applicable, add the following below this CDDL HEADER, with the
     16      0    stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17      0    stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18      0    stevel  *
     19      0    stevel  * CDDL HEADER END
     20      0    stevel  */
     21      0    stevel /*
     22   8798  Dhanaraj  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23      0    stevel  * Use is subject to license terms.
     24      0    stevel  */
     25      0    stevel 
     26      0    stevel /*
     27      0    stevel  * Kernel statistics framework
     28      0    stevel  */
     29      0    stevel 
     30      0    stevel #include <sys/types.h>
     31      0    stevel #include <sys/time.h>
     32      0    stevel #include <sys/systm.h>
     33      0    stevel #include <sys/vmsystm.h>
     34      0    stevel #include <sys/t_lock.h>
     35      0    stevel #include <sys/param.h>
     36      0    stevel #include <sys/errno.h>
     37      0    stevel #include <sys/vmem.h>
     38      0    stevel #include <sys/sysmacros.h>
     39      0    stevel #include <sys/cmn_err.h>
     40      0    stevel #include <sys/kstat.h>
     41      0    stevel #include <sys/sysinfo.h>
     42      0    stevel #include <sys/cpuvar.h>
     43      0    stevel #include <sys/fcntl.h>
     44      0    stevel #include <sys/flock.h>
     45      0    stevel #include <sys/vnode.h>
     46      0    stevel #include <sys/vfs.h>
     47      0    stevel #include <sys/dnlc.h>
     48      0    stevel #include <sys/var.h>
     49      0    stevel #include <sys/vmmeter.h>
     50      0    stevel #include <sys/debug.h>
     51      0    stevel #include <sys/kobj.h>
     52      0    stevel #include <sys/avl.h>
     53      0    stevel #include <sys/pool_pset.h>
     54      0    stevel #include <sys/cpupart.h>
     55      0    stevel #include <sys/zone.h>
     56      0    stevel #include <sys/loadavg.h>
     57      0    stevel #include <vm/page.h>
     58      0    stevel #include <vm/anon.h>
     59      0    stevel #include <vm/seg_kmem.h>
     60      0    stevel 
     61      0    stevel /*
     62      0    stevel  * Global lock to protect the AVL trees and kstat_chain_id.
     63      0    stevel  */
     64      0    stevel static kmutex_t kstat_chain_lock;
     65      0    stevel 
     66      0    stevel /*
     67      0    stevel  * Every install/delete kstat bumps kstat_chain_id.  This is used by:
     68      0    stevel  *
     69      0    stevel  * (1)	/dev/kstat, to detect changes in the kstat chain across ioctls;
     70      0    stevel  *
     71      0    stevel  * (2)	kstat_create(), to assign a KID (kstat ID) to each new kstat.
     72      0    stevel  *	/dev/kstat uses the KID as a cookie for kstat lookups.
     73      0    stevel  *
     74      0    stevel  * We reserve the first two IDs because some kstats are created before
     75      0    stevel  * the well-known ones (kstat_headers = 0, kstat_types = 1).
     76      0    stevel  *
     77      0    stevel  * We also bump the kstat_chain_id if a zone is gaining or losing visibility
     78      0    stevel  * into a particular kstat, which is logically equivalent to a kstat being
     79      0    stevel  * installed/deleted.
     80      0    stevel  */
     81      0    stevel 
     82      0    stevel kid_t kstat_chain_id = 2;
     83      0    stevel 
     84      0    stevel /*
     85      0    stevel  * As far as zones are concerned, there are 3 types of kstat:
     86      0    stevel  *
     87      0    stevel  * 1) Those which have a well-known name, and which should return per-zone data
     88      0    stevel  * depending on which zone is doing the kstat_read().  sockfs:0:sock_unix_list
     89      0    stevel  * is an example of this type of kstat.
     90      0    stevel  *
     91      0    stevel  * 2) Those which should only be exported to a particular list of zones.
     92      0    stevel  * For example, in the case of nfs:*:mntinfo, we don't want zone A to be
     93      0    stevel  * able to see NFS mounts associated with zone B, while we want the
     94      0    stevel  * global zone to be able to see all mounts on the system.
     95      0    stevel  *
     96      0    stevel  * 3) Those that can be exported to all zones.  Most system-related
     97      0    stevel  * kstats fall within this category.
     98      0    stevel  *
     99      0    stevel  * An ekstat_t thus contains a list of kstats that the zone is to be
    100      0    stevel  * exported to.  The lookup of a name:instance:module thus translates to a
    101      0    stevel  * lookup of name:instance:module:myzone; if the kstat is not exported
    102      0    stevel  * to all zones, and does not have the caller's zoneid explicitly
    103      0    stevel  * enumerated in the list of zones to be exported to, it is the same as
    104      0    stevel  * if the kstat didn't exist.
    105      0    stevel  *
    106      0    stevel  * Writing to kstats is currently disallowed from within a non-global
    107      0    stevel  * zone, although this restriction could be removed in the future.
    108      0    stevel  */
    109      0    stevel typedef struct kstat_zone {
    110      0    stevel 	zoneid_t zoneid;
    111      0    stevel 	struct kstat_zone *next;
    112      0    stevel } kstat_zone_t;
    113      0    stevel 
    114      0    stevel /*
    115      0    stevel  * Extended kstat structure -- for internal use only.
    116      0    stevel  */
    117      0    stevel typedef struct ekstat {
    118      0    stevel 	kstat_t		e_ks;		/* the kstat itself */
    119      0    stevel 	size_t		e_size;		/* total allocation size */
    120      0    stevel 	kthread_t	*e_owner;	/* thread holding this kstat */
    121      0    stevel 	kcondvar_t	e_cv;		/* wait for owner == NULL */
    122      0    stevel 	avl_node_t	e_avl_bykid;	/* AVL tree to sort by KID */
    123      0    stevel 	avl_node_t	e_avl_byname;	/* AVL tree to sort by name */
    124      0    stevel 	kstat_zone_t	e_zone;		/* zone to export stats to */
    125      0    stevel } ekstat_t;
    126      0    stevel 
    127      0    stevel static uint64_t kstat_initial[8192];
    128      0    stevel static void *kstat_initial_ptr = kstat_initial;
    129      0    stevel static size_t kstat_initial_avail = sizeof (kstat_initial);
    130      0    stevel static vmem_t *kstat_arena;
    131      0    stevel 
    132      0    stevel #define	KSTAT_ALIGN	(sizeof (uint64_t))
    133      0    stevel 
    134      0    stevel static avl_tree_t kstat_avl_bykid;
    135      0    stevel static avl_tree_t kstat_avl_byname;
    136      0    stevel 
    137      0    stevel /*
    138      0    stevel  * Various pointers we need to create kstats at boot time in kstat_init()
    139      0    stevel  */
    140      0    stevel extern	kstat_named_t	*segmapcnt_ptr;
    141      0    stevel extern	uint_t		segmapcnt_ndata;
    142      0    stevel extern	int		segmap_kstat_update(kstat_t *, int);
    143      0    stevel extern	kstat_named_t	*biostats_ptr;
    144      0    stevel extern	uint_t		biostats_ndata;
    145      0    stevel extern	kstat_named_t	*pollstats_ptr;
    146      0    stevel extern	uint_t		pollstats_ndata;
    147      0    stevel 
    148      0    stevel extern	int	vac;
    149      0    stevel extern	uint_t	nproc;
    150      0    stevel extern	time_t	boot_time;
    151      0    stevel extern	sysinfo_t	sysinfo;
    152      0    stevel extern	vminfo_t	vminfo;
    153      0    stevel 
    154      0    stevel struct {
    155      0    stevel 	kstat_named_t ncpus;
    156      0    stevel 	kstat_named_t lbolt;
    157      0    stevel 	kstat_named_t deficit;
    158      0    stevel 	kstat_named_t clk_intr;
    159      0    stevel 	kstat_named_t vac;
    160      0    stevel 	kstat_named_t nproc;
    161      0    stevel 	kstat_named_t avenrun_1min;
    162      0    stevel 	kstat_named_t avenrun_5min;
    163      0    stevel 	kstat_named_t avenrun_15min;
    164      0    stevel 	kstat_named_t boot_time;
    165      0    stevel } system_misc_kstat = {
    166      0    stevel 	{ "ncpus",		KSTAT_DATA_UINT32 },
    167      0    stevel 	{ "lbolt",		KSTAT_DATA_UINT32 },
    168      0    stevel 	{ "deficit",		KSTAT_DATA_UINT32 },
    169      0    stevel 	{ "clk_intr",		KSTAT_DATA_UINT32 },
    170      0    stevel 	{ "vac",		KSTAT_DATA_UINT32 },
    171      0    stevel 	{ "nproc",		KSTAT_DATA_UINT32 },
    172      0    stevel 	{ "avenrun_1min",	KSTAT_DATA_UINT32 },
    173      0    stevel 	{ "avenrun_5min",	KSTAT_DATA_UINT32 },
    174      0    stevel 	{ "avenrun_15min",	KSTAT_DATA_UINT32 },
    175      0    stevel 	{ "boot_time",		KSTAT_DATA_UINT32 },
    176      0    stevel };
    177      0    stevel 
    178      0    stevel struct {
    179      0    stevel 	kstat_named_t physmem;
    180      0    stevel 	kstat_named_t nalloc;
    181      0    stevel 	kstat_named_t nfree;
    182      0    stevel 	kstat_named_t nalloc_calls;
    183      0    stevel 	kstat_named_t nfree_calls;
    184      0    stevel 	kstat_named_t kernelbase;
    185      0    stevel 	kstat_named_t econtig;
    186      0    stevel 	kstat_named_t freemem;
    187      0    stevel 	kstat_named_t availrmem;
    188      0    stevel 	kstat_named_t lotsfree;
    189      0    stevel 	kstat_named_t desfree;
    190      0    stevel 	kstat_named_t minfree;
    191      0    stevel 	kstat_named_t fastscan;
    192      0    stevel 	kstat_named_t slowscan;
    193      0    stevel 	kstat_named_t nscan;
    194      0    stevel 	kstat_named_t desscan;
    195      0    stevel 	kstat_named_t pp_kernel;
    196      0    stevel 	kstat_named_t pagesfree;
    197      0    stevel 	kstat_named_t pageslocked;
    198      0    stevel 	kstat_named_t pagestotal;
    199      0    stevel } system_pages_kstat = {
    200      0    stevel 	{ "physmem",		KSTAT_DATA_ULONG },
    201      0    stevel 	{ "nalloc",		KSTAT_DATA_ULONG },
    202      0    stevel 	{ "nfree",		KSTAT_DATA_ULONG },
    203      0    stevel 	{ "nalloc_calls",	KSTAT_DATA_ULONG },
    204      0    stevel 	{ "nfree_calls",	KSTAT_DATA_ULONG },
    205      0    stevel 	{ "kernelbase",		KSTAT_DATA_ULONG },
    206      0    stevel 	{ "econtig", 		KSTAT_DATA_ULONG },
    207      0    stevel 	{ "freemem", 		KSTAT_DATA_ULONG },
    208      0    stevel 	{ "availrmem", 		KSTAT_DATA_ULONG },
    209      0    stevel 	{ "lotsfree", 		KSTAT_DATA_ULONG },
    210      0    stevel 	{ "desfree", 		KSTAT_DATA_ULONG },
    211      0    stevel 	{ "minfree", 		KSTAT_DATA_ULONG },
    212      0    stevel 	{ "fastscan", 		KSTAT_DATA_ULONG },
    213      0    stevel 	{ "slowscan", 		KSTAT_DATA_ULONG },
    214      0    stevel 	{ "nscan", 		KSTAT_DATA_ULONG },
    215      0    stevel 	{ "desscan", 		KSTAT_DATA_ULONG },
    216      0    stevel 	{ "pp_kernel", 		KSTAT_DATA_ULONG },
    217      0    stevel 	{ "pagesfree", 		KSTAT_DATA_ULONG },
    218      0    stevel 	{ "pageslocked", 	KSTAT_DATA_ULONG },
    219      0    stevel 	{ "pagestotal",		KSTAT_DATA_ULONG },
    220      0    stevel };
    221      0    stevel 
    222      0    stevel static int header_kstat_update(kstat_t *, int);
    223      0    stevel static int header_kstat_snapshot(kstat_t *, void *, int);
    224      0    stevel static int system_misc_kstat_update(kstat_t *, int);
    225      0    stevel static int system_pages_kstat_update(kstat_t *, int);
    226      0    stevel 
    227      0    stevel static struct {
    228      0    stevel 	char	name[KSTAT_STRLEN];
    229      0    stevel 	size_t	size;
    230      0    stevel 	uint_t	min_ndata;
    231      0    stevel 	uint_t	max_ndata;
    232      0    stevel } kstat_data_type[KSTAT_NUM_TYPES] = {
    233      0    stevel 	{ "raw",		1,			0,	INT_MAX	},
    234      0    stevel 	{ "name=value",		sizeof (kstat_named_t),	0,	INT_MAX	},
    235      0    stevel 	{ "interrupt",		sizeof (kstat_intr_t),	1,	1	},
    236      0    stevel 	{ "i/o",		sizeof (kstat_io_t),	1,	1	},
    237      0    stevel 	{ "event_timer",	sizeof (kstat_timer_t),	0,	INT_MAX	},
    238      0    stevel };
    239      0    stevel 
    240      0    stevel int
    241      0    stevel kstat_zone_find(kstat_t *k, zoneid_t zoneid)
    242      0    stevel {
    243      0    stevel 	ekstat_t *e = (ekstat_t *)k;
    244      0    stevel 	kstat_zone_t *kz;
    245      0    stevel 
    246      0    stevel 	ASSERT(MUTEX_HELD(&kstat_chain_lock));
    247      0    stevel 	for (kz = &e->e_zone; kz != NULL; kz = kz->next) {
    248      0    stevel 		if (zoneid == ALL_ZONES || kz->zoneid == ALL_ZONES)
    249      0    stevel 			return (1);
    250      0    stevel 		if (zoneid == kz->zoneid)
    251      0    stevel 			return (1);
    252      0    stevel 	}
    253      0    stevel 	return (0);
    254      0    stevel }
    255      0    stevel 
    256      0    stevel void
    257      0    stevel kstat_zone_remove(kstat_t *k, zoneid_t zoneid)
    258      0    stevel {
    259      0    stevel 	ekstat_t *e = (ekstat_t *)k;
    260      0    stevel 	kstat_zone_t *kz, *t = NULL;
    261      0    stevel 
    262      0    stevel 	mutex_enter(&kstat_chain_lock);
    263      0    stevel 	if (zoneid == e->e_zone.zoneid) {
    264      0    stevel 		kz = e->e_zone.next;
    265      0    stevel 		ASSERT(kz != NULL);
    266      0    stevel 		e->e_zone.zoneid = kz->zoneid;
    267      0    stevel 		e->e_zone.next = kz->next;
    268      0    stevel 		goto out;
    269      0    stevel 	}
    270      0    stevel 	for (kz = &e->e_zone; kz->next != NULL; kz = kz->next) {
    271      0    stevel 		if (kz->next->zoneid == zoneid) {
    272      0    stevel 			t = kz->next;
    273      0    stevel 			kz->next = t->next;
    274      0    stevel 			break;
    275      0    stevel 		}
    276      0    stevel 	}
    277      0    stevel 	ASSERT(t != NULL);	/* we removed something */
    278      0    stevel 	kz = t;
    279      0    stevel out:
    280      0    stevel 	kstat_chain_id++;
    281      0    stevel 	mutex_exit(&kstat_chain_lock);
    282      0    stevel 	kmem_free(kz, sizeof (*kz));
    283      0    stevel }
    284      0    stevel 
    285      0    stevel void
    286      0    stevel kstat_zone_add(kstat_t *k, zoneid_t zoneid)
    287      0    stevel {
    288      0    stevel 	ekstat_t *e = (ekstat_t *)k;
    289      0    stevel 	kstat_zone_t *kz;
    290      0    stevel 
    291   3792     akolb 	kz = kmem_alloc(sizeof (*kz), KM_NOSLEEP);
    292   3792     akolb 	if (kz == NULL)
    293   3792     akolb 		return;
    294      0    stevel 	mutex_enter(&kstat_chain_lock);
    295      0    stevel 	kz->zoneid = zoneid;
    296      0    stevel 	kz->next = e->e_zone.next;
    297      0    stevel 	e->e_zone.next = kz;
    298      0    stevel 	kstat_chain_id++;
    299      0    stevel 	mutex_exit(&kstat_chain_lock);
    300      0    stevel }
    301      0    stevel 
    302      0    stevel /*
    303      0    stevel  * Compare the list of zones for the given kstats, returning 0 if they match
    304      0    stevel  * (ie, one list contains ALL_ZONES or both lists contain the same zoneid).
    305      0    stevel  * In practice, this is called indirectly by kstat_hold_byname(), so one of the
    306      0    stevel  * two lists always has one element, and this is an O(n) operation rather than
    307      0    stevel  * O(n^2).
    308      0    stevel  */
    309      0    stevel static int
    310      0    stevel kstat_zone_compare(ekstat_t *e1, ekstat_t *e2)
    311      0    stevel {
    312      0    stevel 	kstat_zone_t *kz1, *kz2;
    313      0    stevel 
    314      0    stevel 	ASSERT(MUTEX_HELD(&kstat_chain_lock));
    315      0    stevel 	for (kz1 = &e1->e_zone; kz1 != NULL; kz1 = kz1->next) {
    316      0    stevel 		for (kz2 = &e2->e_zone; kz2 != NULL; kz2 = kz2->next) {
    317      0    stevel 			if (kz1->zoneid == ALL_ZONES ||
    318      0    stevel 			    kz2->zoneid == ALL_ZONES)
    319      0    stevel 				return (0);
    320      0    stevel 			if (kz1->zoneid == kz2->zoneid)
    321      0    stevel 				return (0);
    322      0    stevel 		}
    323      0    stevel 	}
    324      0    stevel 	return (e1->e_zone.zoneid < e2->e_zone.zoneid ? -1 : 1);
    325      0    stevel }
    326      0    stevel 
    327      0    stevel /*
    328      0    stevel  * Support for keeping kstats sorted in AVL trees for fast lookups.
    329      0    stevel  */
    330      0    stevel static int
    331      0    stevel kstat_compare_bykid(const void *a1, const void *a2)
    332      0    stevel {
    333      0    stevel 	const kstat_t *k1 = a1;
    334      0    stevel 	const kstat_t *k2 = a2;
    335      0    stevel 
    336      0    stevel 	if (k1->ks_kid < k2->ks_kid)
    337      0    stevel 		return (-1);
    338      0    stevel 	if (k1->ks_kid > k2->ks_kid)
    339      0    stevel 		return (1);
    340      0    stevel 	return (kstat_zone_compare((ekstat_t *)k1, (ekstat_t *)k2));
    341      0    stevel }
    342      0    stevel 
    343      0    stevel static int
    344      0    stevel kstat_compare_byname(const void *a1, const void *a2)
    345      0    stevel {
    346      0    stevel 	const kstat_t *k1 = a1;
    347      0    stevel 	const kstat_t *k2 = a2;
    348      0    stevel 	int s;
    349      0    stevel 
    350      0    stevel 	s = strcmp(k1->ks_module, k2->ks_module);
    351      0    stevel 	if (s > 0)
    352      0    stevel 		return (1);
    353      0    stevel 	if (s < 0)
    354      0    stevel 		return (-1);
    355      0    stevel 
    356      0    stevel 	if (k1->ks_instance < k2->ks_instance)
    357      0    stevel 		return (-1);
    358      0    stevel 	if (k1->ks_instance > k2->ks_instance)
    359      0    stevel 		return (1);
    360      0    stevel 
    361      0    stevel 	s = strcmp(k1->ks_name, k2->ks_name);
    362      0    stevel 	if (s > 0)
    363      0    stevel 		return (1);
    364      0    stevel 	if (s < 0)
    365      0    stevel 		return (-1);
    366      0    stevel 
    367      0    stevel 	return (kstat_zone_compare((ekstat_t *)k1, (ekstat_t *)k2));
    368      0    stevel }
    369      0    stevel 
    370      0    stevel static kstat_t *
    371      0    stevel kstat_hold(avl_tree_t *t, ekstat_t *template)
    372      0    stevel {
    373      0    stevel 	kstat_t *ksp;
    374      0    stevel 	ekstat_t *e;
    375      0    stevel 
    376      0    stevel 	mutex_enter(&kstat_chain_lock);
    377      0    stevel 	for (;;) {
    378      0    stevel 		ksp = avl_find(t, template, NULL);
    379      0    stevel 		if (ksp == NULL)
    380      0    stevel 			break;
    381      0    stevel 		e = (ekstat_t *)ksp;
    382      0    stevel 		if (e->e_owner == NULL) {
    383      0    stevel 			e->e_owner = curthread;
    384      0    stevel 			break;
    385      0    stevel 		}
    386      0    stevel 		cv_wait(&e->e_cv, &kstat_chain_lock);
    387      0    stevel 	}
    388      0    stevel 	mutex_exit(&kstat_chain_lock);
    389      0    stevel 	return (ksp);
    390      0    stevel }
    391      0    stevel 
    392      0    stevel void
    393      0    stevel kstat_rele(kstat_t *ksp)
    394      0    stevel {
    395      0    stevel 	ekstat_t *e = (ekstat_t *)ksp;
    396      0    stevel 
    397      0    stevel 	mutex_enter(&kstat_chain_lock);
    398      0    stevel 	ASSERT(e->e_owner == curthread);
    399      0    stevel 	e->e_owner = NULL;
    400      0    stevel 	cv_broadcast(&e->e_cv);
    401      0    stevel 	mutex_exit(&kstat_chain_lock);
    402      0    stevel }
    403      0    stevel 
    404      0    stevel kstat_t *
    405      0    stevel kstat_hold_bykid(kid_t kid, zoneid_t zoneid)
    406      0    stevel {
    407      0    stevel 	ekstat_t e;
    408      0    stevel 
    409      0    stevel 	e.e_ks.ks_kid = kid;
    410      0    stevel 	e.e_zone.zoneid = zoneid;
    411      0    stevel 	e.e_zone.next = NULL;
    412      0    stevel 
    413      0    stevel 	return (kstat_hold(&kstat_avl_bykid, &e));
    414      0    stevel }
    415      0    stevel 
    416      0    stevel kstat_t *
    417   2951     elowe kstat_hold_byname(const char *ks_module, int ks_instance, const char *ks_name,
    418      0    stevel     zoneid_t ks_zoneid)
    419      0    stevel {
    420      0    stevel 	ekstat_t e;
    421      0    stevel 
    422      0    stevel 	kstat_set_string(e.e_ks.ks_module, ks_module);
    423      0    stevel 	e.e_ks.ks_instance = ks_instance;
    424      0    stevel 	kstat_set_string(e.e_ks.ks_name, ks_name);
    425      0    stevel 	e.e_zone.zoneid = ks_zoneid;
    426      0    stevel 	e.e_zone.next = NULL;
    427      0    stevel 	return (kstat_hold(&kstat_avl_byname, &e));
    428      0    stevel }
    429      0    stevel 
    430      0    stevel static ekstat_t *
    431      0    stevel kstat_alloc(size_t size)
    432      0    stevel {
    433      0    stevel 	ekstat_t *e = NULL;
    434      0    stevel 
    435      0    stevel 	size = P2ROUNDUP(sizeof (ekstat_t) + size, KSTAT_ALIGN);
    436      0    stevel 
    437      0    stevel 	if (kstat_arena == NULL) {
    438      0    stevel 		if (size <= kstat_initial_avail) {
    439      0    stevel 			e = kstat_initial_ptr;
    440      0    stevel 			kstat_initial_ptr = (char *)kstat_initial_ptr + size;
    441      0    stevel 			kstat_initial_avail -= size;
    442      0    stevel 		}
    443      0    stevel 	} else {
    444      0    stevel 		e = vmem_alloc(kstat_arena, size, VM_NOSLEEP);
    445      0    stevel 	}
    446      0    stevel 
    447      0    stevel 	if (e != NULL) {
    448      0    stevel 		bzero(e, size);
    449      0    stevel 		e->e_size = size;
    450      0    stevel 		cv_init(&e->e_cv, NULL, CV_DEFAULT, NULL);
    451      0    stevel 	}
    452      0    stevel 
    453      0    stevel 	return (e);
    454      0    stevel }
    455      0    stevel 
    456      0    stevel static void
    457      0    stevel kstat_free(ekstat_t *e)
    458      0    stevel {
    459      0    stevel 	cv_destroy(&e->e_cv);
    460      0    stevel 	vmem_free(kstat_arena, e, e->e_size);
    461      0    stevel }
    462      0    stevel 
    463      0    stevel /*
    464      0    stevel  * Create various system kstats.
    465      0    stevel  */
    466      0    stevel void
    467      0    stevel kstat_init(void)
    468      0    stevel {
    469      0    stevel 	kstat_t *ksp;
    470      0    stevel 	ekstat_t *e;
    471      0    stevel 	avl_tree_t *t = &kstat_avl_bykid;
    472      0    stevel 
    473      0    stevel 	/*
    474      0    stevel 	 * Set up the kstat vmem arena.
    475      0    stevel 	 */
    476      0    stevel 	kstat_arena = vmem_create("kstat",
    477      0    stevel 	    kstat_initial, sizeof (kstat_initial), KSTAT_ALIGN,
    478      0    stevel 	    segkmem_alloc, segkmem_free, heap_arena, 0, VM_SLEEP);
    479      0    stevel 
    480      0    stevel 	/*
    481      0    stevel 	 * Make initial kstats appear as though they were allocated.
    482      0    stevel 	 */
    483      0    stevel 	for (e = avl_first(t); e != NULL; e = avl_walk(t, e, AVL_AFTER))
    484      0    stevel 		(void) vmem_xalloc(kstat_arena, e->e_size, KSTAT_ALIGN,
    485      0    stevel 		    0, 0, e, (char *)e + e->e_size,
    486      0    stevel 		    VM_NOSLEEP | VM_BESTFIT | VM_PANIC);
    487      0    stevel 
    488      0    stevel 	/*
    489      0    stevel 	 * The mother of all kstats.  The first kstat in the system, which
    490      0    stevel 	 * always has KID 0, has the headers for all kstats (including itself)
    491      0    stevel 	 * as its data.  Thus, the kstat driver does not need any special
    492      0    stevel 	 * interface to extract the kstat chain.
    493      0    stevel 	 */
    494      0    stevel 	kstat_chain_id = 0;
    495      0    stevel 	ksp = kstat_create("unix", 0, "kstat_headers", "kstat", KSTAT_TYPE_RAW,
    496   6695  aguzovsk 	    0, KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_VAR_SIZE);
    497      0    stevel 	if (ksp) {
    498      0    stevel 		ksp->ks_lock = &kstat_chain_lock;
    499      0    stevel 		ksp->ks_update = header_kstat_update;
    500      0    stevel 		ksp->ks_snapshot = header_kstat_snapshot;
    501      0    stevel 		kstat_install(ksp);
    502      0    stevel 	} else {
    503      0    stevel 		panic("cannot create kstat 'kstat_headers'");
    504      0    stevel 	}
    505      0    stevel 
    506      0    stevel 	ksp = kstat_create("unix", 0, "kstat_types", "kstat",
    507   6695  aguzovsk 	    KSTAT_TYPE_NAMED, KSTAT_NUM_TYPES, 0);
    508      0    stevel 	if (ksp) {
    509      0    stevel 		int i;
    510      0    stevel 		kstat_named_t *kn = KSTAT_NAMED_PTR(ksp);
    511      0    stevel 
    512      0    stevel 		for (i = 0; i < KSTAT_NUM_TYPES; i++) {
    513      0    stevel 			kstat_named_init(&kn[i], kstat_data_type[i].name,
    514   6695  aguzovsk 			    KSTAT_DATA_ULONG);
    515      0    stevel 			kn[i].value.ul = i;
    516      0    stevel 		}
    517      0    stevel 		kstat_install(ksp);
    518      0    stevel 	}
    519      0    stevel 
    520      0    stevel 	ksp = kstat_create("unix", 0, "sysinfo", "misc", KSTAT_TYPE_RAW,
    521   6695  aguzovsk 	    sizeof (sysinfo_t), KSTAT_FLAG_VIRTUAL);
    522      0    stevel 	if (ksp) {
    523      0    stevel 		ksp->ks_data = (void *) &sysinfo;
    524      0    stevel 		kstat_install(ksp);
    525      0    stevel 	}
    526      0    stevel 
    527      0    stevel 	ksp = kstat_create("unix", 0, "vminfo", "vm", KSTAT_TYPE_RAW,
    528   6695  aguzovsk 	    sizeof (vminfo_t), KSTAT_FLAG_VIRTUAL);
    529      0    stevel 	if (ksp) {
    530      0    stevel 		ksp->ks_data = (void *) &vminfo;
    531      0    stevel 		kstat_install(ksp);
    532      0    stevel 	}
    533      0    stevel 
    534      0    stevel 	ksp = kstat_create("unix", 0, "segmap", "vm", KSTAT_TYPE_NAMED,
    535   6695  aguzovsk 	    segmapcnt_ndata, KSTAT_FLAG_VIRTUAL);
    536      0    stevel 	if (ksp) {
    537      0    stevel 		ksp->ks_data = (void *) segmapcnt_ptr;
    538      0    stevel 		ksp->ks_update = segmap_kstat_update;
    539      0    stevel 		kstat_install(ksp);
    540      0    stevel 	}
    541      0    stevel 
    542      0    stevel 	ksp = kstat_create("unix", 0, "biostats", "misc", KSTAT_TYPE_NAMED,
    543   6695  aguzovsk 	    biostats_ndata, KSTAT_FLAG_VIRTUAL);
    544      0    stevel 	if (ksp) {
    545      0    stevel 		ksp->ks_data = (void *) biostats_ptr;
    546      0    stevel 		kstat_install(ksp);
    547      0    stevel 	}
    548      0    stevel 
    549      0    stevel #ifdef VAC
    550      0    stevel 	ksp = kstat_create("unix", 0, "flushmeter", "hat", KSTAT_TYPE_RAW,
    551   6695  aguzovsk 	    sizeof (struct flushmeter), KSTAT_FLAG_VIRTUAL);
    552      0    stevel 	if (ksp) {
    553      0    stevel 		ksp->ks_data = (void *) &flush_cnt;
    554      0    stevel 		kstat_install(ksp);
    555      0    stevel 	}
    556      0    stevel #endif	/* VAC */
    557      0    stevel 
    558      0    stevel 	ksp = kstat_create("unix", 0, "var", "misc", KSTAT_TYPE_RAW,
    559   6695  aguzovsk 	    sizeof (struct var), KSTAT_FLAG_VIRTUAL);
    560      0    stevel 	if (ksp) {
    561      0    stevel 		ksp->ks_data = (void *) &v;
    562      0    stevel 		kstat_install(ksp);
    563      0    stevel 	}
    564      0    stevel 
    565      0    stevel 	ksp = kstat_create("unix", 0, "system_misc", "misc", KSTAT_TYPE_NAMED,
    566   6695  aguzovsk 	    sizeof (system_misc_kstat) / sizeof (kstat_named_t),
    567   6695  aguzovsk 	    KSTAT_FLAG_VIRTUAL);
    568      0    stevel 	if (ksp) {
    569      0    stevel 		ksp->ks_data = (void *) &system_misc_kstat;
    570      0    stevel 		ksp->ks_update = system_misc_kstat_update;
    571      0    stevel 		kstat_install(ksp);
    572      0    stevel 	}
    573      0    stevel 
    574      0    stevel 	ksp = kstat_create("unix", 0, "system_pages", "pages", KSTAT_TYPE_NAMED,
    575   6695  aguzovsk 	    sizeof (system_pages_kstat) / sizeof (kstat_named_t),
    576   6695  aguzovsk 	    KSTAT_FLAG_VIRTUAL);
    577      0    stevel 	if (ksp) {
    578      0    stevel 		ksp->ks_data = (void *) &system_pages_kstat;
    579      0    stevel 		ksp->ks_update = system_pages_kstat_update;
    580      0    stevel 		kstat_install(ksp);
    581      0    stevel 	}
    582      0    stevel 
    583      0    stevel 	ksp = kstat_create("poll", 0, "pollstats", "misc", KSTAT_TYPE_NAMED,
    584      0    stevel 	    pollstats_ndata, KSTAT_FLAG_VIRTUAL | KSTAT_FLAG_WRITABLE);
    585      0    stevel 
    586      0    stevel 	if (ksp) {
    587      0    stevel 		ksp->ks_data = pollstats_ptr;
    588      0    stevel 		kstat_install(ksp);
    589      0    stevel 	}
    590      0    stevel }
    591      0    stevel 
    592      0    stevel /*
    593      0    stevel  * Caller of this should ensure that the string pointed by src
    594      0    stevel  * doesn't change while kstat's lock is held. Not doing so defeats
    595      0    stevel  * kstat's snapshot strategy as explained in <sys/kstat.h>
    596      0    stevel  */
    597      0    stevel void
    598      0    stevel kstat_named_setstr(kstat_named_t *knp, const char *src)
    599      0    stevel {
    600      0    stevel 	if (knp->data_type != KSTAT_DATA_STRING)
    601      0    stevel 		panic("kstat_named_setstr('%p', '%p'): "
    602   7240   rh87107 		    "named kstat is not of type KSTAT_DATA_STRING",
    603   7240   rh87107 		    (void *)knp, (void *)src);
    604      0    stevel 
    605      0    stevel 	KSTAT_NAMED_STR_PTR(knp) = (char *)src;
    606      0    stevel 	if (src != NULL)
    607      0    stevel 		KSTAT_NAMED_STR_BUFLEN(knp) = strlen(src) + 1;
    608      0    stevel 	else
    609      0    stevel 		KSTAT_NAMED_STR_BUFLEN(knp) = 0;
    610      0    stevel }
    611      0    stevel 
    612      0    stevel void
    613   2951     elowe kstat_set_string(char *dst, const char *src)
    614      0    stevel {
    615      0    stevel 	bzero(dst, KSTAT_STRLEN);
    616      0    stevel 	(void) strncpy(dst, src, KSTAT_STRLEN - 1);
    617      0    stevel }
    618      0    stevel 
    619      0    stevel void
    620   2951     elowe kstat_named_init(kstat_named_t *knp, const char *name, uchar_t data_type)
    621      0    stevel {
    622      0    stevel 	kstat_set_string(knp->name, name);
    623      0    stevel 	knp->data_type = data_type;
    624      0    stevel 
    625      0    stevel 	if (data_type == KSTAT_DATA_STRING)
    626      0    stevel 		kstat_named_setstr(knp, NULL);
    627      0    stevel }
    628      0    stevel 
    629      0    stevel void
    630   2951     elowe kstat_timer_init(kstat_timer_t *ktp, const char *name)
    631      0    stevel {
    632      0    stevel 	kstat_set_string(ktp->name, name);
    633      0    stevel }
    634      0    stevel 
    635      0    stevel /* ARGSUSED */
    636      0    stevel static int
    637      0    stevel default_kstat_update(kstat_t *ksp, int rw)
    638      0    stevel {
    639      0    stevel 	uint_t i;
    640      0    stevel 	size_t len = 0;
    641      0    stevel 	kstat_named_t *knp;
    642      0    stevel 
    643      0    stevel 	/*
    644      0    stevel 	 * Named kstats with variable-length long strings have a standard
    645      0    stevel 	 * way of determining how much space is needed to hold the snapshot:
    646      0    stevel 	 */
    647      0    stevel 	if (ksp->ks_data != NULL && ksp->ks_type == KSTAT_TYPE_NAMED &&
    648      0    stevel 	    (ksp->ks_flags & KSTAT_FLAG_VAR_SIZE)) {
    649      0    stevel 
    650      0    stevel 		/*
    651      0    stevel 		 * Add in the space required for the strings
    652      0    stevel 		 */
    653      0    stevel 		knp = KSTAT_NAMED_PTR(ksp);
    654      0    stevel 		for (i = 0; i < ksp->ks_ndata; i++, knp++) {
    655      0    stevel 			if (knp->data_type == KSTAT_DATA_STRING)
    656      0    stevel 				len += KSTAT_NAMED_STR_BUFLEN(knp);
    657      0    stevel 		}
    658      0    stevel 		ksp->ks_data_size =
    659      0    stevel 		    ksp->ks_ndata * sizeof (kstat_named_t) + len;
    660      0    stevel 	}
    661      0    stevel 	return (0);
    662      0    stevel }
    663      0    stevel 
    664      0    stevel static int
    665      0    stevel default_kstat_snapshot(kstat_t *ksp, void *buf, int rw)
    666      0    stevel {
    667      0    stevel 	kstat_io_t *kiop;
    668      0    stevel 	hrtime_t cur_time;
    669      0    stevel 	size_t	namedsz;
    670      0    stevel 
    671      0    stevel 	ksp->ks_snaptime = cur_time = gethrtime();
    672      0    stevel 
    673      0    stevel 	if (rw == KSTAT_WRITE) {
    674      0    stevel 		if (!(ksp->ks_flags & KSTAT_FLAG_WRITABLE))
    675      0    stevel 			return (EACCES);
    676      0    stevel 		bcopy(buf, ksp->ks_data, ksp->ks_data_size);
    677      0    stevel 		return (0);
    678      0    stevel 	}
    679      0    stevel 
    680      0    stevel 	/*
    681      0    stevel 	 * KSTAT_TYPE_NAMED kstats are defined to have ks_ndata
    682      0    stevel 	 * number of kstat_named_t structures, followed by an optional
    683      0    stevel 	 * string segment. The ks_data generally holds only the
    684      0    stevel 	 * kstat_named_t structures. So we copy it first. The strings,
    685      0    stevel 	 * if any, are copied below. For other kstat types, ks_data holds the
    686      0    stevel 	 * entire buffer.
    687      0    stevel 	 */
    688      0    stevel 
    689      0    stevel 	namedsz = sizeof (kstat_named_t) * ksp->ks_ndata;
    690      0    stevel 	if (ksp->ks_type == KSTAT_TYPE_NAMED && ksp->ks_data_size > namedsz)
    691      0    stevel 		bcopy(ksp->ks_data, buf, namedsz);
    692      0    stevel 	else
    693      0    stevel 		bcopy(ksp->ks_data, buf, ksp->ks_data_size);
    694      0    stevel 
    695      0    stevel 	/*
    696      0    stevel 	 * Apply kstat type-specific data massaging
    697      0    stevel 	 */
    698      0    stevel 	switch (ksp->ks_type) {
    699      0    stevel 
    700      0    stevel 	case KSTAT_TYPE_IO:
    701      0    stevel 		/*
    702      0    stevel 		 * Normalize time units and deal with incomplete transactions
    703      0    stevel 		 */
    704      0    stevel 		kiop = (kstat_io_t *)buf;
    705      0    stevel 
    706      0    stevel 		scalehrtime(&kiop->wtime);
    707      0    stevel 		scalehrtime(&kiop->wlentime);
    708      0    stevel 		scalehrtime(&kiop->wlastupdate);
    709      0    stevel 		scalehrtime(&kiop->rtime);
    710      0    stevel 		scalehrtime(&kiop->rlentime);
    711      0    stevel 		scalehrtime(&kiop->rlastupdate);
    712      0    stevel 
    713      0    stevel 		if (kiop->wcnt != 0) {
    714   2723       cth 			/* like kstat_waitq_exit */
    715      0    stevel 			hrtime_t wfix = cur_time - kiop->wlastupdate;
    716   2723       cth 			kiop->wlastupdate = cur_time;
    717   2723       cth 			kiop->wlentime += kiop->wcnt * wfix;
    718      0    stevel 			kiop->wtime += wfix;
    719      0    stevel 		}
    720   2723       cth 
    721      0    stevel 		if (kiop->rcnt != 0) {
    722   2723       cth 			/* like kstat_runq_exit */
    723      0    stevel 			hrtime_t rfix = cur_time - kiop->rlastupdate;
    724   2723       cth 			kiop->rlastupdate = cur_time;
    725   2723       cth 			kiop->rlentime += kiop->rcnt * rfix;
    726      0    stevel 			kiop->rtime += rfix;
    727      0    stevel 		}
    728      0    stevel 		break;
    729      0    stevel 
    730      0    stevel 	case KSTAT_TYPE_NAMED:
    731      0    stevel 		/*
    732      0    stevel 		 * Massage any long strings in at the end of the buffer
    733      0    stevel 		 */
    734      0    stevel 		if (ksp->ks_data_size > namedsz) {
    735      0    stevel 			uint_t i;
    736      0    stevel 			kstat_named_t *knp = buf;
    737      0    stevel 			char *dst = (char *)(knp + ksp->ks_ndata);
    738      0    stevel 			/*
    739      0    stevel 			 * Copy strings and update pointers
    740      0    stevel 			 */
    741      0    stevel 			for (i = 0; i < ksp->ks_ndata; i++, knp++) {
    742      0    stevel 				if (knp->data_type == KSTAT_DATA_STRING &&
    743      0    stevel 				    KSTAT_NAMED_STR_PTR(knp) != NULL) {
    744      0    stevel 					bcopy(KSTAT_NAMED_STR_PTR(knp), dst,
    745      0    stevel 					    KSTAT_NAMED_STR_BUFLEN(knp));
    746      0    stevel 					KSTAT_NAMED_STR_PTR(knp) = dst;
    747      0    stevel 					dst += KSTAT_NAMED_STR_BUFLEN(knp);
    748      0    stevel 				}
    749      0    stevel 			}
    750      0    stevel 			ASSERT(dst <= ((char *)buf + ksp->ks_data_size));
    751      0    stevel 		}
    752      0    stevel 		break;
    753      0    stevel 	}
    754      0    stevel 	return (0);
    755      0    stevel }
    756      0    stevel 
    757      0    stevel static int
    758      0    stevel header_kstat_update(kstat_t *header_ksp, int rw)
    759      0    stevel {
    760      0    stevel 	int nkstats = 0;
    761      0    stevel 	ekstat_t *e;
    762      0    stevel 	avl_tree_t *t = &kstat_avl_bykid;
    763      0    stevel 	zoneid_t zoneid;
    764      0    stevel 
    765      0    stevel 	if (rw == KSTAT_WRITE)
    766      0    stevel 		return (EACCES);
    767      0    stevel 
    768      0    stevel 	ASSERT(MUTEX_HELD(&kstat_chain_lock));
    769      0    stevel 
    770      0    stevel 	zoneid = getzoneid();
    771      0    stevel 	for (e = avl_first(t); e != NULL; e = avl_walk(t, e, AVL_AFTER)) {
    772      0    stevel 		if (kstat_zone_find((kstat_t *)e, zoneid)) {
    773      0    stevel 			nkstats++;
    774      0    stevel 		}
    775      0    stevel 	}
    776      0    stevel 	header_ksp->ks_ndata = nkstats;
    777      0    stevel 	header_ksp->ks_data_size = nkstats * sizeof (kstat_t);
    778      0    stevel 	return (0);
    779      0    stevel }
    780      0    stevel 
    781      0    stevel /*
    782      0    stevel  * Copy out the data section of kstat 0, which consists of the list
    783      0    stevel  * of all kstat headers.  By specification, these headers must be
    784      0    stevel  * copied out in order of increasing KID.
    785      0    stevel  */
    786      0    stevel static int
    787      0    stevel header_kstat_snapshot(kstat_t *header_ksp, void *buf, int rw)
    788      0    stevel {
    789      0    stevel 	ekstat_t *e;
    790      0    stevel 	avl_tree_t *t = &kstat_avl_bykid;
    791      0    stevel 	zoneid_t zoneid;
    792      0    stevel 
    793      0    stevel 	header_ksp->ks_snaptime = gethrtime();
    794      0    stevel 
    795      0    stevel 	if (rw == KSTAT_WRITE)
    796      0    stevel 		return (EACCES);
    797      0    stevel 
    798      0    stevel 	ASSERT(MUTEX_HELD(&kstat_chain_lock));
    799      0    stevel 
    800      0    stevel 	zoneid = getzoneid();
    801      0    stevel 	for (e = avl_first(t); e != NULL; e = avl_walk(t, e, AVL_AFTER)) {
    802      0    stevel 		if (kstat_zone_find((kstat_t *)e, zoneid)) {
    803      0    stevel 			bcopy(&e->e_ks, buf, sizeof (kstat_t));
    804      0    stevel 			buf = (char *)buf + sizeof (kstat_t);
    805      0    stevel 		}
    806      0    stevel 	}
    807      0    stevel 
    808      0    stevel 	return (0);
    809      0    stevel }
    810      0    stevel 
    811      0    stevel /* ARGSUSED */
    812      0    stevel static int
    813      0    stevel system_misc_kstat_update(kstat_t *ksp, int rw)
    814      0    stevel {
    815      0    stevel 	int myncpus = ncpus;
    816      0    stevel 	int *loadavgp = &avenrun[0];
    817      0    stevel 	int loadavg[LOADAVG_NSTATS];
    818   8798  Dhanaraj 	time_t zone_boot_time;
    819   8798  Dhanaraj 	clock_t zone_lbolt;
    820   8798  Dhanaraj 	hrtime_t zone_hrtime;
    821      0    stevel 
    822      0    stevel 	if (rw == KSTAT_WRITE)
    823      0    stevel 		return (EACCES);
    824      0    stevel 
    825      0    stevel 	if (!INGLOBALZONE(curproc)) {
    826      0    stevel 		/*
    827      0    stevel 		 * Here we grab cpu_lock which is OK as long as no-one in the
    828      0    stevel 		 * future attempts to lookup this particular kstat
    829      0    stevel 		 * (unix:0:system_misc) while holding cpu_lock.
    830      0    stevel 		 */
    831      0    stevel 		mutex_enter(&cpu_lock);
    832      0    stevel 		if (pool_pset_enabled()) {
    833      0    stevel 			psetid_t mypsid = zone_pset_get(curproc->p_zone);
    834      0    stevel 			int error;
    835      0    stevel 
    836      0    stevel 			myncpus = zone_ncpus_get(curproc->p_zone);
    837      0    stevel 			ASSERT(myncpus > 0);
    838      0    stevel 			error = cpupart_get_loadavg(mypsid, &loadavg[0],
    839      0    stevel 			    LOADAVG_NSTATS);
    840      0    stevel 			ASSERT(error == 0);
    841      0    stevel 			loadavgp = &loadavg[0];
    842      0    stevel 		}
    843      0    stevel 		mutex_exit(&cpu_lock);
    844      0    stevel 	}
    845      0    stevel 
    846   8798  Dhanaraj 	if (curproc->p_zone->zone_id == 0) {
    847   8798  Dhanaraj 		zone_boot_time = boot_time;
    848  11066    rafael 		zone_lbolt = ddi_get_lbolt();
    849   8798  Dhanaraj 	} else {
    850   8798  Dhanaraj 		struct timeval tvp;
    851   8798  Dhanaraj 		hrt2tv(curproc->p_zone->zone_zsched->p_mstart, &tvp);
    852   8798  Dhanaraj 		zone_boot_time = tvp.tv_sec;
    853   8798  Dhanaraj 
    854   8798  Dhanaraj 		zone_hrtime = gethrtime();
    855   8798  Dhanaraj 		zone_lbolt = (clock_t)(NSEC_TO_TICK(zone_hrtime) -
    856   8798  Dhanaraj 		    NSEC_TO_TICK(curproc->p_zone->zone_zsched->p_mstart));
    857   8798  Dhanaraj 	}
    858   8798  Dhanaraj 
    859      0    stevel 	system_misc_kstat.ncpus.value.ui32		= (uint32_t)myncpus;
    860   8798  Dhanaraj 	system_misc_kstat.lbolt.value.ui32		= (uint32_t)zone_lbolt;
    861      0    stevel 	system_misc_kstat.deficit.value.ui32		= (uint32_t)deficit;
    862   8798  Dhanaraj 	system_misc_kstat.clk_intr.value.ui32		= (uint32_t)zone_lbolt;
    863      0    stevel 	system_misc_kstat.vac.value.ui32		= (uint32_t)vac;
    864      0    stevel 	system_misc_kstat.nproc.value.ui32		= (uint32_t)nproc;
    865      0    stevel 	system_misc_kstat.avenrun_1min.value.ui32	= (uint32_t)loadavgp[0];
    866      0    stevel 	system_misc_kstat.avenrun_5min.value.ui32	= (uint32_t)loadavgp[1];
    867      0    stevel 	system_misc_kstat.avenrun_15min.value.ui32	= (uint32_t)loadavgp[2];
    868   8798  Dhanaraj 	system_misc_kstat.boot_time.value.ui32		= (uint32_t)
    869   8798  Dhanaraj 	    zone_boot_time;
    870      0    stevel 	return (0);
    871      0    stevel }
    872      0    stevel 
    873      0    stevel #ifdef	__sparc
    874      0    stevel extern caddr_t	econtig32;
    875      0    stevel #else	/* !__sparc */
    876      0    stevel extern caddr_t	econtig;
    877      0    stevel #endif	/* __sparc */
    878      0    stevel 
    879      0    stevel /* ARGSUSED */
    880      0    stevel static int
    881      0    stevel system_pages_kstat_update(kstat_t *ksp, int rw)
    882      0    stevel {
    883      0    stevel 	kobj_stat_t kobj_stat;
    884      0    stevel 
    885      0    stevel 	if (rw == KSTAT_WRITE) {
    886      0    stevel 		return (EACCES);
    887      0    stevel 	}
    888      0    stevel 
    889      0    stevel 	kobj_stat_get(&kobj_stat);
    890      0    stevel 	system_pages_kstat.physmem.value.ul	= (ulong_t)physmem;
    891      0    stevel 	system_pages_kstat.nalloc.value.ul	= kobj_stat.nalloc;
    892      0    stevel 	system_pages_kstat.nfree.value.ul	= kobj_stat.nfree;
    893      0    stevel 	system_pages_kstat.nalloc_calls.value.ul = kobj_stat.nalloc_calls;
    894      0    stevel 	system_pages_kstat.nfree_calls.value.ul	= kobj_stat.nfree_calls;
    895      0    stevel 	system_pages_kstat.kernelbase.value.ul	= (ulong_t)KERNELBASE;
    896      0    stevel 
    897      0    stevel #ifdef	__sparc
    898      0    stevel 	/*
    899      0    stevel 	 * kstat should REALLY be modified to also report kmem64_base and
    900      0    stevel 	 * kmem64_end (see sun4u/os/startup.c), as the virtual address range
    901      0    stevel 	 * [ kernelbase .. econtig ] no longer is truly reflective of the
    902      0    stevel 	 * kernel's vallocs...
    903      0    stevel 	 */
    904      0    stevel 	system_pages_kstat.econtig.value.ul	= (ulong_t)econtig32;
    905      0    stevel #else	/* !__sparc */
    906      0    stevel 	system_pages_kstat.econtig.value.ul	= (ulong_t)econtig;
    907      0    stevel #endif	/* __sparc */
    908      0    stevel 
    909      0    stevel 	system_pages_kstat.freemem.value.ul	= (ulong_t)freemem;
    910      0    stevel 	system_pages_kstat.availrmem.value.ul	= (ulong_t)availrmem;
    911      0    stevel 	system_pages_kstat.lotsfree.value.ul	= (ulong_t)lotsfree;
    912      0    stevel 	system_pages_kstat.desfree.value.ul	= (ulong_t)desfree;
    913      0    stevel 	system_pages_kstat.minfree.value.ul	= (ulong_t)minfree;
    914      0    stevel 	system_pages_kstat.fastscan.value.ul	= (ulong_t)fastscan;
    915      0    stevel 	system_pages_kstat.slowscan.value.ul	= (ulong_t)slowscan;
    916      0    stevel 	system_pages_kstat.nscan.value.ul	= (ulong_t)nscan;
    917      0    stevel 	system_pages_kstat.desscan.value.ul	= (ulong_t)desscan;
    918      0    stevel 	system_pages_kstat.pagesfree.value.ul	= (ulong_t)freemem;
    919      0    stevel 	system_pages_kstat.pageslocked.value.ul	= (ulong_t)(availrmem_initial -
    920      0    stevel 	    availrmem);
    921      0    stevel 	system_pages_kstat.pagestotal.value.ul	= (ulong_t)total_pages;
    922      0    stevel 	/*
    923      0    stevel 	 * pp_kernel represents total pages used by the kernel since the
    924      0    stevel 	 * startup. This formula takes into account the boottime kernel
    925      0    stevel 	 * footprint and also considers the availrmem changes because of
    926      0    stevel 	 * user explicit page locking.
    927      0    stevel 	 */
    928      0    stevel 	system_pages_kstat.pp_kernel.value.ul   = (ulong_t)(physinstalled -
    929   6695  aguzovsk 	    obp_pages - availrmem - k_anoninfo.ani_mem_resv -
    930   6695  aguzovsk 	    anon_segkp_pages_locked - pages_locked -
    931   6695  aguzovsk 	    pages_claimed - pages_useclaim);
    932      0    stevel 
    933      0    stevel 	return (0);
    934      0    stevel }
    935      0    stevel 
    936      0    stevel kstat_t *
    937   2951     elowe kstat_create(const char *ks_module, int ks_instance, const char *ks_name,
    938   2951     elowe     const char *ks_class, uchar_t ks_type, uint_t ks_ndata, uchar_t ks_flags)
    939      0    stevel {
    940      0    stevel 	return (kstat_create_zone(ks_module, ks_instance, ks_name, ks_class,
    941   6695  aguzovsk 	    ks_type, ks_ndata, ks_flags, ALL_ZONES));
    942      0    stevel }
    943      0    stevel 
    944      0    stevel /*
    945      0    stevel  * Allocate and initialize a kstat structure.  Or, if a dormant kstat with
    946      0    stevel  * the specified name exists, reactivate it.  Returns a pointer to the kstat
    947      0    stevel  * on success, NULL on failure.  The kstat will not be visible to the
    948      0    stevel  * kstat driver until kstat_install().
    949      0    stevel  */
    950      0    stevel kstat_t *
    951   2951     elowe kstat_create_zone(const char *ks_module, int ks_instance, const char *ks_name,
    952   2951     elowe     const char *ks_class, uchar_t ks_type, uint_t ks_ndata, uchar_t ks_flags,
    953      0    stevel     zoneid_t ks_zoneid)
    954      0    stevel {
    955      0    stevel 	size_t ks_data_size;
    956      0    stevel 	kstat_t *ksp;
    957      0    stevel 	ekstat_t *e;
    958      0    stevel 	avl_index_t where;
    959      0    stevel 	char namebuf[KSTAT_STRLEN + 16];
    960      0    stevel 
    961      0    stevel 	if (avl_numnodes(&kstat_avl_bykid) == 0) {
    962      0    stevel 		avl_create(&kstat_avl_bykid, kstat_compare_bykid,
    963      0    stevel 		    sizeof (ekstat_t), offsetof(struct ekstat, e_avl_bykid));
    964      0    stevel 
    965      0    stevel 		avl_create(&kstat_avl_byname, kstat_compare_byname,
    966      0    stevel 		    sizeof (ekstat_t), offsetof(struct ekstat, e_avl_byname));
    967      0    stevel 	}
    968      0    stevel 
    969      0    stevel 	/*
    970      0    stevel 	 * If ks_name == NULL, set the ks_name to <module><instance>.
    971      0    stevel 	 */
    972      0    stevel 	if (ks_name == NULL) {
    973      0    stevel 		char buf[KSTAT_STRLEN];
    974      0    stevel 		kstat_set_string(buf, ks_module);
    975      0    stevel 		(void) sprintf(namebuf, "%s%d", buf, ks_instance);
    976      0    stevel 		ks_name = namebuf;
    977      0    stevel 	}
    978      0    stevel 
    979      0    stevel 	/*
    980      0    stevel 	 * Make sure it's a valid kstat data type
    981      0    stevel 	 */
    982      0    stevel 	if (ks_type >= KSTAT_NUM_TYPES) {
    983      0    stevel 		cmn_err(CE_WARN, "kstat_create('%s', %d, '%s'): "
    984   6695  aguzovsk 		    "invalid kstat type %d",
    985   6695  aguzovsk 		    ks_module, ks_instance, ks_name, ks_type);
    986      0    stevel 		return (NULL);
    987      0    stevel 	}
    988      0    stevel 
    989      0    stevel 	/*
    990      0    stevel 	 * Don't allow persistent virtual kstats -- it makes no sense.
    991      0    stevel 	 * ks_data points to garbage when the client goes away.
    992      0    stevel 	 */
    993      0    stevel 	if ((ks_flags & KSTAT_FLAG_PERSISTENT) &&
    994      0    stevel 	    (ks_flags & KSTAT_FLAG_VIRTUAL)) {
    995      0    stevel 		cmn_err(CE_WARN, "kstat_create('%s', %d, '%s'): "
    996   6695  aguzovsk 		    "cannot create persistent virtual kstat",
    997   6695  aguzovsk 		    ks_module, ks_instance, ks_name);
    998      0    stevel 		return (NULL);
    999      0    stevel 	}
   1000      0    stevel 
   1001      0    stevel 	/*
   1002      0    stevel 	 * Don't allow variable-size physical kstats, since the framework's
   1003      0    stevel 	 * memory allocation for physical kstat data is fixed at creation time.
   1004      0    stevel 	 */
   1005      0    stevel 	if ((ks_flags & KSTAT_FLAG_VAR_SIZE) &&
   1006      0    stevel 	    !(ks_flags & KSTAT_FLAG_VIRTUAL)) {
   1007      0    stevel 		cmn_err(CE_WARN, "kstat_create('%s', %d, '%s'): "
   1008   6695  aguzovsk 		    "cannot create variable-size physical kstat",
   1009   6695  aguzovsk 		    ks_module, ks_instance, ks_name);
   1010      0    stevel 		return (NULL);
   1011      0    stevel 	}
   1012      0    stevel 
   1013      0    stevel 	/*
   1014      0    stevel 	 * Make sure the number of data fields is within legal range
   1015      0    stevel 	 */
   1016      0    stevel 	if (ks_ndata < kstat_data_type[ks_type].min_ndata ||
   1017      0    stevel 	    ks_ndata > kstat_data_type[ks_type].max_ndata) {
   1018      0    stevel 		cmn_err(CE_WARN, "kstat_create('%s', %d, '%s'): "
   1019   6695  aguzovsk 		    "ks_ndata=%d out of range [%d, %d]",
   1020   6695  aguzovsk 		    ks_module, ks_instance, ks_name, (int)ks_ndata,
   1021   6695  aguzovsk 		    kstat_data_type[ks_type].min_ndata,
   1022   6695  aguzovsk 		    kstat_data_type[ks_type].max_ndata);
   1023      0    stevel 		return (NULL);
   1024      0    stevel 	}
   1025      0    stevel 
   1026      0    stevel 	ks_data_size = kstat_data_type[ks_type].size * ks_ndata;
   1027      0    stevel 
   1028      0    stevel 	/*
   1029      0    stevel 	 * If the named kstat already exists and is dormant, reactivate it.
   1030      0    stevel 	 */
   1031      0    stevel 	ksp = kstat_hold_byname(ks_module, ks_instance, ks_name, ks_zoneid);
   1032      0    stevel 	if (ksp != NULL) {
   1033      0    stevel 		if (!(ksp->ks_flags & KSTAT_FLAG_DORMANT)) {
   1034      0    stevel 			/*
   1035      0    stevel 			 * The named kstat exists but is not dormant --
   1036      0    stevel 			 * this is a kstat namespace collision.
   1037      0    stevel 			 */
   1038      0    stevel 			kstat_rele(ksp);
   1039      0    stevel 			cmn_err(CE_WARN,
   1040      0    stevel 			    "kstat_create('%s', %d, '%s'): namespace collision",
   1041      0    stevel 			    ks_module, ks_instance, ks_name);
   1042      0    stevel 			return (NULL);
   1043      0    stevel 		}
   1044      0    stevel 		if ((strcmp(ksp->ks_class, ks_class) != 0) ||
   1045      0    stevel 		    (ksp->ks_type != ks_type) ||
   1046      0    stevel 		    (ksp->ks_ndata != ks_ndata) ||
   1047      0    stevel 		    (ks_flags & KSTAT_FLAG_VIRTUAL)) {
   1048      0    stevel 			/*
   1049      0    stevel 			 * The name is the same, but the other key parameters
   1050      0    stevel 			 * differ from those of the dormant kstat -- bogus.
   1051      0    stevel 			 */
   1052      0    stevel 			kstat_rele(ksp);
   1053      0    stevel 			cmn_err(CE_WARN, "kstat_create('%s', %d, '%s'): "
   1054   6695  aguzovsk 			    "invalid reactivation of dormant kstat",
   1055   6695  aguzovsk 			    ks_module, ks_instance, ks_name);
   1056      0    stevel 			return (NULL);
   1057      0    stevel 		}
   1058      0    stevel 		/*
   1059      0    stevel 		 * Return dormant kstat pointer to caller.  As usual,
   1060      0    stevel 		 * the kstat is marked invalid until kstat_install().
   1061      0    stevel 		 */
   1062      0    stevel 		ksp->ks_flags |= KSTAT_FLAG_INVALID;
   1063      0    stevel 		kstat_rele(ksp);
   1064      0    stevel 		return (ksp);
   1065      0    stevel 	}
   1066      0    stevel 
   1067      0    stevel 	/*
   1068      0    stevel 	 * Allocate memory for the new kstat header and, if this is a physical
   1069      0    stevel 	 * kstat, the data section.
   1070      0    stevel 	 */
   1071      0    stevel 	e = kstat_alloc(ks_flags & KSTAT_FLAG_VIRTUAL ? 0 : ks_data_size);
   1072      0    stevel 	if (e == NULL) {
   1073      0    stevel 		cmn_err(CE_NOTE, "kstat_create('%s', %d, '%s'): "
   1074   6695  aguzovsk 		    "insufficient kernel memory",
   1075   6695  aguzovsk 		    ks_module, ks_instance, ks_name);
   1076      0    stevel 		return (NULL);
   1077      0    stevel 	}
   1078      0    stevel 
   1079      0    stevel 	/*
   1080      0    stevel 	 * Initialize as many fields as we can.  The caller may reset
   1081      0    stevel 	 * ks_lock, ks_update, ks_private, and ks_snapshot as necessary.
   1082      0    stevel 	 * Creators of virtual kstats may also reset ks_data.  It is
   1083      0    stevel 	 * also up to the caller to initialize the kstat data section,
   1084      0    stevel 	 * if necessary.  All initialization must be complete before
   1085      0    stevel 	 * calling kstat_install().
   1086      0    stevel 	 */
   1087      0    stevel 	e->e_zone.zoneid = ks_zoneid;
   1088      0    stevel 	e->e_zone.next = NULL;
   1089      0    stevel 
   1090      0    stevel 	ksp = &e->e_ks;
   1091      0    stevel 	ksp->ks_crtime		= gethrtime();
   1092      0    stevel 	kstat_set_string(ksp->ks_module, ks_module);
   1093      0    stevel 	ksp->ks_instance	= ks_instance;
   1094      0    stevel 	kstat_set_string(ksp->ks_name, ks_name);
   1095      0    stevel 	ksp->ks_type		= ks_type;
   1096      0    stevel 	kstat_set_string(ksp->ks_class, ks_class);
   1097      0    stevel 	ksp->ks_flags		= ks_flags | KSTAT_FLAG_INVALID;
   1098      0    stevel 	if (ks_flags & KSTAT_FLAG_VIRTUAL)
   1099      0    stevel 		ksp->ks_data	= NULL;
   1100      0    stevel 	else
   1101      0    stevel 		ksp->ks_data	= (void *)(e + 1);
   1102      0    stevel 	ksp->ks_ndata		= ks_ndata;
   1103      0    stevel 	ksp->ks_data_size	= ks_data_size;
   1104      0    stevel 	ksp->ks_snaptime	= ksp->ks_crtime;
   1105      0    stevel 	ksp->ks_update		= default_kstat_update;
   1106      0    stevel 	ksp->ks_private		= NULL;
   1107      0    stevel 	ksp->ks_snapshot	= default_kstat_snapshot;
   1108      0    stevel 	ksp->ks_lock		= NULL;
   1109      0    stevel 
   1110      0    stevel 	mutex_enter(&kstat_chain_lock);
   1111      0    stevel 
   1112      0    stevel 	/*
   1113      0    stevel 	 * Add our kstat to the AVL trees.
   1114      0    stevel 	 */
   1115      0    stevel 	if (avl_find(&kstat_avl_byname, e, &where) != NULL) {
   1116      0    stevel 		mutex_exit(&kstat_chain_lock);
   1117      0    stevel 		cmn_err(CE_WARN,
   1118      0    stevel 		    "kstat_create('%s', %d, '%s'): namespace collision",
   1119      0    stevel 		    ks_module, ks_instance, ks_name);
   1120      0    stevel 		kstat_free(e);
   1121      0    stevel 		return (NULL);
   1122      0    stevel 	}
   1123      0    stevel 	avl_insert(&kstat_avl_byname, e, where);
   1124      0    stevel 
   1125      0    stevel 	/*
   1126      0    stevel 	 * Loop around until we find an unused KID.
   1127      0    stevel 	 */
   1128      0    stevel 	do {
   1129      0    stevel 		ksp->ks_kid = kstat_chain_id++;
   1130      0    stevel 	} while (avl_find(&kstat_avl_bykid, e, &where) != NULL);
   1131      0    stevel 	avl_insert(&kstat_avl_bykid, e, where);
   1132      0    stevel 
   1133      0    stevel 	mutex_exit(&kstat_chain_lock);
   1134      0    stevel 
   1135      0    stevel 	return (ksp);
   1136      0    stevel }
   1137      0    stevel 
   1138      0    stevel /*
   1139      0    stevel  * Activate a fully initialized kstat and make it visible to /dev/kstat.
   1140      0    stevel  */
   1141      0    stevel void
   1142      0    stevel kstat_install(kstat_t *ksp)
   1143      0    stevel {
   1144      0    stevel 	zoneid_t zoneid = ((ekstat_t *)ksp)->e_zone.zoneid;
   1145      0    stevel 
   1146      0    stevel 	/*
   1147      0    stevel 	 * If this is a variable-size kstat, it MUST provide kstat data locking
   1148      0    stevel 	 * to prevent data-size races with kstat readers.
   1149      0    stevel 	 */
   1150      0    stevel 	if ((ksp->ks_flags & KSTAT_FLAG_VAR_SIZE) && ksp->ks_lock == NULL) {
   1151      0    stevel 		panic("kstat_install('%s', %d, '%s'): "
   1152      0    stevel 		    "cannot create variable-size kstat without data lock",
   1153      0    stevel 		    ksp->ks_module, ksp->ks_instance, ksp->ks_name);
   1154      0    stevel 	}
   1155      0    stevel 
   1156      0    stevel 	if (kstat_hold_bykid(ksp->ks_kid, zoneid) != ksp) {
   1157      0    stevel 		cmn_err(CE_WARN, "kstat_install(%p): does not exist",
   1158      0    stevel 		    (void *)ksp);
   1159      0    stevel 		return;
   1160      0    stevel 	}
   1161      0    stevel 
   1162      0    stevel 	if (ksp->ks_type == KSTAT_TYPE_NAMED && ksp->ks_data != NULL) {
   1163      0    stevel 		int has_long_strings = 0;
   1164      0    stevel 		uint_t i;
   1165      0    stevel 		kstat_named_t *knp = KSTAT_NAMED_PTR(ksp);
   1166      0    stevel 
   1167      0    stevel 		for (i = 0; i < ksp->ks_ndata; i++, knp++) {
   1168      0    stevel 			if (knp->data_type == KSTAT_DATA_STRING) {
   1169      0    stevel 				has_long_strings = 1;
   1170      0    stevel 				break;
   1171      0    stevel 			}
   1172      0    stevel 		}
   1173      0    stevel 		/*
   1174      0    stevel 		 * It is an error for a named kstat with fields of
   1175      0    stevel 		 * KSTAT_DATA_STRING to be non-virtual.
   1176      0    stevel 		 */
   1177      0    stevel 		if (has_long_strings && !(ksp->ks_flags & KSTAT_FLAG_VIRTUAL)) {
   1178      0    stevel 			panic("kstat_install('%s', %d, '%s'): "
   1179      0    stevel 			    "named kstat containing KSTAT_DATA_STRING "
   1180      0    stevel 			    "is not virtual",
   1181      0    stevel 			    ksp->ks_module, ksp->ks_instance,
   1182      0    stevel 			    ksp->ks_name);
   1183      0    stevel 		}
   1184      0    stevel 		/*
   1185      0    stevel 		 * The default snapshot routine does not handle KSTAT_WRITE
   1186      0    stevel 		 * for long strings.
   1187      0    stevel 		 */
   1188      0    stevel 		if (has_long_strings && (ksp->ks_flags & KSTAT_FLAG_WRITABLE) &&
   1189      0    stevel 		    (ksp->ks_snapshot == default_kstat_snapshot)) {
   1190      0    stevel 			panic("kstat_install('%s', %d, '%s'): "
   1191      0    stevel 			    "named kstat containing KSTAT_DATA_STRING "
   1192      0    stevel 			    "is writable but uses default snapshot routine",
   1193      0    stevel 			    ksp->ks_module, ksp->ks_instance, ksp->ks_name);
   1194      0    stevel 		}
   1195      0    stevel 	}
   1196      0    stevel 
   1197      0    stevel 	if (ksp->ks_flags & KSTAT_FLAG_DORMANT) {
   1198      0    stevel 
   1199      0    stevel 		/*
   1200      0    stevel 		 * We are reactivating a dormant kstat.  Initialize the
   1201      0    stevel 		 * caller's underlying data to the value it had when the
   1202      0    stevel 		 * kstat went dormant, and mark the kstat as active.
   1203      0    stevel 		 * Grab the provider's kstat lock if it's not already held.
   1204      0    stevel 		 */
   1205      0    stevel 		kmutex_t *lp = ksp->ks_lock;
   1206      0    stevel 		if (lp != NULL && MUTEX_NOT_HELD(lp)) {
   1207      0    stevel 			mutex_enter(lp);
   1208      0    stevel 			(void) KSTAT_UPDATE(ksp, KSTAT_WRITE);
   1209      0    stevel 			mutex_exit(lp);
   1210      0    stevel 		} else {
   1211      0    stevel 			(void) KSTAT_UPDATE(ksp, KSTAT_WRITE);
   1212      0    stevel 		}
   1213      0    stevel 		ksp->ks_flags &= ~KSTAT_FLAG_DORMANT;
   1214      0    stevel 	}
   1215      0    stevel 
   1216      0    stevel 	/*
   1217      0    stevel 	 * Now that the kstat is active, make it visible to the kstat driver.
   1218      0    stevel 	 */
   1219      0    stevel 	ksp->ks_flags &= ~KSTAT_FLAG_INVALID;
   1220      0    stevel 	kstat_rele(ksp);
   1221      0    stevel }
   1222      0    stevel 
   1223      0    stevel /*
   1224      0    stevel  * Remove a kstat from the system.  Or, if it's a persistent kstat,
   1225      0    stevel  * just update the data and mark it as dormant.
   1226      0    stevel  */
   1227      0    stevel void
   1228      0    stevel kstat_delete(kstat_t *ksp)
   1229      0    stevel {
   1230      0    stevel 	kmutex_t *lp;
   1231      0    stevel 	ekstat_t *e = (ekstat_t *)ksp;
   1232      0    stevel 	zoneid_t zoneid = e->e_zone.zoneid;
   1233      0    stevel 	kstat_zone_t *kz;
   1234      0    stevel 
   1235      0    stevel 	if (ksp == NULL)
   1236      0    stevel 		return;
   1237      0    stevel 
   1238      0    stevel 	lp = ksp->ks_lock;
   1239      0    stevel 
   1240      0    stevel 	if (lp != NULL && MUTEX_HELD(lp)) {
   1241      0    stevel 		panic("kstat_delete(%p): caller holds data lock %p",
   1242      0    stevel 		    (void *)ksp, (void *)lp);
   1243      0    stevel 	}
   1244      0    stevel 
   1245      0    stevel 	if (kstat_hold_bykid(ksp->ks_kid, zoneid) != ksp) {
   1246      0    stevel 		cmn_err(CE_WARN, "kstat_delete(%p): does not exist",
   1247      0    stevel 		    (void *)ksp);
   1248      0    stevel 		return;
   1249      0    stevel 	}
   1250      0    stevel 
   1251      0    stevel 	if (ksp->ks_flags & KSTAT_FLAG_PERSISTENT) {
   1252      0    stevel 		/*
   1253      0    stevel 		 * Update the data one last time, so that all activity
   1254      0    stevel 		 * prior to going dormant has been accounted for.
   1255      0    stevel 		 */
   1256      0    stevel 		KSTAT_ENTER(ksp);
   1257      0    stevel 		(void) KSTAT_UPDATE(ksp, KSTAT_READ);
   1258      0    stevel 		KSTAT_EXIT(ksp);
   1259      0    stevel 
   1260      0    stevel 		/*
   1261      0    stevel 		 * Mark the kstat as dormant and restore caller-modifiable
   1262      0    stevel 		 * fields to default values, so the kstat is readable during
   1263      0    stevel 		 * the dormant phase.
   1264      0    stevel 		 */
   1265      0    stevel 		ksp->ks_flags |= KSTAT_FLAG_DORMANT;
   1266      0    stevel 		ksp->ks_lock = NULL;
   1267      0    stevel 		ksp->ks_update = default_kstat_update;
   1268      0    stevel 		ksp->ks_private = NULL;
   1269      0    stevel 		ksp->ks_snapshot = default_kstat_snapshot;
   1270      0    stevel 		kstat_rele(ksp);
   1271      0    stevel 		return;
   1272      0    stevel 	}
   1273      0    stevel 
   1274      0    stevel 	/*
   1275      0    stevel 	 * Remove the kstat from the framework's AVL trees,
   1276      0    stevel 	 * free the allocated memory, and increment kstat_chain_id so
   1277      0    stevel 	 * /dev/kstat clients can detect the event.
   1278      0    stevel 	 */
   1279      0    stevel 	mutex_enter(&kstat_chain_lock);
   1280      0    stevel 	avl_remove(&kstat_avl_bykid, e);
   1281      0    stevel 	avl_remove(&kstat_avl_byname, e);
   1282      0    stevel 	kstat_chain_id++;
   1283      0    stevel 	mutex_exit(&kstat_chain_lock);
   1284      0    stevel 
   1285      0    stevel 	kz = e->e_zone.next;
   1286      0    stevel 	while (kz != NULL) {
   1287      0    stevel 		kstat_zone_t *t = kz;
   1288      0    stevel 
   1289      0    stevel 		kz = kz->next;
   1290      0    stevel 		kmem_free(t, sizeof (*t));
   1291      0    stevel 	}
   1292      0    stevel 	kstat_rele(ksp);
   1293      0    stevel 	kstat_free(e);
   1294      0    stevel }
   1295      0    stevel 
   1296      0    stevel void
   1297   2951     elowe kstat_delete_byname_zone(const char *ks_module, int ks_instance,
   1298   2951     elowe     const char *ks_name, zoneid_t ks_zoneid)
   1299      0    stevel {
   1300      0    stevel 	kstat_t *ksp;
   1301      0    stevel 
   1302      0    stevel 	ksp = kstat_hold_byname(ks_module, ks_instance, ks_name, ks_zoneid);
   1303      0    stevel 	if (ksp != NULL) {
   1304      0    stevel 		kstat_rele(ksp);
   1305      0    stevel 		kstat_delete(ksp);
   1306      0    stevel 	}
   1307      0    stevel }
   1308      0    stevel 
   1309      0    stevel void
   1310   2951     elowe kstat_delete_byname(const char *ks_module, int ks_instance, const char *ks_name)
   1311      0    stevel {
   1312      0    stevel 	kstat_delete_byname_zone(ks_module, ks_instance, ks_name, ALL_ZONES);
   1313      0    stevel }
   1314      0    stevel 
   1315      0    stevel /*
   1316      0    stevel  * The sparc V9 versions of these routines can be much cheaper than
   1317      0    stevel  * the poor 32-bit compiler can comprehend, so they're in sparcv9_subr.s.
   1318      0    stevel  * For simplicity, however, we always feed the C versions to lint.
   1319      0    stevel  */
   1320      0    stevel #if !defined(__sparc) || defined(lint) || defined(__lint)
   1321      0    stevel 
   1322      0    stevel void
   1323      0    stevel kstat_waitq_enter(kstat_io_t *kiop)
   1324      0    stevel {
   1325      0    stevel 	hrtime_t new, delta;
   1326      0    stevel 	ulong_t wcnt;
   1327      0    stevel 
   1328      0    stevel 	new = gethrtime_unscaled();
   1329      0    stevel 	delta = new - kiop->wlastupdate;
   1330      0    stevel 	kiop->wlastupdate = new;
   1331      0    stevel 	wcnt = kiop->wcnt++;
   1332      0    stevel 	if (wcnt != 0) {
   1333      0    stevel 		kiop->wlentime += delta * wcnt;
   1334      0    stevel 		kiop->wtime += delta;
   1335      0    stevel 	}
   1336      0    stevel }
   1337      0    stevel 
   1338      0    stevel void
   1339      0    stevel kstat_waitq_exit(kstat_io_t *kiop)
   1340      0    stevel {
   1341      0    stevel 	hrtime_t new, delta;
   1342      0    stevel 	ulong_t wcnt;
   1343      0    stevel 
   1344      0    stevel 	new = gethrtime_unscaled();
   1345      0    stevel 	delta = new - kiop->wlastupdate;
   1346      0    stevel 	kiop->wlastupdate = new;
   1347      0    stevel 	wcnt = kiop->wcnt--;
   1348      0    stevel 	ASSERT((int)wcnt > 0);
   1349      0    stevel 	kiop->wlentime += delta * wcnt;
   1350      0    stevel 	kiop->wtime += delta;
   1351      0    stevel }
   1352      0    stevel 
   1353      0    stevel void
   1354      0    stevel kstat_runq_enter(kstat_io_t *kiop)
   1355      0    stevel {
   1356      0    stevel 	hrtime_t new, delta;
   1357      0    stevel 	ulong_t rcnt;
   1358      0    stevel 
   1359      0    stevel 	new = gethrtime_unscaled();
   1360      0    stevel 	delta = new - kiop->rlastupdate;
   1361      0    stevel 	kiop->rlastupdate = new;
   1362      0    stevel 	rcnt = kiop->rcnt++;
   1363      0    stevel 	if (rcnt != 0) {
   1364      0    stevel 		kiop->rlentime += delta * rcnt;
   1365      0    stevel 		kiop->rtime += delta;
   1366      0    stevel 	}
   1367      0    stevel }
   1368      0    stevel 
   1369      0    stevel void
   1370      0    stevel kstat_runq_exit(kstat_io_t *kiop)
   1371      0    stevel {
   1372      0    stevel 	hrtime_t new, delta;
   1373      0    stevel 	ulong_t rcnt;
   1374      0    stevel 
   1375      0    stevel 	new = gethrtime_unscaled();
   1376      0    stevel 	delta = new - kiop->rlastupdate;
   1377      0    stevel 	kiop->rlastupdate = new;
   1378      0    stevel 	rcnt = kiop->rcnt--;
   1379      0    stevel 	ASSERT((int)rcnt > 0);
   1380      0    stevel 	kiop->rlentime += delta * rcnt;
   1381      0    stevel 	kiop->rtime += delta;
   1382      0    stevel }
   1383      0    stevel 
   1384      0    stevel void
   1385      0    stevel kstat_waitq_to_runq(kstat_io_t *kiop)
   1386      0    stevel {
   1387      0    stevel 	hrtime_t new, delta;
   1388      0    stevel 	ulong_t wcnt, rcnt;
   1389      0    stevel 
   1390      0    stevel 	new = gethrtime_unscaled();
   1391      0    stevel 
   1392      0    stevel 	delta = new - kiop->wlastupdate;
   1393      0    stevel 	kiop->wlastupdate = new;
   1394      0    stevel 	wcnt = kiop->wcnt--;
   1395      0    stevel 	ASSERT((int)wcnt > 0);
   1396      0    stevel 	kiop->wlentime += delta * wcnt;
   1397      0    stevel 	kiop->wtime += delta;
   1398      0    stevel 
   1399      0    stevel 	delta = new - kiop->rlastupdate;
   1400      0    stevel 	kiop->rlastupdate = new;
   1401      0    stevel 	rcnt = kiop->rcnt++;
   1402      0    stevel 	if (rcnt != 0) {
   1403      0    stevel 		kiop->rlentime += delta * rcnt;
   1404      0    stevel 		kiop->rtime += delta;
   1405      0    stevel 	}
   1406      0    stevel }
   1407      0    stevel 
   1408      0    stevel void
   1409      0    stevel kstat_runq_back_to_waitq(kstat_io_t *kiop)
   1410      0    stevel {
   1411      0    stevel 	hrtime_t new, delta;
   1412      0    stevel 	ulong_t wcnt, rcnt;
   1413      0    stevel 
   1414      0    stevel 	new = gethrtime_unscaled();
   1415      0    stevel 
   1416      0    stevel 	delta = new - kiop->rlastupdate;
   1417      0    stevel 	kiop->rlastupdate = new;
   1418      0    stevel 	rcnt = kiop->rcnt--;
   1419      0    stevel 	ASSERT((int)rcnt > 0);
   1420      0    stevel 	kiop->rlentime += delta * rcnt;
   1421      0    stevel 	kiop->rtime += delta;
   1422      0    stevel 
   1423      0    stevel 	delta = new - kiop->wlastupdate;
   1424      0    stevel 	kiop->wlastupdate = new;
   1425      0    stevel 	wcnt = kiop->wcnt++;
   1426      0    stevel 	if (wcnt != 0) {
   1427      0    stevel 		kiop->wlentime += delta * wcnt;
   1428      0    stevel 		kiop->wtime += delta;
   1429      0    stevel 	}
   1430      0    stevel }
   1431      0    stevel 
   1432      0    stevel #endif
   1433      0    stevel 
   1434      0    stevel void
   1435      0    stevel kstat_timer_start(kstat_timer_t *ktp)
   1436      0    stevel {
   1437      0    stevel 	ktp->start_time = gethrtime();
   1438      0    stevel }
   1439      0    stevel 
   1440      0    stevel void
   1441      0    stevel kstat_timer_stop(kstat_timer_t *ktp)
   1442      0    stevel {
   1443      0    stevel 	hrtime_t	etime;
   1444      0    stevel 	u_longlong_t	num_events;
   1445      0    stevel 
   1446      0    stevel 	ktp->stop_time = etime = gethrtime();
   1447      0    stevel 	etime -= ktp->start_time;
   1448      0    stevel 	num_events = ktp->num_events;
   1449      0    stevel 	if (etime < ktp->min_time || num_events == 0)
   1450      0    stevel 		ktp->min_time = etime;
   1451      0    stevel 	if (etime > ktp->max_time)
   1452      0    stevel 		ktp->max_time = etime;
   1453      0    stevel 	ktp->elapsed_time += etime;
   1454      0    stevel 	ktp->num_events = num_events + 1;
   1455      0    stevel }
   1456