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