1f110b23bSJohn Baldwin /*- 2f110b23bSJohn Baldwin * Copyright (c) 2008 Yahoo!, Inc. 3f110b23bSJohn Baldwin * All rights reserved. 4f110b23bSJohn Baldwin * Written by: John Baldwin <jhb@FreeBSD.org> 5f110b23bSJohn Baldwin * 6f110b23bSJohn Baldwin * Redistribution and use in source and binary forms, with or without 7f110b23bSJohn Baldwin * modification, are permitted provided that the following conditions 8f110b23bSJohn Baldwin * are met: 9f110b23bSJohn Baldwin * 1. Redistributions of source code must retain the above copyright 10f110b23bSJohn Baldwin * notice, this list of conditions and the following disclaimer. 11f110b23bSJohn Baldwin * 2. Redistributions in binary form must reproduce the above copyright 12f110b23bSJohn Baldwin * notice, this list of conditions and the following disclaimer in the 13f110b23bSJohn Baldwin * documentation and/or other materials provided with the distribution. 14f110b23bSJohn Baldwin * 3. Neither the name of the author nor the names of any co-contributors 15f110b23bSJohn Baldwin * may be used to endorse or promote products derived from this software 16f110b23bSJohn Baldwin * without specific prior written permission. 17f110b23bSJohn Baldwin * 18f110b23bSJohn Baldwin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19f110b23bSJohn Baldwin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20f110b23bSJohn Baldwin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21f110b23bSJohn Baldwin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22f110b23bSJohn Baldwin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23f110b23bSJohn Baldwin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24f110b23bSJohn Baldwin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25f110b23bSJohn Baldwin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26f110b23bSJohn Baldwin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27f110b23bSJohn Baldwin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28f110b23bSJohn Baldwin * SUCH DAMAGE. 29f110b23bSJohn Baldwin */ 30f110b23bSJohn Baldwin 31f110b23bSJohn Baldwin #include <sys/cdefs.h> 32f110b23bSJohn Baldwin __FBSDID("$FreeBSD$"); 33f110b23bSJohn Baldwin 34f110b23bSJohn Baldwin #include <sys/param.h> 35f110b23bSJohn Baldwin #include <sys/pcpu.h> 36f110b23bSJohn Baldwin #include <sys/resource.h> 37f110b23bSJohn Baldwin #include <sys/sysctl.h> 38f110b23bSJohn Baldwin #include <errno.h> 39f110b23bSJohn Baldwin #include <kvm.h> 40f110b23bSJohn Baldwin #include <limits.h> 41f110b23bSJohn Baldwin #include <stdlib.h> 42953e4134SEd Schouten #include <string.h> 43f110b23bSJohn Baldwin 44f110b23bSJohn Baldwin #include "kvm_private.h" 45f110b23bSJohn Baldwin 46f110b23bSJohn Baldwin static struct nlist kvm_cp_time_nl[] = { 47f110b23bSJohn Baldwin { "_cp_time" }, /* (deprecated) */ 48f110b23bSJohn Baldwin { NULL }, 49f110b23bSJohn Baldwin }; 50f110b23bSJohn Baldwin 51f110b23bSJohn Baldwin #define NL_CP_TIME 0 52f110b23bSJohn Baldwin 53f110b23bSJohn Baldwin static int kvm_cp_time_cached; 54f110b23bSJohn Baldwin 55f110b23bSJohn Baldwin static int 56f110b23bSJohn Baldwin _kvm_cp_time_init(kvm_t *kd) 57f110b23bSJohn Baldwin { 58f110b23bSJohn Baldwin 59f110b23bSJohn Baldwin if (kvm_nlist(kd, kvm_cp_time_nl) < 0) 60f110b23bSJohn Baldwin return (-1); 61f110b23bSJohn Baldwin kvm_cp_time_cached = 1; 62f110b23bSJohn Baldwin } 63f110b23bSJohn Baldwin 64f110b23bSJohn Baldwin static int 65f110b23bSJohn Baldwin getsysctl(kvm_t *kd, const char *name, void *buf, size_t len) 66f110b23bSJohn Baldwin { 67f110b23bSJohn Baldwin size_t nlen; 68f110b23bSJohn Baldwin 69f110b23bSJohn Baldwin nlen = len; 70f110b23bSJohn Baldwin if (sysctlbyname(name, buf, &nlen, NULL, 0) < 0) { 71f110b23bSJohn Baldwin _kvm_err(kd, kd->program, "cannot read sysctl %s:%s", name, 72f110b23bSJohn Baldwin strerror(errno)); 73f110b23bSJohn Baldwin return (-1); 74f110b23bSJohn Baldwin } 75f110b23bSJohn Baldwin if (nlen != len) { 76f110b23bSJohn Baldwin _kvm_err(kd, kd->program, "sysctl %s has unexpected size", 77f110b23bSJohn Baldwin name); 78f110b23bSJohn Baldwin return (-1); 79f110b23bSJohn Baldwin } 80f110b23bSJohn Baldwin return (0); 81f110b23bSJohn Baldwin } 82f110b23bSJohn Baldwin 83f110b23bSJohn Baldwin int 84f110b23bSJohn Baldwin kvm_getcptime(kvm_t *kd, long *cp_time) 85f110b23bSJohn Baldwin { 86f110b23bSJohn Baldwin struct pcpu *pc; 87f110b23bSJohn Baldwin int i, j, maxcpu; 88f110b23bSJohn Baldwin 89f110b23bSJohn Baldwin if (kd == NULL) { 90f110b23bSJohn Baldwin kvm_cp_time_cached = 0; 91f110b23bSJohn Baldwin return (0); 92f110b23bSJohn Baldwin } 93f110b23bSJohn Baldwin 94f110b23bSJohn Baldwin if (ISALIVE(kd)) 95f110b23bSJohn Baldwin return (getsysctl(kd, "kern.cp_time", cp_time, sizeof(long) * 96f110b23bSJohn Baldwin CPUSTATES)); 97f110b23bSJohn Baldwin 98f110b23bSJohn Baldwin if (kvm_cp_time_cached == 0) { 99f110b23bSJohn Baldwin if (_kvm_cp_time_init(kd) < 0) 100f110b23bSJohn Baldwin return (-1); 101f110b23bSJohn Baldwin } 102f110b23bSJohn Baldwin 103f110b23bSJohn Baldwin /* If this kernel has a "cp_time[]" symbol, then just read that. */ 104f110b23bSJohn Baldwin if (kvm_cp_time_nl[NL_CP_TIME].n_value != 0) { 105f110b23bSJohn Baldwin if (kvm_read(kd, kvm_cp_time_nl[NL_CP_TIME].n_value, cp_time, 106f110b23bSJohn Baldwin sizeof(long) * CPUSTATES) != sizeof(long) * CPUSTATES) { 107f110b23bSJohn Baldwin _kvm_err(kd, kd->program, "cannot read cp_time array"); 108f110b23bSJohn Baldwin return (-1); 109f110b23bSJohn Baldwin } 110f110b23bSJohn Baldwin return (0); 111f110b23bSJohn Baldwin } 112f110b23bSJohn Baldwin 113f110b23bSJohn Baldwin /* 114f110b23bSJohn Baldwin * If we don't have that symbol, then we have to simulate 115f110b23bSJohn Baldwin * "cp_time[]" by adding up the individual times for each CPU. 116f110b23bSJohn Baldwin */ 117f110b23bSJohn Baldwin maxcpu = kvm_getmaxcpu(kd); 118f110b23bSJohn Baldwin if (maxcpu < 0) 119f110b23bSJohn Baldwin return (-1); 120f110b23bSJohn Baldwin for (i = 0; i < CPUSTATES; i++) 121f110b23bSJohn Baldwin cp_time[i] = 0; 122f110b23bSJohn Baldwin for (i = 0; i < maxcpu; i++) { 123f110b23bSJohn Baldwin pc = kvm_getpcpu(kd, i); 124f110b23bSJohn Baldwin if (pc == NULL) 125f110b23bSJohn Baldwin continue; 126f110b23bSJohn Baldwin if (pc == (void *)-1) 127f110b23bSJohn Baldwin return (-1); 128f110b23bSJohn Baldwin for (j = 0; j < CPUSTATES; j++) 129f110b23bSJohn Baldwin cp_time[j] += pc->pc_cp_time[j]; 130f110b23bSJohn Baldwin free(pc); 131f110b23bSJohn Baldwin } 132f110b23bSJohn Baldwin return (0); 133f110b23bSJohn Baldwin } 134