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, args); \ 25 n += w; \ 26 } while (0) 27 28 static int vmm_ncpus; 29 static int vmm_fetched; 30 static struct vmmeter *vmm_cur, *vmm_prev; 31 static struct kinfo_cputime *vmm_cptime_cur, *vmm_cptime_prev; 32 static struct save_ctx symctx; 33 static int symbols_read; 34 35 static void 36 getvmm(void) 37 { 38 size_t sz; 39 int i; 40 41 for (i = 0; i < vmm_ncpus; ++i) { 42 struct vmmeter *vmm = &vmm_cur[i]; 43 char buf[64]; 44 45 sz = sizeof(*vmm); 46 snprintf(buf, sizeof(buf), "vm.cpu%d.vmmeter", i); 47 if (sysctlbyname(buf, vmm, &sz, NULL, 0)) 48 err(1, "sysctlbyname(cpu%d)", i); 49 50 vmm->v_intr -= (vmm->v_timer + vmm->v_ipi); 51 } 52 53 sz = vmm_ncpus * sizeof(struct kinfo_cputime); 54 if (sysctlbyname("kern.cputime", vmm_cptime_cur, &sz, NULL, 0)) 55 err(1, "kern.cputime"); 56 } 57 58 int 59 initvmm(void) 60 { 61 return 1; 62 } 63 64 void 65 showvmm(void) 66 { 67 int i, n; 68 69 if (!vmm_fetched) 70 return; 71 72 for (i = 0; i < vmm_ncpus; ++i) { 73 struct kinfo_cputime d; 74 uint64_t cp_total = 0; 75 76 n = X_START + CPU_LABEL_W; 77 78 #define D(idx, field) \ 79 (vmm_cur[idx].field - vmm_prev[idx].field) / (u_int)naptime 80 81 DRAW_ROW(n, CPU_START + i, 6, "%*u", D(i, v_timer)); 82 DRAW_ROW(n, CPU_START + i, 8, "%*u", D(i, v_ipi)); 83 DRAW_ROW(n, CPU_START + i, 8, "%*u", D(i, v_intr)); 84 85 #undef D 86 87 #define CPUD(dif, idx, field) \ 88 do { \ 89 dif.cp_##field = vmm_cptime_cur[idx].cp_##field - \ 90 vmm_cptime_prev[idx].cp_##field; \ 91 cp_total += dif.cp_##field; \ 92 } while (0) 93 94 #define CPUV(dif, field) \ 95 (dif.cp_##field * 100.0) / cp_total 96 97 CPUD(d, i, user); 98 CPUD(d, i, idle); 99 CPUD(d, i, intr); 100 CPUD(d, i, nice); 101 CPUD(d, i, sys); 102 103 if (cp_total == 0) 104 cp_total = 1; 105 106 DRAW_ROW(n, CPU_START + i, 7, "%*.1f", CPUV(d, user)); 107 DRAW_ROW(n, CPU_START + i, 7, "%*.1f", CPUV(d, nice)); 108 DRAW_ROW(n, CPU_START + i, 7, "%*.1f", CPUV(d, sys)); 109 DRAW_ROW(n, CPU_START + i, 7, "%*.1f", CPUV(d, intr)); 110 DRAW_ROW(n, CPU_START + i, 7, "%*.1f", CPUV(d, idle)); 111 112 #undef CPUV 113 #undef CPUD 114 #define CPUC(idx, field) vmm_cptime_cur[idx].cp_##field 115 116 n = X_START + CPU_LABEL_W; 117 118 DRAW_ROW(n, CPU_STARTX + i, 15, "%-*s", CPUC(i, msg)); 119 DRAW_ROW(n, CPU_STARTX + i, 35, "%-*s", 120 address_to_symbol((void *)(intptr_t)CPUC(i, stallpc), 121 &symctx)); 122 #undef CPUC 123 } 124 } 125 126 void 127 fetchvmm(void) 128 { 129 vmm_fetched = 1; 130 131 memcpy(vmm_prev, vmm_cur, sizeof(struct vmmeter) * vmm_ncpus); 132 memcpy(vmm_cptime_prev, vmm_cptime_cur, 133 sizeof(struct kinfo_cputime) * vmm_ncpus); 134 getvmm(); 135 } 136 137 void 138 labelvmm(void) 139 { 140 int i, n; 141 142 clear(); 143 144 n = X_START + CPU_LABEL_W; 145 146 DRAW_ROW(n, CPU_START - 1, 6, "%*s", "timer"); 147 DRAW_ROW(n, CPU_START - 1, 8, "%*s", "ipi"); 148 DRAW_ROW(n, CPU_START - 1, 8, "%*s", "extint"); 149 DRAW_ROW(n, CPU_START - 1, 7, "%*s", "user%"); 150 DRAW_ROW(n, CPU_START - 1, 7, "%*s", "nice%"); 151 DRAW_ROW(n, CPU_START - 1, 7, "%*s", "sys%"); 152 DRAW_ROW(n, CPU_START - 1, 7, "%*s", "intr%"); 153 DRAW_ROW(n, CPU_START - 1, 7, "%*s", "idle%"); 154 155 for (i = 0; i < vmm_ncpus; ++i) 156 mvprintw(CPU_START + i, X_START, "cpu%d", i); 157 158 n = X_START + CPU_LABEL_W; 159 DRAW_ROW(n, CPU_STARTX - 1, 15, "%-*s", "contention"); 160 DRAW_ROW(n, CPU_STARTX - 1, 35, "%-*s", "function"); 161 162 for (i = 0; i < vmm_ncpus; ++i) 163 mvprintw(CPU_STARTX + i, X_START, "cpu%d", i); 164 } 165 166 WINDOW * 167 openvmm(void) 168 { 169 if (symbols_read == 0) { 170 symbols_read = 1; 171 read_symbols(NULL); 172 } 173 174 if (kinfo_get_cpus(&vmm_ncpus)) 175 err(1, "kinfo_get_cpus"); 176 177 vmm_cur = calloc(vmm_ncpus, sizeof(*vmm_cur)); 178 if (vmm_cur == NULL) 179 err(1, "calloc vmm_cur"); 180 181 vmm_prev = calloc(vmm_ncpus, sizeof(*vmm_prev)); 182 if (vmm_prev == NULL) 183 err(1, "calloc vmm_prev"); 184 185 vmm_cptime_cur = calloc(vmm_ncpus, sizeof(*vmm_cptime_cur)); 186 if (vmm_cptime_cur == NULL) 187 err(1, "calloc vmm_cptime_cur"); 188 189 vmm_cptime_prev = calloc(vmm_ncpus, sizeof(*vmm_cptime_prev)); 190 if (vmm_cptime_prev == NULL) 191 err(1, "calloc vmm_cptime_prev"); 192 193 getvmm(); 194 195 return (stdscr); 196 } 197 198 void 199 closevmm(WINDOW *w) 200 { 201 if (vmm_cur != NULL) 202 free(vmm_cur); 203 if (vmm_prev != NULL) 204 free(vmm_prev); 205 206 if (vmm_cptime_cur != NULL) 207 free(vmm_cptime_cur); 208 if (vmm_cptime_prev != NULL) 209 free(vmm_cptime_prev); 210 211 vmm_fetched = 0; 212 213 if (w == NULL) 214 return; 215 wclear(w); 216 wrefresh(w); 217 } 218