1 #define _KERNEL_STRUCTURES 2 #include <sys/param.h> 3 #include <sys/sysctl.h> 4 #include <sys/vmmeter.h> 5 6 #include <err.h> 7 #include <kinfo.h> 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <devstat.h> 12 13 #include "systat.h" 14 #include "extern.h" 15 16 #define X_START 1 17 #define CPU_START 1 18 #define CPU_LABEL_W 7 19 20 #define DRAW_ROW(n, y, w, fmt, args...) \ 21 do { \ 22 mvprintw(y, n, fmt, w, args); \ 23 n += w; \ 24 } while (0) 25 26 static int vmm_ncpus; 27 static int vmm_fetched; 28 static struct vmmeter *vmm_cur, *vmm_prev; 29 static struct kinfo_cputime *vmm_cptime_cur, *vmm_cptime_prev; 30 31 static void 32 getvmm(void) 33 { 34 size_t sz; 35 int i; 36 37 for (i = 0; i < vmm_ncpus; ++i) { 38 struct vmmeter *vmm = &vmm_cur[i]; 39 char buf[64]; 40 41 sz = sizeof(*vmm); 42 snprintf(buf, sizeof(buf), "vm.cpu%d.vmmeter", i); 43 if (sysctlbyname(buf, vmm, &sz, NULL, 0)) 44 err(1, "sysctlbyname(cpu%d)", i); 45 46 vmm->v_intr -= (vmm->v_timer + vmm->v_ipi); 47 } 48 49 sz = vmm_ncpus * sizeof(struct kinfo_cputime); 50 if (sysctlbyname("kern.cputime", vmm_cptime_cur, &sz, NULL, 0)) 51 err(1, "kern.cputime"); 52 } 53 54 int 55 initvmm(void) 56 { 57 return 1; 58 } 59 60 void 61 showvmm(void) 62 { 63 int i, n; 64 65 if (!vmm_fetched) 66 return; 67 68 for (i = 0; i < vmm_ncpus; ++i) { 69 struct kinfo_cputime d; 70 uint64_t cp_total = 0; 71 72 n = X_START + CPU_LABEL_W; 73 74 #define D(idx, field) \ 75 (vmm_cur[idx].field - vmm_prev[idx].field) / (u_int)naptime 76 77 DRAW_ROW(n, CPU_START + i, 6, "%*u", D(i, v_timer)); 78 DRAW_ROW(n, CPU_START + i, 8, "%*u", D(i, v_ipi)); 79 DRAW_ROW(n, CPU_START + i, 8, "%*u", D(i, v_intr)); 80 81 #undef D 82 83 #define CPUD(dif, idx, field) \ 84 do { \ 85 dif.cp_##field = vmm_cptime_cur[idx].cp_##field - \ 86 vmm_cptime_prev[idx].cp_##field; \ 87 cp_total += dif.cp_##field; \ 88 } while (0) 89 90 #define CPUV(dif, field) \ 91 (dif.cp_##field * 100.0) / cp_total 92 93 CPUD(d, i, user); 94 CPUD(d, i, idle); 95 CPUD(d, i, intr); 96 CPUD(d, i, nice); 97 CPUD(d, i, sys); 98 99 if (cp_total == 0) 100 cp_total = 1; 101 102 DRAW_ROW(n, CPU_START + i, 7, "%*.1f", CPUV(d, user)); 103 DRAW_ROW(n, CPU_START + i, 7, "%*.1f", CPUV(d, nice)); 104 DRAW_ROW(n, CPU_START + i, 7, "%*.1f", CPUV(d, sys)); 105 DRAW_ROW(n, CPU_START + i, 7, "%*.1f", CPUV(d, intr)); 106 DRAW_ROW(n, CPU_START + i, 7, "%*.1f", CPUV(d, idle)); 107 108 #undef CPUV 109 #undef CPUD 110 } 111 } 112 113 void 114 fetchvmm(void) 115 { 116 vmm_fetched = 1; 117 118 memcpy(vmm_prev, vmm_cur, sizeof(struct vmmeter) * vmm_ncpus); 119 memcpy(vmm_cptime_prev, vmm_cptime_cur, 120 sizeof(struct kinfo_cputime) * vmm_ncpus); 121 getvmm(); 122 } 123 124 void 125 labelvmm(void) 126 { 127 int i, n; 128 129 clear(); 130 131 n = X_START + CPU_LABEL_W; 132 133 DRAW_ROW(n, 0, 6, "%*s", "timer"); 134 DRAW_ROW(n, 0, 8, "%*s", "ipi"); 135 DRAW_ROW(n, 0, 8, "%*s", "extint"); 136 DRAW_ROW(n, 0, 7, "%*s", "user%"); 137 DRAW_ROW(n, 0, 7, "%*s", "nice%"); 138 DRAW_ROW(n, 0, 7, "%*s", "sys%"); 139 DRAW_ROW(n, 0, 7, "%*s", "intr%"); 140 DRAW_ROW(n, 0, 7, "%*s", "idle%"); 141 142 for (i = 0; i < vmm_ncpus; ++i) 143 mvprintw(CPU_START + i, X_START, "cpu%d", i); 144 } 145 146 WINDOW * 147 openvmm(void) 148 { 149 if (kinfo_get_cpus(&vmm_ncpus)) 150 err(1, "kinfo_get_cpus"); 151 152 vmm_cur = calloc(vmm_ncpus, sizeof(*vmm_cur)); 153 if (vmm_cur == NULL) 154 err(1, "calloc vmm_cur"); 155 156 vmm_prev = calloc(vmm_ncpus, sizeof(*vmm_prev)); 157 if (vmm_prev == NULL) 158 err(1, "calloc vmm_prev"); 159 160 vmm_cptime_cur = calloc(vmm_ncpus, sizeof(*vmm_cptime_cur)); 161 if (vmm_cptime_cur == NULL) 162 err(1, "calloc vmm_cptime_cur"); 163 164 vmm_cptime_prev = calloc(vmm_ncpus, sizeof(*vmm_cptime_prev)); 165 if (vmm_cptime_prev == NULL) 166 err(1, "calloc vmm_cptime_prev"); 167 168 getvmm(); 169 170 return (stdscr); 171 } 172 173 void 174 closevmm(WINDOW *w) 175 { 176 if (vmm_cur != NULL) 177 free(vmm_cur); 178 if (vmm_prev != NULL) 179 free(vmm_prev); 180 181 if (vmm_cptime_cur != NULL) 182 free(vmm_cptime_cur); 183 if (vmm_cptime_prev != NULL) 184 free(vmm_cptime_prev); 185 186 vmm_fetched = 0; 187 188 if (w == NULL) 189 return; 190 wclear(w); 191 wrefresh(w); 192 } 193