1250757Sjkim/*- 2250757Sjkim * SPDX-License-Identifier: BSD-3-Clause 3250757Sjkim * 4250757Sjkim * Copyright (c) 1982, 1986, 1989, 1993 5250757Sjkim * The Regents of the University of California. All rights reserved. 6250757Sjkim * 7250757Sjkim * Redistribution and use in source and binary forms, with or without 8250757Sjkim * modification, are permitted provided that the following conditions 9250757Sjkim * are met: 10250757Sjkim * 1. Redistributions of source code must retain the above copyright 11250757Sjkim * notice, this list of conditions and the following disclaimer. 12250757Sjkim * 2. Redistributions in binary form must reproduce the above copyright 13250757Sjkim * notice, this list of conditions and the following disclaimer in the 14250757Sjkim * documentation and/or other materials provided with the distribution. 15250757Sjkim * 3. Neither the name of the University nor the names of its contributors 16250757Sjkim * may be used to endorse or promote products derived from this software 17250757Sjkim * without specific prior written permission. 18250757Sjkim * 19250757Sjkim * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20250757Sjkim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21250757Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22250757Sjkim * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23250757Sjkim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24250757Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25250757Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26250757Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27250757Sjkim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28250757Sjkim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29250757Sjkim * SUCH DAMAGE. 30250757Sjkim */ 31250757Sjkim 32250757Sjkim#include <sys/param.h> 33250757Sjkim#include <sys/systm.h> 34250757Sjkim#include <sys/kernel.h> 35250757Sjkim#include <sys/lock.h> 36250757Sjkim#include <sys/malloc.h> 37250757Sjkim#include <sys/mutex.h> 38250757Sjkim#include <sys/proc.h> 39250757Sjkim#include <sys/resource.h> 40250757Sjkim#include <sys/rwlock.h> 41250757Sjkim#include <sys/sx.h> 42250757Sjkim#include <sys/vmmeter.h> 43250757Sjkim#include <sys/smp.h> 44250838Sjkim 45250838Sjkim#include <vm/vm.h> 46250838Sjkim#include <vm/vm_page.h> 47250757Sjkim#include <vm/vm_extern.h> 48250757Sjkim#include <vm/vm_param.h> 49250757Sjkim#include <vm/vm_phys.h> 50250757Sjkim#include <vm/vm_pagequeue.h> 51250757Sjkim#include <vm/pmap.h> 52250757Sjkim#include <vm/vm_map.h> 53250757Sjkim#include <vm/vm_object.h> 54250757Sjkim#include <sys/sysctl.h> 55250757Sjkim 56250757Sjkimstruct vmmeter __read_mostly vm_cnt = { 57250757Sjkim .v_swtch = EARLY_COUNTER, 58250757Sjkim .v_trap = EARLY_COUNTER, 59250757Sjkim .v_syscall = EARLY_COUNTER, 60250757Sjkim .v_intr = EARLY_COUNTER, 61250757Sjkim .v_soft = EARLY_COUNTER, 62250757Sjkim .v_vm_faults = EARLY_COUNTER, 63250757Sjkim .v_io_faults = EARLY_COUNTER, 64250757Sjkim .v_cow_faults = EARLY_COUNTER, 65250757Sjkim .v_cow_optim = EARLY_COUNTER, 66250757Sjkim .v_zfod = EARLY_COUNTER, 67250757Sjkim .v_ozfod = EARLY_COUNTER, 68250757Sjkim .v_swapin = EARLY_COUNTER, 69250757Sjkim .v_swapout = EARLY_COUNTER, 70250757Sjkim .v_swappgsin = EARLY_COUNTER, 71250757Sjkim .v_swappgsout = EARLY_COUNTER, 72250757Sjkim .v_vnodein = EARLY_COUNTER, 73250757Sjkim .v_vnodeout = EARLY_COUNTER, 74250757Sjkim .v_vnodepgsin = EARLY_COUNTER, 75250757Sjkim .v_vnodepgsout = EARLY_COUNTER, 76250757Sjkim .v_intrans = EARLY_COUNTER, 77250757Sjkim .v_reactivated = EARLY_COUNTER, 78250757Sjkim .v_pdwakeups = EARLY_COUNTER, 79250757Sjkim .v_pdpages = EARLY_COUNTER, 80250757Sjkim .v_pdshortfalls = EARLY_COUNTER, 81250757Sjkim .v_dfree = EARLY_COUNTER, 82250757Sjkim .v_pfree = EARLY_COUNTER, 83250757Sjkim .v_tfree = EARLY_COUNTER, 84250757Sjkim .v_forks = EARLY_COUNTER, 85250757Sjkim .v_vforks = EARLY_COUNTER, 86250757Sjkim .v_rforks = EARLY_COUNTER, 87250757Sjkim .v_kthreads = EARLY_COUNTER, 88250757Sjkim .v_forkpages = EARLY_COUNTER, 89250757Sjkim .v_vforkpages = EARLY_COUNTER, 90250757Sjkim .v_rforkpages = EARLY_COUNTER, 91250757Sjkim .v_kthreadpages = EARLY_COUNTER, 92250757Sjkim .v_wire_count = EARLY_COUNTER, 93250757Sjkim}; 94250757Sjkim 95250757Sjkimu_long __exclusive_cache_line vm_user_wire_count; 96250757Sjkim 97250757Sjkimstatic void 98250757Sjkimvmcounter_startup(void) 99250757Sjkim{ 100250757Sjkim counter_u64_t *cnt = (counter_u64_t *)&vm_cnt; 101250757Sjkim 102250757Sjkim COUNTER_ARRAY_ALLOC(cnt, VM_METER_NCOUNTERS, M_WAITOK); 103250757Sjkim} 104250757SjkimSYSINIT(counter, SI_SUB_KMEM, SI_ORDER_FIRST, vmcounter_startup, NULL); 105250757Sjkim 106250757SjkimSYSCTL_UINT(_vm, VM_V_FREE_MIN, v_free_min, 107250757Sjkim CTLFLAG_RW, &vm_cnt.v_free_min, 0, "Minimum low-free-pages threshold"); 108250757SjkimSYSCTL_UINT(_vm, VM_V_FREE_TARGET, v_free_target, 109250757Sjkim CTLFLAG_RW, &vm_cnt.v_free_target, 0, "Desired free pages"); 110250757SjkimSYSCTL_UINT(_vm, VM_V_FREE_RESERVED, v_free_reserved, 111250757Sjkim CTLFLAG_RW, &vm_cnt.v_free_reserved, 0, "Pages reserved for deadlock"); 112250757SjkimSYSCTL_UINT(_vm, VM_V_INACTIVE_TARGET, v_inactive_target, 113250757Sjkim CTLFLAG_RW, &vm_cnt.v_inactive_target, 0, "Pages desired inactive"); 114250757SjkimSYSCTL_UINT(_vm, VM_V_PAGEOUT_FREE_MIN, v_pageout_free_min, 115250757Sjkim CTLFLAG_RW, &vm_cnt.v_pageout_free_min, 0, "Min pages reserved for kernel"); 116250757SjkimSYSCTL_UINT(_vm, OID_AUTO, v_free_severe, 117250757Sjkim CTLFLAG_RW, &vm_cnt.v_free_severe, 0, "Severe page depletion point"); 118250757Sjkim 119250757Sjkimstatic int 120250757Sjkimsysctl_vm_loadavg(SYSCTL_HANDLER_ARGS) 121250757Sjkim{ 122250757Sjkim 123250757Sjkim#ifdef SCTL_MASK32 124250757Sjkim uint32_t la[4]; 125250757Sjkim 126250757Sjkim if (req->flags & SCTL_MASK32) { 127250757Sjkim la[0] = averunnable.ldavg[0]; 128250757Sjkim la[1] = averunnable.ldavg[1]; 129250757Sjkim la[2] = averunnable.ldavg[2]; 130250757Sjkim la[3] = averunnable.fscale; 131250757Sjkim return SYSCTL_OUT(req, la, sizeof(la)); 132250757Sjkim } else 133250757Sjkim#endif 134250757Sjkim return SYSCTL_OUT(req, &averunnable, sizeof(averunnable)); 135250757Sjkim} 136250757SjkimSYSCTL_PROC(_vm, VM_LOADAVG, loadavg, CTLTYPE_STRUCT | CTLFLAG_RD | 137250757Sjkim CTLFLAG_MPSAFE, NULL, 0, sysctl_vm_loadavg, "S,loadavg", 138250757Sjkim "Machine loadaverage history"); 139250757Sjkim 140250757Sjkim#if defined(COMPAT_FREEBSD11) 141250757Sjkimstruct vmtotal11 { 142250757Sjkim int16_t t_rq; 143250757Sjkim int16_t t_dw; 144250757Sjkim int16_t t_pw; 145250757Sjkim int16_t t_sl; 146250757Sjkim int16_t t_sw; 147250757Sjkim int32_t t_vm; 148250757Sjkim int32_t t_avm; 149250757Sjkim int32_t t_rm; 150250757Sjkim int32_t t_arm; 151250757Sjkim int32_t t_vmshr; 152250757Sjkim int32_t t_avmshr; 153250757Sjkim int32_t t_rmshr; 154250757Sjkim int32_t t_armshr; 155250757Sjkim int32_t t_free; 156250757Sjkim}; 157250757Sjkim#endif 158250757Sjkim 159250757Sjkimstatic int 160250757Sjkimvmtotal(SYSCTL_HANDLER_ARGS) 161250757Sjkim{ 162250757Sjkim struct vmtotal total; 163250757Sjkim#if defined(COMPAT_FREEBSD11) 164250757Sjkim struct vmtotal11 total11; 165250757Sjkim#endif 166250757Sjkim vm_object_t object; 167250757Sjkim struct proc *p; 168250757Sjkim struct thread *td; 169250757Sjkim 170250757Sjkim if (req->oldptr == NULL) { 171250757Sjkim#if defined(COMPAT_FREEBSD11) 172250757Sjkim if (curproc->p_osrel < P_OSREL_VMTOTAL64) 173250757Sjkim return (SYSCTL_OUT(req, NULL, sizeof(total11))); 174250757Sjkim#endif 175250757Sjkim return (SYSCTL_OUT(req, NULL, sizeof(total))); 176250757Sjkim } 177250757Sjkim bzero(&total, sizeof(total)); 178250757Sjkim 179250757Sjkim /* 180250757Sjkim * Calculate process statistics. 181250757Sjkim */ 182250757Sjkim sx_slock(&allproc_lock); 183250757Sjkim FOREACH_PROC_IN_SYSTEM(p) { 184250757Sjkim if ((p->p_flag & P_SYSTEM) != 0) 185250757Sjkim continue; 186250757Sjkim PROC_LOCK(p); 187250757Sjkim if (p->p_state != PRS_NEW) { 188250757Sjkim FOREACH_THREAD_IN_PROC(p, td) { 189250757Sjkim thread_lock(td); 190250757Sjkim switch (TD_GET_STATE(td)) { 191250757Sjkim case TDS_INHIBITED: 192250757Sjkim if (TD_IS_SWAPPED(td)) 193250757Sjkim total.t_sw++; 194250757Sjkim else if (TD_IS_SLEEPING(td)) { 195250757Sjkim if (td->td_priority <= PZERO) 196250757Sjkim total.t_dw++; 197250757Sjkim else 198250757Sjkim total.t_sl++; 199250757Sjkim } 200250757Sjkim break; 201250757Sjkim case TDS_CAN_RUN: 202250757Sjkim total.t_sw++; 203250757Sjkim break; 204250757Sjkim case TDS_RUNQ: 205250757Sjkim case TDS_RUNNING: 206250757Sjkim total.t_rq++; 207250757Sjkim break; 208250757Sjkim default: 209250757Sjkim break; 210250757Sjkim } 211250757Sjkim thread_unlock(td); 212250757Sjkim } 213250757Sjkim } 214250757Sjkim PROC_UNLOCK(p); 215250757Sjkim } 216250757Sjkim sx_sunlock(&allproc_lock); 217250757Sjkim /* 218250757Sjkim * Calculate object memory usage statistics. 219250757Sjkim */ 220250757Sjkim mtx_lock(&vm_object_list_mtx); 221250757Sjkim TAILQ_FOREACH(object, &vm_object_list, object_list) { 222250757Sjkim /* 223250757Sjkim * Perform unsynchronized reads on the object. In 224250757Sjkim * this case, the lack of synchronization should not 225250757Sjkim * impair the accuracy of the reported statistics. 226250757Sjkim */ 227250757Sjkim if ((object->flags & OBJ_FICTITIOUS) != 0) { 228250757Sjkim /* 229250757Sjkim * Devices, like /dev/mem, will badly skew our totals. 230250757Sjkim */ 231250757Sjkim continue; 232250757Sjkim } 233250757Sjkim if (object->ref_count == 0) { 234250757Sjkim /* 235250757Sjkim * Also skip unreferenced objects, including 236250757Sjkim * vnodes representing mounted file systems. 237250757Sjkim */ 238250757Sjkim continue; 239250757Sjkim } 240250757Sjkim if (object->ref_count == 1 && 241250757Sjkim (object->flags & (OBJ_ANON | OBJ_SWAP)) == OBJ_SWAP) { 242250757Sjkim /* 243250757Sjkim * Also skip otherwise unreferenced swap 244250757Sjkim * objects backing tmpfs vnodes, and POSIX or 245250757Sjkim * SysV shared memory. 246250757Sjkim */ 247250757Sjkim continue; 248250757Sjkim } 249250757Sjkim total.t_vm += object->size; 250250757Sjkim total.t_rm += object->resident_page_count; 251250757Sjkim if (vm_object_is_active(object)) { 252250757Sjkim total.t_avm += object->size; 253250757Sjkim total.t_arm += object->resident_page_count; 254250757Sjkim } 255250757Sjkim if (object->shadow_count > 1) { 256250757Sjkim /* shared object */ 257250757Sjkim total.t_vmshr += object->size; 258250757Sjkim total.t_rmshr += object->resident_page_count; 259250757Sjkim if (vm_object_is_active(object)) { 260250757Sjkim total.t_avmshr += object->size; 261250757Sjkim total.t_armshr += object->resident_page_count; 262250757Sjkim } 263250757Sjkim } 264250757Sjkim } 265250757Sjkim mtx_unlock(&vm_object_list_mtx); 266250757Sjkim total.t_pw = vm_wait_count(); 267250757Sjkim total.t_free = vm_free_count(); 268250757Sjkim#if defined(COMPAT_FREEBSD11) 269250757Sjkim /* sysctl(8) allocates twice as much memory as reported by sysctl(3) */ 270250757Sjkim if (curproc->p_osrel < P_OSREL_VMTOTAL64 && (req->oldlen == 271250757Sjkim sizeof(total11) || req->oldlen == 2 * sizeof(total11))) { 272250757Sjkim bzero(&total11, sizeof(total11)); 273250757Sjkim total11.t_rq = total.t_rq; 274250757Sjkim total11.t_dw = total.t_dw; 275250757Sjkim total11.t_pw = total.t_pw; 276250757Sjkim total11.t_sl = total.t_sl; 277250757Sjkim total11.t_sw = total.t_sw; 278250757Sjkim total11.t_vm = total.t_vm; /* truncate */ 279250757Sjkim total11.t_avm = total.t_avm; /* truncate */ 280250757Sjkim total11.t_rm = total.t_rm; /* truncate */ 281250757Sjkim total11.t_arm = total.t_arm; /* truncate */ 282250757Sjkim total11.t_vmshr = total.t_vmshr; /* truncate */ 283250757Sjkim total11.t_avmshr = total.t_avmshr; /* truncate */ 284250757Sjkim total11.t_rmshr = total.t_rmshr; /* truncate */ 285250757Sjkim total11.t_armshr = total.t_armshr; /* truncate */ 286250757Sjkim total11.t_free = total.t_free; /* truncate */ 287250757Sjkim return (SYSCTL_OUT(req, &total11, sizeof(total11))); 288250757Sjkim } 289250757Sjkim#endif 290250757Sjkim return (SYSCTL_OUT(req, &total, sizeof(total))); 291250757Sjkim} 292250757Sjkim 293250757SjkimSYSCTL_PROC(_vm, VM_TOTAL, vmtotal, CTLTYPE_OPAQUE | CTLFLAG_RD | 294250757Sjkim CTLFLAG_MPSAFE, NULL, 0, vmtotal, "S,vmtotal", 295250757Sjkim "System virtual memory statistics"); 296250757SjkimSYSCTL_NODE(_vm, OID_AUTO, stats, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 297250757Sjkim "VM meter stats"); 298250757Sjkimstatic SYSCTL_NODE(_vm_stats, OID_AUTO, sys, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 299250757Sjkim "VM meter sys stats"); 300250757Sjkimstatic SYSCTL_NODE(_vm_stats, OID_AUTO, vm, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 301250757Sjkim "VM meter vm stats"); 302250757SjkimSYSCTL_NODE(_vm_stats, OID_AUTO, misc, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 303250757Sjkim "VM meter misc stats"); 304250757Sjkim 305250757Sjkimstatic int 306250757Sjkimsysctl_handle_vmstat(SYSCTL_HANDLER_ARGS) 307250757Sjkim{ 308250757Sjkim uint64_t val; 309250757Sjkim#ifdef COMPAT_FREEBSD11 310250757Sjkim uint32_t val32; 311250757Sjkim#endif 312250757Sjkim 313250757Sjkim val = counter_u64_fetch(*(counter_u64_t *)arg1); 314250757Sjkim#ifdef COMPAT_FREEBSD11 315250757Sjkim if (req->oldlen == sizeof(val32)) { 316250757Sjkim val32 = val; /* truncate */ 317250757Sjkim return (SYSCTL_OUT(req, &val32, sizeof(val32))); 318250757Sjkim } 319250757Sjkim#endif 320250757Sjkim return (SYSCTL_OUT(req, &val, sizeof(val))); 321250757Sjkim} 322250757Sjkim 323250757Sjkim#define VM_STATS(parent, var, descr) \ 324250757Sjkim SYSCTL_OID(parent, OID_AUTO, var, CTLTYPE_U64 | CTLFLAG_MPSAFE | \ 325250757Sjkim CTLFLAG_RD, &vm_cnt.var, 0, sysctl_handle_vmstat, "QU", descr) 326250757Sjkim#define VM_STATS_VM(var, descr) VM_STATS(_vm_stats_vm, var, descr) 327250757Sjkim#define VM_STATS_SYS(var, descr) VM_STATS(_vm_stats_sys, var, descr) 328250757Sjkim 329250757SjkimVM_STATS_SYS(v_swtch, "Context switches"); 330250757SjkimVM_STATS_SYS(v_trap, "Traps"); 331250757SjkimVM_STATS_SYS(v_syscall, "System calls"); 332250757SjkimVM_STATS_SYS(v_intr, "Device interrupts"); 333250757SjkimVM_STATS_SYS(v_soft, "Software interrupts"); 334250757SjkimVM_STATS_VM(v_vm_faults, "Address memory faults"); 335250757SjkimVM_STATS_VM(v_io_faults, "Page faults requiring I/O"); 336250757SjkimVM_STATS_VM(v_cow_faults, "Copy-on-write faults"); 337250757SjkimVM_STATS_VM(v_cow_optim, "Optimized COW faults"); 338250757SjkimVM_STATS_VM(v_zfod, "Pages zero-filled on demand"); 339250757SjkimVM_STATS_VM(v_ozfod, "Optimized zero fill pages"); 340250757SjkimVM_STATS_VM(v_swapin, "Swap pager pageins"); 341250757SjkimVM_STATS_VM(v_swapout, "Swap pager pageouts"); 342250757SjkimVM_STATS_VM(v_swappgsin, "Swap pages swapped in"); 343250757SjkimVM_STATS_VM(v_swappgsout, "Swap pages swapped out"); 344250757SjkimVM_STATS_VM(v_vnodein, "Vnode pager pageins"); 345250757SjkimVM_STATS_VM(v_vnodeout, "Vnode pager pageouts"); 346250757SjkimVM_STATS_VM(v_vnodepgsin, "Vnode pages paged in"); 347250757SjkimVM_STATS_VM(v_vnodepgsout, "Vnode pages paged out"); 348250757SjkimVM_STATS_VM(v_intrans, "In transit page faults"); 349250757SjkimVM_STATS_VM(v_reactivated, "Pages reactivated by pagedaemon"); 350250757SjkimVM_STATS_VM(v_pdwakeups, "Pagedaemon wakeups"); 351250757SjkimVM_STATS_VM(v_pdshortfalls, "Page reclamation shortfalls"); 352250757SjkimVM_STATS_VM(v_dfree, "Pages freed by pagedaemon"); 353250757SjkimVM_STATS_VM(v_pfree, "Pages freed by exiting processes"); 354250757SjkimVM_STATS_VM(v_tfree, "Total pages freed"); 355250757SjkimVM_STATS_VM(v_forks, "Number of fork() calls"); 356250757SjkimVM_STATS_VM(v_vforks, "Number of vfork() calls"); 357250757SjkimVM_STATS_VM(v_rforks, "Number of rfork() calls"); 358250757SjkimVM_STATS_VM(v_kthreads, "Number of fork() calls by kernel"); 359250757SjkimVM_STATS_VM(v_forkpages, "VM pages affected by fork()"); 360250757SjkimVM_STATS_VM(v_vforkpages, "VM pages affected by vfork()"); 361250757SjkimVM_STATS_VM(v_rforkpages, "VM pages affected by rfork()"); 362250757SjkimVM_STATS_VM(v_kthreadpages, "VM pages affected by fork() by kernel"); 363250757Sjkim 364250757Sjkimstatic int 365250757Sjkimsysctl_handle_vmstat_proc(SYSCTL_HANDLER_ARGS) 366250757Sjkim{ 367250757Sjkim u_int (*fn)(void); 368250757Sjkim uint32_t val; 369250757Sjkim 370250757Sjkim fn = arg1; 371250757Sjkim val = fn(); 372250757Sjkim return (SYSCTL_OUT(req, &val, sizeof(val))); 373250757Sjkim} 374250757Sjkim 375250757Sjkim#define VM_STATS_PROC(var, descr, fn) \ 376250757Sjkim SYSCTL_OID(_vm_stats_vm, OID_AUTO, var, CTLTYPE_U32 | CTLFLAG_MPSAFE | \ 377250757Sjkim CTLFLAG_RD, fn, 0, sysctl_handle_vmstat_proc, "IU", descr) 378250757Sjkim 379250757Sjkim#define VM_STATS_UINT(var, descr) \ 380250757Sjkim SYSCTL_UINT(_vm_stats_vm, OID_AUTO, var, CTLFLAG_RD, &vm_cnt.var, 0, descr) 381250757Sjkim#define VM_STATS_ULONG(var, descr) \ 382250757Sjkim SYSCTL_ULONG(_vm_stats_vm, OID_AUTO, var, CTLFLAG_RD, &vm_cnt.var, 0, descr) 383250757Sjkim 384250757SjkimVM_STATS_UINT(v_page_size, "Page size in bytes"); 385250757SjkimVM_STATS_UINT(v_page_count, "Total number of pages in system"); 386250757SjkimVM_STATS_UINT(v_free_reserved, "Pages reserved for deadlock"); 387250757SjkimVM_STATS_UINT(v_free_target, "Pages desired free"); 388250757SjkimVM_STATS_UINT(v_free_min, "Minimum low-free-pages threshold"); 389250757SjkimVM_STATS_PROC(v_free_count, "Free pages", vm_free_count); 390250757SjkimVM_STATS_PROC(v_wire_count, "Wired pages", vm_wire_count); 391250757SjkimVM_STATS_PROC(v_active_count, "Active pages", vm_active_count); 392250757SjkimVM_STATS_UINT(v_inactive_target, "Desired inactive pages"); 393250757SjkimVM_STATS_PROC(v_inactive_count, "Inactive pages", vm_inactive_count); 394250757SjkimVM_STATS_PROC(v_laundry_count, "Pages eligible for laundering", 395250757Sjkim vm_laundry_count); 396250757SjkimVM_STATS_UINT(v_pageout_free_min, "Min pages reserved for kernel"); 397250757SjkimVM_STATS_UINT(v_interrupt_free_min, "Reserved pages for interrupt code"); 398250757SjkimVM_STATS_UINT(v_free_severe, "Severe page depletion point"); 399250757Sjkim 400250757SjkimSYSCTL_ULONG(_vm_stats_vm, OID_AUTO, v_user_wire_count, CTLFLAG_RD, 401250757Sjkim &vm_user_wire_count, 0, "User-wired virtual memory"); 402250757Sjkim 403250757Sjkim#ifdef COMPAT_FREEBSD11 404250757Sjkim/* 405250757Sjkim * Provide compatibility sysctls for the benefit of old utilities which exit 406250757Sjkim * with an error if they cannot be found. 407250757Sjkim */ 408250757SjkimSYSCTL_UINT(_vm_stats_vm, OID_AUTO, v_cache_count, CTLFLAG_RD, 409250757Sjkim SYSCTL_NULL_UINT_PTR, 0, "Dummy for compatibility"); 410250757SjkimSYSCTL_UINT(_vm_stats_vm, OID_AUTO, v_tcached, CTLFLAG_RD, 411250757Sjkim SYSCTL_NULL_UINT_PTR, 0, "Dummy for compatibility"); 412250757Sjkim#endif 413250757Sjkim 414250757Sjkimu_int 415250757Sjkimvm_free_count(void) 416250757Sjkim{ 417250757Sjkim u_int v; 418250757Sjkim int i; 419250757Sjkim 420250757Sjkim v = 0; 421250757Sjkim for (i = 0; i < vm_ndomains; i++) 422250757Sjkim v += vm_dom[i].vmd_free_count; 423250757Sjkim 424250757Sjkim return (v); 425250757Sjkim} 426250757Sjkim 427250757Sjkimstatic u_int 428250757Sjkimvm_pagequeue_count(int pq) 429250757Sjkim{ 430250757Sjkim u_int v; 431250757Sjkim int i; 432250757Sjkim 433250757Sjkim v = 0; 434250757Sjkim for (i = 0; i < vm_ndomains; i++) 435250757Sjkim v += vm_dom[i].vmd_pagequeues[pq].pq_cnt; 436250757Sjkim 437250757Sjkim return (v); 438250757Sjkim} 439250757Sjkim 440250757Sjkimu_int 441250757Sjkimvm_active_count(void) 442250757Sjkim{ 443250757Sjkim 444250757Sjkim return (vm_pagequeue_count(PQ_ACTIVE)); 445250757Sjkim} 446250757Sjkim 447250757Sjkimu_int 448250757Sjkimvm_inactive_count(void) 449250757Sjkim{ 450250757Sjkim 451250757Sjkim return (vm_pagequeue_count(PQ_INACTIVE)); 452250757Sjkim} 453250757Sjkim 454250757Sjkimu_int 455250757Sjkimvm_laundry_count(void) 456250757Sjkim{ 457250757Sjkim 458250757Sjkim return (vm_pagequeue_count(PQ_LAUNDRY)); 459250757Sjkim} 460250757Sjkim 461250757Sjkimstatic int 462250757Sjkimsysctl_vm_pdpages(SYSCTL_HANDLER_ARGS) 463250757Sjkim{ 464250757Sjkim struct vm_pagequeue *pq; 465250757Sjkim uint64_t ret; 466250757Sjkim int dom, i; 467250757Sjkim 468250757Sjkim ret = counter_u64_fetch(vm_cnt.v_pdpages); 469250757Sjkim for (dom = 0; dom < vm_ndomains; dom++) 470250757Sjkim for (i = 0; i < PQ_COUNT; i++) { 471250757Sjkim pq = &VM_DOMAIN(dom)->vmd_pagequeues[i]; 472250757Sjkim ret += pq->pq_pdpages; 473250757Sjkim } 474250757Sjkim return (SYSCTL_OUT(req, &ret, sizeof(ret))); 475250757Sjkim} 476250757SjkimSYSCTL_PROC(_vm_stats_vm, OID_AUTO, v_pdpages, 477250757Sjkim CTLTYPE_U64 | CTLFLAG_MPSAFE | CTLFLAG_RD, NULL, 0, sysctl_vm_pdpages, "QU", 478250757Sjkim "Pages analyzed by pagedaemon"); 479250757Sjkim 480250757Sjkimstatic void 481250757Sjkimvm_domain_stats_init(struct vm_domain *vmd, struct sysctl_oid *parent) 482250757Sjkim{ 483250757Sjkim struct sysctl_oid *oid; 484250757Sjkim 485250757Sjkim vmd->vmd_oid = SYSCTL_ADD_NODE(NULL, SYSCTL_CHILDREN(parent), OID_AUTO, 486250757Sjkim vmd->vmd_name, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, ""); 487250757Sjkim oid = SYSCTL_ADD_NODE(NULL, SYSCTL_CHILDREN(vmd->vmd_oid), OID_AUTO, 488250757Sjkim "stats", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, ""); 489250757Sjkim SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(oid), OID_AUTO, 490250757Sjkim "free_count", CTLFLAG_RD, &vmd->vmd_free_count, 0, 491250757Sjkim "Free pages"); 492250757Sjkim SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(oid), OID_AUTO, 493250757Sjkim "active", CTLFLAG_RD, &vmd->vmd_pagequeues[PQ_ACTIVE].pq_cnt, 0, 494250757Sjkim "Active pages"); 495250757Sjkim SYSCTL_ADD_U64(NULL, SYSCTL_CHILDREN(oid), OID_AUTO, 496250757Sjkim "actpdpgs", CTLFLAG_RD, 497250757Sjkim &vmd->vmd_pagequeues[PQ_ACTIVE].pq_pdpages, 0, 498250757Sjkim "Active pages scanned by the page daemon"); 499250757Sjkim SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(oid), OID_AUTO, 500250757Sjkim "inactive", CTLFLAG_RD, &vmd->vmd_pagequeues[PQ_INACTIVE].pq_cnt, 0, 501250757Sjkim "Inactive pages"); 502250757Sjkim SYSCTL_ADD_U64(NULL, SYSCTL_CHILDREN(oid), OID_AUTO, 503250757Sjkim "inactpdpgs", CTLFLAG_RD, 504250757Sjkim &vmd->vmd_pagequeues[PQ_INACTIVE].pq_pdpages, 0, 505250757Sjkim "Inactive pages scanned by the page daemon"); 506250757Sjkim SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(oid), OID_AUTO, 507250757Sjkim "laundry", CTLFLAG_RD, &vmd->vmd_pagequeues[PQ_LAUNDRY].pq_cnt, 0, 508250757Sjkim "laundry pages"); 509250757Sjkim SYSCTL_ADD_U64(NULL, SYSCTL_CHILDREN(oid), OID_AUTO, 510250757Sjkim "laundpdpgs", CTLFLAG_RD, 511250757Sjkim &vmd->vmd_pagequeues[PQ_LAUNDRY].pq_pdpages, 0, 512250757Sjkim "Laundry pages scanned by the page daemon"); 513250757Sjkim SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(oid), OID_AUTO, "unswappable", 514250757Sjkim CTLFLAG_RD, &vmd->vmd_pagequeues[PQ_UNSWAPPABLE].pq_cnt, 0, 515250757Sjkim "Unswappable pages"); 516250757Sjkim SYSCTL_ADD_U64(NULL, SYSCTL_CHILDREN(oid), OID_AUTO, 517250757Sjkim "unswppdpgs", CTLFLAG_RD, 518250757Sjkim &vmd->vmd_pagequeues[PQ_UNSWAPPABLE].pq_pdpages, 0, 519250757Sjkim "Unswappable pages scanned by the page daemon"); 520250757Sjkim SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(oid), OID_AUTO, 521250757Sjkim "inactive_target", CTLFLAG_RD, &vmd->vmd_inactive_target, 0, 522250757Sjkim "Target inactive pages"); 523250757Sjkim SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(oid), OID_AUTO, 524250757Sjkim "free_target", CTLFLAG_RD, &vmd->vmd_free_target, 0, 525250757Sjkim "Target free pages"); 526250757Sjkim SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(oid), OID_AUTO, 527250757Sjkim "free_reserved", CTLFLAG_RD, &vmd->vmd_free_reserved, 0, 528250757Sjkim "Reserved free pages"); 529250757Sjkim SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(oid), OID_AUTO, 530250757Sjkim "free_min", CTLFLAG_RD, &vmd->vmd_free_min, 0, 531250757Sjkim "Minimum free pages"); 532250757Sjkim SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(oid), OID_AUTO, 533250757Sjkim "free_severe", CTLFLAG_RD, &vmd->vmd_free_severe, 0, 534250757Sjkim "Severe free pages"); 535250757Sjkim SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(oid), OID_AUTO, 536250757Sjkim "inactive_pps", CTLFLAG_RD, &vmd->vmd_inactive_pps, 0, 537250757Sjkim "inactive pages freed/second"); 538250757Sjkim 539250757Sjkim} 540250757Sjkim 541250757Sjkimstatic void 542250757Sjkimvm_stats_init(void *arg __unused) 543250757Sjkim{ 544250757Sjkim struct sysctl_oid *oid; 545250757Sjkim int i; 546250757Sjkim 547250757Sjkim oid = SYSCTL_ADD_NODE(NULL, SYSCTL_STATIC_CHILDREN(_vm), OID_AUTO, 548250757Sjkim "domain", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, ""); 549250757Sjkim for (i = 0; i < vm_ndomains; i++) 550250757Sjkim vm_domain_stats_init(VM_DOMAIN(i), oid); 551250757Sjkim} 552250757Sjkim 553250757SjkimSYSINIT(vmstats_init, SI_SUB_VM_CONF, SI_ORDER_FIRST, vm_stats_init, NULL); 554250757Sjkim