7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * CDDL HEADER START
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * The contents of this file are subject to the terms of the
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * Common Development and Distribution License (the "License").
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * You may not use this file except in compliance with the License.
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * or http://www.opensolaris.org/os/licensing.
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * See the License for the specific language governing permissions
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * and limitations under the License.
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * When distributing Covered Code, include this CDDL HEADER in each
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * If applicable, add the following below this CDDL HEADER, with the
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * fields enclosed by brackets "[]" replaced with your own identifying
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * information: Portions Copyright [yyyy] [name of copyright owner]
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * CDDL HEADER END
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * Copyright (c) 2011, Joyent, Inc. All rights reserved.
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill int ksf_width; /* width for field in output line */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill uint32_t ksf_flags; /* flags for this field, if any */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill int ksf_hint; /* index hint for field in kstat */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill char ksi_name[KSTAT_STRLEN]; /* name of the underlying kstat */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill int ksi_instance; /* instance identifer of this kstat */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill uint64_t *ksi_data[2]; /* pointer to two generations of data */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill hrtime_t ksi_snaptime[2]; /* hrtime for data generations */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill struct kstat_instance *ksi_next; /* next in instance list */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill (void) fprintf(stderr, ": %s\n", strerror(error));
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillkstat_field_hint(kstat_t *ksp, kstat_field_t *field)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (strcmp(field->ksf_name, nm[i].name) == 0)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill fatal("could not find field '%s' in %s:%d\n",
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill field->ksf_name, ksp->ks_name, ksp->ks_instance);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillkstat_instances_compare(const void *lhs, const void *rhs)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_instance_t *l = *((kstat_instance_t **)lhs);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_instance_t *r = *((kstat_instance_t **)rhs);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if ((rval = strcmp(l->ksi_name, r->ksi_name)) != 0)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillkstat_instances_update(kstat_ctl_t *kcp, kstat_instance_t **head,
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if ((kid = kstat_chain_update(kcp)) == 0 && *head != NULL)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (ksi = *head; ksi != NULL; ksi = ksi->ksi_next)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (ksp = kcp->kc_chain; ksp != NULL; ksp = ksp->ks_next) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * Now look to see if we have this instance and name. (Yes,
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * this is a linear search; we're assuming that this list is
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * modest in size.)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (ksi = *head; ksi != NULL; ksi = ksi->ksi_next) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (strcmp(ksi->ksi_name, ksp->ks_name) != 0)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if ((ksi = malloc(sizeof (kstat_instance_t))) == NULL)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill fatal("could not allocate memory for stat instance");
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill (void) strlcpy(ksi->ksi_name, ksp->ks_name, KSTAT_STRLEN);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * Now we know how many instances we have; iterate back over them,
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * pruning the stale ones and adding the active ones to a holding
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * array in which to sort them.
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill sorted = (void *)alloca(ninstances * sizeof (kstat_instance_t *));
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill qsort(sorted, ninstances, sizeof (kstat_instance_t *),
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (i = 0; i < ninstances; i++) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill ksi->ksi_next = i < ninstances - 1 ? sorted[i + 1] : NULL;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillkstat_instances_read(kstat_ctl_t *kcp, kstat_instance_t *instances,
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (nfields = 0; fields[nfields].ksf_header != NULL; nfields++)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (ksi = instances; ksi != NULL; ksi = ksi->ksi_next) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * Our kstat has been removed since the update;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * NULL it out to prevent us from trying to read
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * it again (and to indicate that it should not
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * be displayed) and drive on.
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill fatal("%s:%d is not a named kstat", ksi->ksi_name,
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill size_t size = nfields * sizeof (uint64_t) * 2;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (i = 0; i < nfields; i++) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill strcmp(field->ksf_name, nm[hint].name) != 0) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill ksi->ksi_data[ksi->ksi_gen][i] = nm[hint].value.ui64;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill ksi->ksi_snaptime[ksi->ksi_gen] = ksp->ks_snaptime;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillkstat_instances_delta(kstat_instance_t *ksi, int i)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill uint64_t delta = ksi->ksi_data[gen ^ 1][i] - ksi->ksi_data[gen][i];
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill uint64_t tdelta = ksi->ksi_snaptime[gen ^ 1] - ksi->ksi_snaptime[gen];
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill return (((delta * (uint64_t)NANOSEC) + (tdelta / 2)) / tdelta);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillkstat_instances_print(kstat_instance_t *instances, kstat_field_t *fields,
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (nfields = 0; fields[nfields].ksf_header != NULL; nfields++)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (i = 0; i < nfields; i++) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill fields[i].ksf_header, i < nfields - 1 ? ' ' : '\n');
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (ksi = instances; ksi != NULL; ksi = ksi->ksi_next) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (ksi->ksi_snaptime[1] == 0 || ksi->ksi_ksp == NULL)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (i = 0; i < nfields; i++) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (fields[i].ksf_flags & KSTAT_FIELD_FILLER) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill (void) printf("%*lld%c", fields[i].ksf_width,
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill fields[i].ksf_flags & KSTAT_FIELD_USEINSTANCE ?
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (strstr(ksp->ks_name, name) != ksp->ks_name)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill/* BEGIN CSTYLED */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillchar *g_usage = "Usage: kvmstat [interval [count]]\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " Displays statistics for running kernel virtual machines, with one line\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " per virtual CPU. All statistics are reported as per-second rates.\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " The columns are as follows:\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " pid => identifier of process controlling the virtual CPU\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " vcpu => virtual CPU identifier relative to its virtual machine\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " exits => virtual machine exits for the virtual CPU\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " haltx => virtual machine exits due to the HLT instruction\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " irqx => virtual machine exits due to a pending external interrupt\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " irqwx => virtual machine exits due to an open interrupt window\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " iox => virtual machine exits due to an I/O instruction\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " mmiox => virtual machine exits due to memory mapped I/O \n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " irqs => interrupts injected into the virtual CPU\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " emul => instructions emulated in the kernel\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " eptv => extended page table violations\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill/* END CSTYLED */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill { "vcpu", NULL, 4, KSTAT_FIELD_USEINSTANCE },
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (setitimer(ITIMER_REAL, &itimer, NULL) != 0) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill fatal("could not set timer to %d second%s", interval,
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_instances_update(kcp, &instances, interested);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_instances_read(kcp, instances, fields);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (i++ > 0) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill instances != NULL && instances->ksi_next == NULL ?
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill /*NOTREACHED*/