1*8304c252Smpi /* $OpenBSD: uvm.c,v 1.11 2025/01/23 11:05:26 mpi Exp $ */ 24b6a654dSkrw /* 34b6a654dSkrw * Copyright (c) 2008 Can Erkin Acar <canacar@openbsd.org> 44b6a654dSkrw * Copyright (c) 2018 Kenneth R Westerback <krw@openbsd.org> 54b6a654dSkrw * 64b6a654dSkrw * Permission to use, copy, modify, and distribute this software for any 74b6a654dSkrw * purpose with or without fee is hereby granted, provided that the above 84b6a654dSkrw * copyright notice and this permission notice appear in all copies. 94b6a654dSkrw * 104b6a654dSkrw * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 114b6a654dSkrw * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 124b6a654dSkrw * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 134b6a654dSkrw * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 144b6a654dSkrw * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 154b6a654dSkrw * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 164b6a654dSkrw * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 174b6a654dSkrw */ 184b6a654dSkrw 194b6a654dSkrw #include <sys/types.h> 204b6a654dSkrw #include <sys/signal.h> 214b6a654dSkrw #include <sys/sysctl.h> 224b6a654dSkrw #include <sys/pool.h> 234b6a654dSkrw #include <ctype.h> 244b6a654dSkrw #include <err.h> 254b6a654dSkrw #include <errno.h> 264b6a654dSkrw #include <stdlib.h> 274b6a654dSkrw #include <string.h> 284b6a654dSkrw #include <limits.h> 294b6a654dSkrw 304b6a654dSkrw #include "systat.h" 314b6a654dSkrw 324b6a654dSkrw #ifndef nitems 334b6a654dSkrw #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) 344b6a654dSkrw #endif 354b6a654dSkrw 364b6a654dSkrw void print_uvm(void); 374b6a654dSkrw int read_uvm(void); 384b6a654dSkrw int select_uvm(void); 394b6a654dSkrw 404b6a654dSkrw void print_uvmexp_field(field_def *, field_def *, int *, int *, const char *); 414b6a654dSkrw 424b6a654dSkrw struct uvmexp uvmexp; 434b6a654dSkrw struct uvmexp last_uvmexp; 444b6a654dSkrw 454b6a654dSkrw struct uvmline { 464b6a654dSkrw int *v1; 474b6a654dSkrw int *ov1; 484b6a654dSkrw char *n1; 494b6a654dSkrw int *v2; 504b6a654dSkrw int *ov2; 514b6a654dSkrw char *n2; 524b6a654dSkrw int *v3; 534b6a654dSkrw int *ov3; 544b6a654dSkrw char *n3; 554b6a654dSkrw }; 564b6a654dSkrw 574b6a654dSkrw struct uvmline uvmline[] = { 584b6a654dSkrw { NULL, NULL, "Page Counters", 594b6a654dSkrw NULL, NULL, "Stats Counters", 604b6a654dSkrw NULL, NULL, "Fault Counters" }, 614b6a654dSkrw { &uvmexp.npages, &last_uvmexp.npages, "npages", 624b6a654dSkrw &uvmexp.faults, &last_uvmexp.faults, "faults", 634b6a654dSkrw &uvmexp.fltnoram, &last_uvmexp.fltnoram, "fltnoram" }, 644b6a654dSkrw { &uvmexp.free, &last_uvmexp.free, "free", 654b6a654dSkrw &uvmexp.traps, &last_uvmexp.traps, "traps", 664b6a654dSkrw &uvmexp.fltnoanon, &last_uvmexp.fltnoanon, "fltnoanon" }, 674b6a654dSkrw { &uvmexp.active, &last_uvmexp.active, "active", 684b6a654dSkrw &uvmexp.intrs, &last_uvmexp.intrs, "intrs", 694b6a654dSkrw &uvmexp.fltnoamap, &last_uvmexp.fltnoamap, "fltnoamap" }, 704b6a654dSkrw { &uvmexp.inactive, &last_uvmexp.inactive, "inactive", 714b6a654dSkrw &uvmexp.swtch, &last_uvmexp.swtch, "swtch", 724b6a654dSkrw &uvmexp.fltpgwait, &last_uvmexp.fltpgwait, "fltpgwait" }, 734b6a654dSkrw { &uvmexp.paging, &last_uvmexp.paging, "paging", 744b6a654dSkrw &uvmexp.softs, &last_uvmexp.softs, "softs", 754b6a654dSkrw &uvmexp.fltpgrele, &last_uvmexp.fltpgrele, "fltpgrele" }, 764b6a654dSkrw { &uvmexp.wired, &last_uvmexp.wired, "wired", 774b6a654dSkrw &uvmexp.syscalls, &last_uvmexp.syscalls, "syscalls", 784b6a654dSkrw &uvmexp.fltrelck, &last_uvmexp.fltrelck, "fltrelck" }, 794b6a654dSkrw { &uvmexp.zeropages, &last_uvmexp.zeropages, "zeropages", 804b6a654dSkrw &uvmexp.pageins, &last_uvmexp.pageins, "pageins", 814b6a654dSkrw &uvmexp.fltrelckok, &last_uvmexp.fltrelckok, "fltrelckok" }, 8282673a18Smpi { &uvmexp.percpucaches, &last_uvmexp.percpucaches, "percpucaches", 83a1774ed1Skrw &uvmexp.pgswapin, &last_uvmexp.pgswapin, "pgswapin", 844b6a654dSkrw &uvmexp.fltanget, &last_uvmexp.fltanget, "fltanget" }, 8582673a18Smpi { NULL, NULL, NULL, 86a1774ed1Skrw &uvmexp.pgswapout, &last_uvmexp.pgswapout, "pgswapout", 874b6a654dSkrw &uvmexp.fltanretry, &last_uvmexp.fltanretry, "fltanretry" }, 8865a05629Skrw { NULL, NULL, NULL, 894b6a654dSkrw &uvmexp.forks, &last_uvmexp.forks, "forks", 90a1774ed1Skrw &uvmexp.fltamcopy, &last_uvmexp.fltamcopy, "fltamcopy" }, 914b6a654dSkrw { NULL, NULL, "Pageout Params", 92a1774ed1Skrw &uvmexp.forks_ppwait, &last_uvmexp.forks_ppwait, "forks_ppwait", 93a1774ed1Skrw &uvmexp.fltnamap, &last_uvmexp.fltnamap, "fltnamap" }, 944b6a654dSkrw { &uvmexp.freemin, &last_uvmexp.freemin, "freemin", 95a1774ed1Skrw &uvmexp.forks_sharevm, &last_uvmexp.forks_sharevm, "forks_sharevm", 96a1774ed1Skrw &uvmexp.fltnomap, &last_uvmexp.fltnomap, "fltnomap" }, 974b6a654dSkrw { &uvmexp.freetarg, &last_uvmexp.freetarg, "freetarg", 98a1774ed1Skrw &uvmexp.pga_zerohit, &last_uvmexp.pga_zerohit, "pga_zerohit", 99a1774ed1Skrw &uvmexp.fltlget, &last_uvmexp.fltlget, "fltlget" }, 1004b6a654dSkrw { &uvmexp.inactarg, &last_uvmexp.inactarg, "inactarg", 101a1774ed1Skrw &uvmexp.pga_zeromiss, &last_uvmexp.pga_zeromiss, "pga_zeromiss", 102a1774ed1Skrw &uvmexp.fltget, &last_uvmexp.fltget, "fltget" }, 1034b6a654dSkrw { &uvmexp.wiredmax, &last_uvmexp.wiredmax, "wiredmax", 1044b6a654dSkrw NULL, NULL, NULL, 105a1774ed1Skrw &uvmexp.flt_anon, &last_uvmexp.flt_anon, "flt_anon" }, 106*8304c252Smpi { NULL, NULL, NULL, 107*8304c252Smpi NULL, NULL, NULL, 108a1774ed1Skrw &uvmexp.flt_acow, &last_uvmexp.flt_acow, "flt_acow" }, 109*8304c252Smpi { NULL, NULL, NULL, 110*8304c252Smpi NULL, NULL, "Daemon Counters", 111a1774ed1Skrw &uvmexp.flt_obj, &last_uvmexp.flt_obj, "flt_obj" }, 112*8304c252Smpi { NULL, NULL, "Per-CPU Counters", 113*8304c252Smpi &uvmexp.pdwoke, &last_uvmexp.pdwoke, "pdwoke", 114a1774ed1Skrw &uvmexp.flt_prcopy, &last_uvmexp.flt_prcopy, "flt_prcopy" }, 115*8304c252Smpi { &uvmexp.pcphit, &last_uvmexp.pcphit, "pcphit", 116*8304c252Smpi &uvmexp.pdrevs, &last_uvmexp.pdrevs, "pdrevs", 117a1774ed1Skrw &uvmexp.flt_przero, &last_uvmexp.flt_przero, "flt_przero" }, 118*8304c252Smpi { &uvmexp.pcpmiss, &last_uvmexp.pcpmiss, "pcpmiss", 119*8304c252Smpi &uvmexp.pdswout, &last_uvmexp.pdswout, "pdswout", 120a1774ed1Skrw NULL, NULL, NULL }, 121*8304c252Smpi { NULL, NULL, NULL, 122a1774ed1Skrw &uvmexp.pdfreed, &last_uvmexp.pdfreed, "pdfreed", 123*8304c252Smpi NULL, NULL, NULL }, 1244b6a654dSkrw { NULL, NULL, NULL, 125a1774ed1Skrw &uvmexp.pdscans, &last_uvmexp.pdscans, "pdscans", 126*8304c252Smpi NULL, NULL, NULL }, 1274b6a654dSkrw { NULL, NULL, "Misc Counters", 128a1774ed1Skrw &uvmexp.pdanscan, &last_uvmexp.pdanscan, "pdanscan", 129*8304c252Smpi NULL, NULL, NULL }, 1304b6a654dSkrw { &uvmexp.fpswtch, &last_uvmexp.fpswtch, "fpswtch", 131a1774ed1Skrw &uvmexp.pdobscan, &last_uvmexp.pdobscan, "pdobscan", 132*8304c252Smpi NULL, NULL, NULL }, 1334b6a654dSkrw { &uvmexp.kmapent, &last_uvmexp.kmapent, "kmapent", 134a1774ed1Skrw &uvmexp.pdreact, &last_uvmexp.pdreact, "pdreact", 135*8304c252Smpi NULL, NULL, "Swap Counters" }, 1364b6a654dSkrw { NULL, NULL, NULL, 137a1774ed1Skrw &uvmexp.pdbusy, &last_uvmexp.pdbusy, "pdbusy", 138*8304c252Smpi &uvmexp.nswapdev, &last_uvmexp.nswapdev, "nswapdev" }, 1394b6a654dSkrw { NULL, NULL, "Constants", 140a1774ed1Skrw &uvmexp.pdpageouts, &last_uvmexp.pdpageouts, "pdpageouts", 141*8304c252Smpi &uvmexp.swpages, &last_uvmexp.swpages, "swpages" }, 1424b6a654dSkrw { &uvmexp.pagesize, &last_uvmexp.pagesize, "pagesize", 143a1774ed1Skrw &uvmexp.pdpending, &last_uvmexp.pdpending, "pdpending", 144*8304c252Smpi &uvmexp.swpginuse, &last_uvmexp.swpginuse, "swpginuse" }, 1454b6a654dSkrw { &uvmexp.pagemask, &last_uvmexp.pagemask, "pagemask", 146a1774ed1Skrw &uvmexp.pddeact, &last_uvmexp.pddeact, "pddeact", 147*8304c252Smpi &uvmexp.swpgonly, &last_uvmexp.swpgonly, "swpgonly" }, 1484b6a654dSkrw { &uvmexp.pageshift, &last_uvmexp.pageshift, "pageshift", 1494b6a654dSkrw NULL, NULL, NULL, 150*8304c252Smpi &uvmexp.nswget, &last_uvmexp.nswget, "nswget" } 1514b6a654dSkrw }; 1524b6a654dSkrw 1534b6a654dSkrw field_def fields_uvm[] = { 1544b6a654dSkrw {"", 5,10,1, FLD_ALIGN_RIGHT, -1,0,0,0 }, 1554b6a654dSkrw {"", 18,19,1, FLD_ALIGN_LEFT, -1,0,0,0 }, 1564b6a654dSkrw {"", 5,10,1, FLD_ALIGN_RIGHT, -1,0,0,0 }, 1574b6a654dSkrw {"", 18,19,1, FLD_ALIGN_LEFT, -1,0,0,0 }, 1584b6a654dSkrw {"", 5,10,1, FLD_ALIGN_RIGHT, -1,0,0,0 }, 1594b6a654dSkrw {"", 18,19,1, FLD_ALIGN_LEFT, -1,0,0,0 }, 1604b6a654dSkrw }; 1614b6a654dSkrw 1624b6a654dSkrw #define FLD_VALUE1 FIELD_ADDR(fields_uvm, 0) 1634b6a654dSkrw #define FLD_NAME1 FIELD_ADDR(fields_uvm, 1) 1644b6a654dSkrw #define FLD_VALUE2 FIELD_ADDR(fields_uvm, 2) 1654b6a654dSkrw #define FLD_NAME2 FIELD_ADDR(fields_uvm, 3) 1664b6a654dSkrw #define FLD_VALUE3 FIELD_ADDR(fields_uvm, 4) 1674b6a654dSkrw #define FLD_NAME3 FIELD_ADDR(fields_uvm, 5) 1684b6a654dSkrw 1694b6a654dSkrw /* Define views */ 1704b6a654dSkrw field_def *view_uvm_0[] = { 1714b6a654dSkrw FLD_VALUE1, FLD_NAME1, 1724b6a654dSkrw FLD_VALUE2, FLD_NAME2, 1734b6a654dSkrw FLD_VALUE3, FLD_NAME3, 1744b6a654dSkrw NULL 1754b6a654dSkrw }; 1764b6a654dSkrw 1774b6a654dSkrw /* Define view managers */ 1784b6a654dSkrw struct view_manager uvm_mgr = { 1794b6a654dSkrw "UVM", select_uvm, read_uvm, NULL, print_header, 1804b6a654dSkrw print_uvm, keyboard_callback, NULL, NULL 1814b6a654dSkrw }; 1824b6a654dSkrw 1834b6a654dSkrw field_view uvm_view = { 1844b6a654dSkrw view_uvm_0, 1854b6a654dSkrw "uvm", 1864b6a654dSkrw '5', 1874b6a654dSkrw &uvm_mgr 1884b6a654dSkrw }; 1894b6a654dSkrw 1904b6a654dSkrw int 1914b6a654dSkrw select_uvm(void) 1924b6a654dSkrw { 1934b6a654dSkrw return (0); 1944b6a654dSkrw } 1954b6a654dSkrw 1964b6a654dSkrw int 1974b6a654dSkrw read_uvm(void) 1984b6a654dSkrw { 1994b6a654dSkrw static int uvmexp_mib[2] = { CTL_VM, VM_UVMEXP }; 2004b6a654dSkrw size_t size; 2014b6a654dSkrw 2024b6a654dSkrw num_disp = nitems(uvmline); 2034b6a654dSkrw memcpy(&last_uvmexp, &uvmexp, sizeof(uvmexp)); 2044b6a654dSkrw 2054b6a654dSkrw size = sizeof(uvmexp); 2063aaa63ebSderaadt if (sysctl(uvmexp_mib, 2, &uvmexp, &size, NULL, 0) == -1) { 2074b6a654dSkrw error("Can't get VM_UVMEXP: %s\n", strerror(errno)); 2084b6a654dSkrw memset(&uvmexp, 0, sizeof(uvmexp)); 2094b6a654dSkrw } 2104b6a654dSkrw 2114b6a654dSkrw return 0; 2124b6a654dSkrw } 2134b6a654dSkrw 2144b6a654dSkrw void 2154b6a654dSkrw print_uvmexp_field(field_def *fvalue, field_def *fname, int *new, int *old, 2164b6a654dSkrw const char *name) 2174b6a654dSkrw { 2184b6a654dSkrw char *uppername; 219c1a2d5c1Sbluhm size_t len, i; 2204b6a654dSkrw 2214b6a654dSkrw if (new == NULL && name == NULL) 2224b6a654dSkrw return; 2234b6a654dSkrw 2244b6a654dSkrw if (new == NULL) { 2254b6a654dSkrw print_fld_str(fvalue, "====="); 2264b6a654dSkrw print_fld_str(fname, name); 2274b6a654dSkrw return; 2284b6a654dSkrw } 2294b6a654dSkrw 2304b6a654dSkrw if (*new != 0) 2314b6a654dSkrw print_fld_ssize(fvalue, *new); 2324b6a654dSkrw if (*new == *old) { 2334b6a654dSkrw print_fld_str(fname, name); 2344b6a654dSkrw return; 2354b6a654dSkrw } 236c1a2d5c1Sbluhm len = strlen(name); 237c1a2d5c1Sbluhm uppername = malloc(len + 1); 2384b6a654dSkrw if (uppername == NULL) 239c1a2d5c1Sbluhm err(1, "malloc"); 240c1a2d5c1Sbluhm for (i = 0; i < len; i++) 2414b6a654dSkrw uppername[i] = toupper(name[i]); 242c1a2d5c1Sbluhm uppername[len] = '\0'; 2434b6a654dSkrw print_fld_str(fname, uppername); 2444b6a654dSkrw free(uppername); 2454b6a654dSkrw } 2464b6a654dSkrw 2474b6a654dSkrw void 2484b6a654dSkrw print_uvm(void) 2494b6a654dSkrw { 2504b6a654dSkrw struct uvmline *l; 2514b6a654dSkrw int i, maxline; 2524b6a654dSkrw 2534b6a654dSkrw maxline = nitems(uvmline); 2544b6a654dSkrw if (maxline > (dispstart + maxprint)) 2554b6a654dSkrw maxline = dispstart + maxprint; 2564b6a654dSkrw 2574b6a654dSkrw for (i = dispstart; i < nitems(uvmline); i++) { 2584b6a654dSkrw l = &uvmline[i]; 2594b6a654dSkrw print_uvmexp_field(FLD_VALUE1, FLD_NAME1, l->v1, l->ov1, l->n1); 2604b6a654dSkrw print_uvmexp_field(FLD_VALUE2, FLD_NAME2, l->v2, l->ov2, l->n2); 2614b6a654dSkrw print_uvmexp_field(FLD_VALUE3, FLD_NAME3, l->v3, l->ov3, l->n3); 2624b6a654dSkrw end_line(); 2634b6a654dSkrw } 2644b6a654dSkrw } 2654b6a654dSkrw 2664b6a654dSkrw int 2674b6a654dSkrw inituvm(void) 2684b6a654dSkrw { 2694b6a654dSkrw add_view(&uvm_view); 2704b6a654dSkrw read_uvm(); 2714b6a654dSkrw 2724b6a654dSkrw return(0); 2734b6a654dSkrw } 274