1 #define _KERNEL_STRUCTURES 2 #include <sys/param.h> 3 #include <sys/sysctl.h> 4 #include <sys/vmmeter.h> 5 #include "symbols.h" 6 7 #include <err.h> 8 #include <kinfo.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 #include <devstat.h> 13 14 #include "systat.h" 15 #include "extern.h" 16 17 #define X_START 1 18 #define CPU_START 1 19 #define CPU_STARTX (3 + vmm_ncpus) 20 #define CPU_LABEL_W 7 21 22 #define DRAW_ROW(n, y, w, fmt, args...) \ 23 do { \ 24 mvprintw(y, n, fmt, w - 1, args); \ 25 n += w; \ 26 } while (0) 27 28 #define DRAW_ROW2(n, y, w, fmt, args...) \ 29 do { \ 30 mvprintw(y, n, fmt, w - 1, w - 1, args); \ 31 n += w; \ 32 } while (0) 33 34 static int vmm_ncpus; 35 static int vmm_fetched; 36 static struct vmmeter *vmm_cur, *vmm_prev; 37 static struct kinfo_cputime *vmm_cptime_cur, *vmm_cptime_prev; 38 #if 0 39 static struct save_ctx symctx; 40 #endif 41 static int symbols_read; 42 43 static void 44 getvmm(void) 45 { 46 size_t sz; 47 int i; 48 49 for (i = 0; i < vmm_ncpus; ++i) { 50 struct vmmeter *vmm = &vmm_cur[i]; 51 char buf[64]; 52 53 sz = sizeof(*vmm); 54 snprintf(buf, sizeof(buf), "vm.cpu%d.vmmeter", i); 55 if (sysctlbyname(buf, vmm, &sz, NULL, 0)) 56 err(1, "sysctlbyname(cpu%d)", i); 57 58 vmm->v_intr -= (vmm->v_timer + vmm->v_ipi); 59 } 60 61 sz = vmm_ncpus * sizeof(struct kinfo_cputime); 62 if (sysctlbyname("kern.cputime", vmm_cptime_cur, &sz, NULL, 0)) 63 err(1, "kern.cputime"); 64 } 65 66 int 67 initvmm(void) 68 { 69 return 1; 70 } 71 72 void 73 showvmm(void) 74 { 75 int i, n; 76 77 if (!vmm_fetched) 78 return; 79 80 for (i = 0; i < vmm_ncpus; ++i) { 81 struct kinfo_cputime d; 82 uint64_t cp_total = 0; 83 84 n = X_START + CPU_LABEL_W; 85 86 #define D(idx, field) \ 87 (vmm_cur[idx].field - vmm_prev[idx].field) / (u_int)naptime 88 89 DRAW_ROW(n, CPU_START + i, 6, "%*u", D(i, v_timer)); 90 DRAW_ROW(n, CPU_START + i, 8, "%*u", D(i, v_ipi)); 91 DRAW_ROW(n, CPU_START + i, 8, "%*u", D(i, v_intr)); 92 93 #define CPUD(dif, idx, field) \ 94 do { \ 95 dif.cp_##field = vmm_cptime_cur[idx].cp_##field - \ 96 vmm_cptime_prev[idx].cp_##field; \ 97 cp_total += dif.cp_##field; \ 98 } while (0) 99 100 #define CPUV(dif, field) \ 101 (dif.cp_##field * 100.0) / cp_total 102 103 CPUD(d, i, user); 104 CPUD(d, i, idle); 105 CPUD(d, i, intr); 106 CPUD(d, i, nice); 107 CPUD(d, i, sys); 108 109 if (cp_total == 0) 110 cp_total = 1; 111 112 DRAW_ROW(n, CPU_START + i, 6, "%*.1f", 113 CPUV(d, user) + CPUV(d, nice)); 114 /* DRAW_ROW(n, CPU_START + i, 6, "%*.1f", CPUV(d, nice));*/ 115 DRAW_ROW(n, CPU_START + i, 6, "%*.1f", CPUV(d, sys)); 116 DRAW_ROW(n, CPU_START + i, 6, "%*.1f", CPUV(d, intr)); 117 DRAW_ROW(n, CPU_START + i, 6, "%*.1f", CPUV(d, idle)); 118 119 /* 120 * Display token collision count and the last-colliding 121 * token name. 122 */ 123 if (D(i, v_lock_colls) > 9999999) 124 DRAW_ROW(n, CPU_START + i, 8, "%*u", 9999999); 125 else 126 DRAW_ROW(n, CPU_START + i, 8, "%*u", 127 D(i, v_lock_colls)); 128 129 if (D(i, v_lock_colls) == 0) { 130 DRAW_ROW2(n, CPU_START + i, 18, "%*.*s", ""); 131 } else { 132 DRAW_ROW2(n, CPU_START + i, 18, "%*.*s", 133 vmm_cur[i].v_lock_name); 134 } 135 136 #undef D 137 #undef CPUV 138 #undef CPUD 139 #define CPUC(idx, field) vmm_cptime_cur[idx].cp_##field 140 141 #if 0 142 n = X_START + CPU_LABEL_W; 143 144 DRAW_ROW(n, CPU_STARTX + i, 15, "%-*s", CPUC(i, msg)); 145 DRAW_ROW(n, CPU_STARTX + i, 35, "%-*s", 146 address_to_symbol((void *)(intptr_t)CPUC(i, stallpc), 147 &symctx)); 148 #endif 149 #undef CPUC 150 } 151 } 152 153 void 154 fetchvmm(void) 155 { 156 vmm_fetched = 1; 157 158 memcpy(vmm_prev, vmm_cur, sizeof(struct vmmeter) * vmm_ncpus); 159 memcpy(vmm_cptime_prev, vmm_cptime_cur, 160 sizeof(struct kinfo_cputime) * vmm_ncpus); 161 getvmm(); 162 } 163 164 void 165 labelvmm(void) 166 { 167 int i, n; 168 169 clear(); 170 171 n = X_START + CPU_LABEL_W; 172 173 DRAW_ROW(n, CPU_START - 1, 6, "%*s", "timer"); 174 DRAW_ROW(n, CPU_START - 1, 8, "%*s", "ipi"); 175 DRAW_ROW(n, CPU_START - 1, 8, "%*s", "extint"); 176 DRAW_ROW(n, CPU_START - 1, 6, "%*s", "user%"); 177 /* DRAW_ROW(n, CPU_START - 1, 6, "%*s", "nice%");*/ 178 DRAW_ROW(n, CPU_START - 1, 6, "%*s", "sys%"); 179 DRAW_ROW(n, CPU_START - 1, 6, "%*s", "intr%"); 180 DRAW_ROW(n, CPU_START - 1, 6, "%*s", "idle%"); 181 DRAW_ROW(n, CPU_START - 1, 8, "%*s", "smpcol"); 182 DRAW_ROW(n, CPU_START - 1, 18, "%*s", "label"); 183 184 for (i = 0; i < vmm_ncpus; ++i) 185 mvprintw(CPU_START + i, X_START, "cpu%d", i); 186 187 #if 0 188 n = X_START + CPU_LABEL_W; 189 DRAW_ROW(n, CPU_STARTX - 1, 15, "%-*s", "contention"); 190 DRAW_ROW(n, CPU_STARTX - 1, 35, "%-*s", "function"); 191 192 for (i = 0; i < vmm_ncpus; ++i) 193 mvprintw(CPU_STARTX + i, X_START, "cpu%d", i); 194 #endif 195 } 196 197 WINDOW * 198 openvmm(void) 199 { 200 if (symbols_read == 0) { 201 symbols_read = 1; 202 read_symbols(NULL); 203 } 204 205 if (kinfo_get_cpus(&vmm_ncpus)) 206 err(1, "kinfo_get_cpus"); 207 208 vmm_cur = calloc(vmm_ncpus, sizeof(*vmm_cur)); 209 if (vmm_cur == NULL) 210 err(1, "calloc vmm_cur"); 211 212 vmm_prev = calloc(vmm_ncpus, sizeof(*vmm_prev)); 213 if (vmm_prev == NULL) 214 err(1, "calloc vmm_prev"); 215 216 vmm_cptime_cur = calloc(vmm_ncpus, sizeof(*vmm_cptime_cur)); 217 if (vmm_cptime_cur == NULL) 218 err(1, "calloc vmm_cptime_cur"); 219 220 vmm_cptime_prev = calloc(vmm_ncpus, sizeof(*vmm_cptime_prev)); 221 if (vmm_cptime_prev == NULL) 222 err(1, "calloc vmm_cptime_prev"); 223 224 getvmm(); 225 226 return (stdscr); 227 } 228 229 void 230 closevmm(WINDOW *w) 231 { 232 if (vmm_cur != NULL) 233 free(vmm_cur); 234 if (vmm_prev != NULL) 235 free(vmm_prev); 236 237 if (vmm_cptime_cur != NULL) 238 free(vmm_cptime_cur); 239 if (vmm_cptime_prev != NULL) 240 free(vmm_cptime_prev); 241 242 vmm_fetched = 0; 243 244 if (w == NULL) 245 return; 246 wclear(w); 247 wrefresh(w); 248 } 249