1 /*- 2 * Copyright (c) 2000 Dag-Erling Co�dan Sm�rgrav 3 * Copyright (c) 1999 Pierre Beyssac 4 * Copyright (c) 1993 Jan-Simon Pendry 5 * Copyright (c) 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Jan-Simon Pendry. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * @(#)procfs_status.c 8.4 (Berkeley) 6/15/94 40 */ 41 42 #include <sys/cdefs.h> 43 __FBSDID("$FreeBSD$"); 44 45 #include <sys/param.h> 46 #include <sys/queue.h> 47 #include <sys/blist.h> 48 #include <sys/conf.h> 49 #include <sys/exec.h> 50 #include <sys/filedesc.h> 51 #include <sys/jail.h> 52 #include <sys/kernel.h> 53 #include <sys/linker.h> 54 #include <sys/lock.h> 55 #include <sys/malloc.h> 56 #include <sys/mount.h> 57 #include <sys/mutex.h> 58 #include <sys/namei.h> 59 #include <sys/proc.h> 60 #include <sys/resourcevar.h> 61 #include <sys/sbuf.h> 62 #include <sys/smp.h> 63 #include <sys/socket.h> 64 #include <sys/sysctl.h> 65 #include <sys/systm.h> 66 #include <sys/time.h> 67 #include <sys/tty.h> 68 #include <sys/user.h> 69 #include <sys/vmmeter.h> 70 #include <sys/vnode.h> 71 72 #include <net/if.h> 73 74 #include <vm/vm.h> 75 #include <vm/pmap.h> 76 #include <vm/vm_map.h> 77 #include <vm/vm_param.h> 78 #include <vm/vm_object.h> 79 #include <vm/swap_pager.h> 80 81 #include <machine/clock.h> 82 83 #if defined(__i386__) || defined(__amd64__) 84 #include <machine/cputypes.h> 85 #include <machine/md_var.h> 86 #endif /* __i386__ || __amd64__ */ 87 88 #include "opt_compat.h" 89 #ifdef COMPAT_LINUX32 /* XXX */ 90 #include <machine/../linux32/linux.h> 91 #else 92 #include <machine/../linux/linux.h> 93 #endif 94 #include <compat/linux/linux_ioctl.h> 95 #include <compat/linux/linux_mib.h> 96 #include <compat/linux/linux_util.h> 97 #include <fs/pseudofs/pseudofs.h> 98 #include <fs/procfs/procfs.h> 99 100 /* 101 * Various conversion macros 102 */ 103 #define T2J(x) (((x) * 100UL) / (stathz ? stathz : hz)) /* ticks to jiffies */ 104 #define T2S(x) ((x) / (stathz ? stathz : hz)) /* ticks to seconds */ 105 #define B2K(x) ((x) >> 10) /* bytes to kbytes */ 106 #define B2P(x) ((x) >> PAGE_SHIFT) /* bytes to pages */ 107 #define P2B(x) ((x) << PAGE_SHIFT) /* pages to bytes */ 108 #define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */ 109 110 /** 111 * @brief Mapping of ki_stat in struct kinfo_proc to the linux state 112 * 113 * The linux procfs state field displays one of the characters RSDZTW to 114 * denote running, sleeping in an interruptible wait, waiting in an 115 * uninteruptible disk sleep, a zombie process, process is being traced 116 * or stopped, or process is paging respectively. 117 * 118 * Our struct kinfo_proc contains the variable ki_stat which contains a 119 * value out of SIDL, SRUN, SSLEEP, SSTOP, SZOMB, SWAIT and SLOCK. 120 * 121 * This character array is used with ki_stati-1 as an index and tries to 122 * map our states to suitable linux states. 123 */ 124 static char linux_state[] = "RRSTZDD"; 125 126 /* 127 * Filler function for proc/meminfo 128 */ 129 static int 130 linprocfs_domeminfo(PFS_FILL_ARGS) 131 { 132 unsigned long memtotal; /* total memory in bytes */ 133 unsigned long memused; /* used memory in bytes */ 134 unsigned long memfree; /* free memory in bytes */ 135 unsigned long memshared; /* shared memory ??? */ 136 unsigned long buffers, cached; /* buffer / cache memory ??? */ 137 unsigned long long swaptotal; /* total swap space in bytes */ 138 unsigned long long swapused; /* used swap space in bytes */ 139 unsigned long long swapfree; /* free swap space in bytes */ 140 vm_object_t object; 141 int i, j; 142 143 memtotal = physmem * PAGE_SIZE; 144 /* 145 * The correct thing here would be: 146 * 147 memfree = cnt.v_free_count * PAGE_SIZE; 148 memused = memtotal - memfree; 149 * 150 * but it might mislead linux binaries into thinking there 151 * is very little memory left, so we cheat and tell them that 152 * all memory that isn't wired down is free. 153 */ 154 memused = cnt.v_wire_count * PAGE_SIZE; 155 memfree = memtotal - memused; 156 swap_pager_status(&i, &j); 157 swaptotal = (unsigned long long)i * PAGE_SIZE; 158 swapused = (unsigned long long)j * PAGE_SIZE; 159 swapfree = swaptotal - swapused; 160 memshared = 0; 161 mtx_lock(&vm_object_list_mtx); 162 TAILQ_FOREACH(object, &vm_object_list, object_list) 163 if (object->shadow_count > 1) 164 memshared += object->resident_page_count; 165 mtx_unlock(&vm_object_list_mtx); 166 memshared *= PAGE_SIZE; 167 /* 168 * We'd love to be able to write: 169 * 170 buffers = bufspace; 171 * 172 * but bufspace is internal to vfs_bio.c and we don't feel 173 * like unstaticizing it just for linprocfs's sake. 174 */ 175 buffers = 0; 176 cached = cnt.v_cache_count * PAGE_SIZE; 177 178 sbuf_printf(sb, 179 " total: used: free: shared: buffers: cached:\n" 180 "Mem: %lu %lu %lu %lu %lu %lu\n" 181 "Swap: %llu %llu %llu\n" 182 "MemTotal: %9lu kB\n" 183 "MemFree: %9lu kB\n" 184 "MemShared:%9lu kB\n" 185 "Buffers: %9lu kB\n" 186 "Cached: %9lu kB\n" 187 "SwapTotal:%9llu kB\n" 188 "SwapFree: %9llu kB\n", 189 memtotal, memused, memfree, memshared, buffers, cached, 190 swaptotal, swapused, swapfree, 191 B2K(memtotal), B2K(memfree), 192 B2K(memshared), B2K(buffers), B2K(cached), 193 B2K(swaptotal), B2K(swapfree)); 194 195 return (0); 196 } 197 198 #if defined(__i386__) || defined(__amd64__) 199 /* 200 * Filler function for proc/cpuinfo (i386 & amd64 version) 201 */ 202 static int 203 linprocfs_docpuinfo(PFS_FILL_ARGS) 204 { 205 int hw_model[2]; 206 char model[128]; 207 size_t size; 208 int class, fqmhz, fqkhz; 209 int i; 210 211 /* 212 * We default the flags to include all non-conflicting flags, 213 * and the Intel versions of conflicting flags. 214 */ 215 static char *flags[] = { 216 "fpu", "vme", "de", "pse", "tsc", 217 "msr", "pae", "mce", "cx8", "apic", 218 "sep", "sep", "mtrr", "pge", "mca", 219 "cmov", "pat", "pse36", "pn", "b19", 220 "b20", "b21", "mmxext", "mmx", "fxsr", 221 "xmm", "b26", "b27", "b28", "b29", 222 "3dnowext", "3dnow" 223 }; 224 225 switch (cpu_class) { 226 #ifdef __i386__ 227 case CPUCLASS_286: 228 class = 2; 229 break; 230 case CPUCLASS_386: 231 class = 3; 232 break; 233 case CPUCLASS_486: 234 class = 4; 235 break; 236 case CPUCLASS_586: 237 class = 5; 238 break; 239 case CPUCLASS_686: 240 class = 6; 241 break; 242 default: 243 class = 0; 244 break; 245 #else /* __amd64__ */ 246 default: 247 class = 15; 248 break; 249 #endif 250 } 251 252 hw_model[0] = CTL_HW; 253 hw_model[1] = HW_MODEL; 254 model[0] = '\0'; 255 size = sizeof(model); 256 if (kernel_sysctl(td, hw_model, 2, &model, &size, 0, 0, 0, 0) != 0) 257 strcpy(model, "unknown"); 258 for (i = 0; i < mp_ncpus; ++i) { 259 sbuf_printf(sb, 260 "processor\t: %d\n" 261 "vendor_id\t: %.20s\n" 262 "cpu family\t: %d\n" 263 "model\t\t: %d\n" 264 "model name\t: %s\n" 265 "stepping\t: %d\n", 266 i, cpu_vendor, class, cpu, model, cpu_id & 0xf); 267 /* XXX per-cpu vendor / class / model / id? */ 268 } 269 270 sbuf_cat(sb, 271 "flags\t\t:"); 272 273 if (!strcmp(cpu_vendor, "AuthenticAMD") && (class < 6)) { 274 flags[16] = "fcmov"; 275 } else if (!strcmp(cpu_vendor, "CyrixInstead")) { 276 flags[24] = "cxmmx"; 277 } 278 279 for (i = 0; i < 32; i++) 280 if (cpu_feature & (1 << i)) 281 sbuf_printf(sb, " %s", flags[i]); 282 sbuf_cat(sb, "\n"); 283 if (class >= 5) { 284 fqmhz = (tsc_freq + 4999) / 1000000; 285 fqkhz = ((tsc_freq + 4999) / 10000) % 100; 286 sbuf_printf(sb, 287 "cpu MHz\t\t: %d.%02d\n" 288 "bogomips\t: %d.%02d\n", 289 fqmhz, fqkhz, fqmhz, fqkhz); 290 } 291 292 return (0); 293 } 294 #endif /* __i386__ || __amd64__ */ 295 296 /* 297 * Filler function for proc/mtab 298 * 299 * This file doesn't exist in Linux' procfs, but is included here so 300 * users can symlink /compat/linux/etc/mtab to /proc/mtab 301 */ 302 static int 303 linprocfs_domtab(PFS_FILL_ARGS) 304 { 305 struct nameidata nd; 306 struct mount *mp; 307 const char *lep; 308 char *dlep, *flep, *mntto, *mntfrom, *fstype; 309 size_t lep_len; 310 int error; 311 312 /* resolve symlinks etc. in the emulation tree prefix */ 313 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, td); 314 flep = NULL; 315 if (namei(&nd) != 0 || vn_fullpath(td, nd.ni_vp, &dlep, &flep) != 0) 316 lep = linux_emul_path; 317 else 318 lep = dlep; 319 lep_len = strlen(lep); 320 321 mtx_lock(&mountlist_mtx); 322 error = 0; 323 TAILQ_FOREACH(mp, &mountlist, mnt_list) { 324 /* determine device name */ 325 mntfrom = mp->mnt_stat.f_mntfromname; 326 327 /* determine mount point */ 328 mntto = mp->mnt_stat.f_mntonname; 329 if (strncmp(mntto, lep, lep_len) == 0 && 330 mntto[lep_len] == '/') 331 mntto += lep_len; 332 333 /* determine fs type */ 334 fstype = mp->mnt_stat.f_fstypename; 335 if (strcmp(fstype, pn->pn_info->pi_name) == 0) 336 mntfrom = fstype = "proc"; 337 else if (strcmp(fstype, "procfs") == 0) 338 continue; 339 340 if (strcmp(fstype, "linsysfs") == 0) { 341 sbuf_printf(sb, "/sys %s sysfs %s", mntto, 342 mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw"); 343 } else { 344 sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype, 345 mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw"); 346 } 347 #define ADD_OPTION(opt, name) \ 348 if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name); 349 ADD_OPTION(MNT_SYNCHRONOUS, "sync"); 350 ADD_OPTION(MNT_NOEXEC, "noexec"); 351 ADD_OPTION(MNT_NOSUID, "nosuid"); 352 ADD_OPTION(MNT_UNION, "union"); 353 ADD_OPTION(MNT_ASYNC, "async"); 354 ADD_OPTION(MNT_SUIDDIR, "suiddir"); 355 ADD_OPTION(MNT_NOSYMFOLLOW, "nosymfollow"); 356 ADD_OPTION(MNT_NOATIME, "noatime"); 357 #undef ADD_OPTION 358 /* a real Linux mtab will also show NFS options */ 359 sbuf_printf(sb, " 0 0\n"); 360 } 361 mtx_unlock(&mountlist_mtx); 362 if (flep != NULL) 363 free(flep, M_TEMP); 364 return (error); 365 } 366 367 /* 368 * Filler function for proc/stat 369 */ 370 static int 371 linprocfs_dostat(PFS_FILL_ARGS) 372 { 373 int i; 374 375 sbuf_printf(sb, "cpu %ld %ld %ld %ld\n", 376 T2J(cp_time[CP_USER]), 377 T2J(cp_time[CP_NICE]), 378 T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/), 379 T2J(cp_time[CP_IDLE])); 380 for (i = 0; i < mp_ncpus; ++i) 381 sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i, 382 T2J(cp_time[CP_USER]) / mp_ncpus, 383 T2J(cp_time[CP_NICE]) / mp_ncpus, 384 T2J(cp_time[CP_SYS]) / mp_ncpus, 385 T2J(cp_time[CP_IDLE]) / mp_ncpus); 386 sbuf_printf(sb, 387 "disk 0 0 0 0\n" 388 "page %u %u\n" 389 "swap %u %u\n" 390 "intr %u\n" 391 "ctxt %u\n" 392 "btime %lld\n", 393 cnt.v_vnodepgsin, 394 cnt.v_vnodepgsout, 395 cnt.v_swappgsin, 396 cnt.v_swappgsout, 397 cnt.v_intr, 398 cnt.v_swtch, 399 (long long)boottime.tv_sec); 400 return (0); 401 } 402 403 /* 404 * Filler function for proc/uptime 405 */ 406 static int 407 linprocfs_douptime(PFS_FILL_ARGS) 408 { 409 struct timeval tv; 410 411 getmicrouptime(&tv); 412 sbuf_printf(sb, "%lld.%02ld %ld.%02ld\n", 413 (long long)tv.tv_sec, tv.tv_usec / 10000, 414 T2S(cp_time[CP_IDLE]), T2J(cp_time[CP_IDLE]) % 100); 415 return (0); 416 } 417 418 /* 419 * Filler function for proc/version 420 */ 421 static int 422 linprocfs_doversion(PFS_FILL_ARGS) 423 { 424 char osname[LINUX_MAX_UTSNAME]; 425 char osrelease[LINUX_MAX_UTSNAME]; 426 427 linux_get_osname(td, osname); 428 linux_get_osrelease(td, osrelease); 429 430 sbuf_printf(sb, 431 "%s version %s (des@freebsd.org) (gcc version " __VERSION__ ")" 432 " #4 Sun Dec 18 04:30:00 CET 1977\n", osname, osrelease); 433 return (0); 434 } 435 436 /* 437 * Filler function for proc/loadavg 438 */ 439 static int 440 linprocfs_doloadavg(PFS_FILL_ARGS) 441 { 442 sbuf_printf(sb, 443 "%d.%02d %d.%02d %d.%02d %d/%d %d\n", 444 (int)(averunnable.ldavg[0] / averunnable.fscale), 445 (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100), 446 (int)(averunnable.ldavg[1] / averunnable.fscale), 447 (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100), 448 (int)(averunnable.ldavg[2] / averunnable.fscale), 449 (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100), 450 1, /* number of running tasks */ 451 nprocs, /* number of tasks */ 452 lastpid /* the last pid */ 453 ); 454 455 return (0); 456 } 457 458 /* 459 * Filler function for proc/pid/stat 460 */ 461 static int 462 linprocfs_doprocstat(PFS_FILL_ARGS) 463 { 464 struct kinfo_proc kp; 465 char state; 466 static int ratelimit = 0; 467 468 PROC_LOCK(p); 469 fill_kinfo_proc(p, &kp); 470 sbuf_printf(sb, "%d", p->p_pid); 471 #define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg) 472 PS_ADD("comm", "(%s)", p->p_comm); 473 if (kp.ki_stat > sizeof(linux_state)) { 474 state = 'R'; 475 476 if (ratelimit == 0) { 477 printf("linprocfs: don't know how to handle unknown FreeBSD state %d/%zd, mapping to R\n", 478 kp.ki_stat, sizeof(linux_state)); 479 ++ratelimit; 480 } 481 } else 482 state = linux_state[kp.ki_stat - 1]; 483 PS_ADD("state", "%c", state); 484 PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0); 485 PS_ADD("pgrp", "%d", p->p_pgid); 486 PS_ADD("session", "%d", p->p_session->s_sid); 487 PROC_UNLOCK(p); 488 PS_ADD("tty", "%d", 0); /* XXX */ 489 PS_ADD("tpgid", "%d", kp.ki_tpgid); 490 PS_ADD("flags", "%u", 0); /* XXX */ 491 PS_ADD("minflt", "%lu", kp.ki_rusage.ru_minflt); 492 PS_ADD("cminflt", "%lu", kp.ki_rusage_ch.ru_minflt); 493 PS_ADD("majflt", "%lu", kp.ki_rusage.ru_majflt); 494 PS_ADD("cmajflt", "%lu", kp.ki_rusage_ch.ru_majflt); 495 PS_ADD("utime", "%ld", T2J(tvtohz(&kp.ki_rusage.ru_utime))); 496 PS_ADD("stime", "%ld", T2J(tvtohz(&kp.ki_rusage.ru_stime))); 497 PS_ADD("cutime", "%ld", T2J(tvtohz(&kp.ki_rusage_ch.ru_utime))); 498 PS_ADD("cstime", "%ld", T2J(tvtohz(&kp.ki_rusage_ch.ru_stime))); 499 PS_ADD("priority", "%d", kp.ki_pri.pri_user); 500 PS_ADD("nice", "%d", kp.ki_nice); /* 19 (nicest) to -19 */ 501 PS_ADD("0", "%d", 0); /* removed field */ 502 PS_ADD("itrealvalue", "%d", 0); /* XXX */ 503 /* XXX: starttime is not right, it is the _same_ for _every_ process. 504 It should be the number of jiffies between system boot and process 505 start. */ 506 PS_ADD("starttime", "%lu", T2J(tvtohz(&kp.ki_start))); 507 PS_ADD("vsize", "%ju", P2K((uintmax_t)kp.ki_size)); 508 PS_ADD("rss", "%ju", (uintmax_t)kp.ki_rssize); 509 PS_ADD("rlim", "%lu", kp.ki_rusage.ru_maxrss); 510 PS_ADD("startcode", "%u", (unsigned)0); 511 PS_ADD("endcode", "%u", 0); /* XXX */ 512 PS_ADD("startstack", "%u", 0); /* XXX */ 513 PS_ADD("kstkesp", "%u", 0); /* XXX */ 514 PS_ADD("kstkeip", "%u", 0); /* XXX */ 515 PS_ADD("signal", "%u", 0); /* XXX */ 516 PS_ADD("blocked", "%u", 0); /* XXX */ 517 PS_ADD("sigignore", "%u", 0); /* XXX */ 518 PS_ADD("sigcatch", "%u", 0); /* XXX */ 519 PS_ADD("wchan", "%u", 0); /* XXX */ 520 PS_ADD("nswap", "%lu", kp.ki_rusage.ru_nswap); 521 PS_ADD("cnswap", "%lu", kp.ki_rusage_ch.ru_nswap); 522 PS_ADD("exitsignal", "%d", 0); /* XXX */ 523 PS_ADD("processor", "%u", kp.ki_lastcpu); 524 PS_ADD("rt_priority", "%u", 0); /* XXX */ /* >= 2.5.19 */ 525 PS_ADD("policy", "%u", kp.ki_pri.pri_class); /* >= 2.5.19 */ 526 #undef PS_ADD 527 sbuf_putc(sb, '\n'); 528 529 return (0); 530 } 531 532 /* 533 * Filler function for proc/pid/statm 534 */ 535 static int 536 linprocfs_doprocstatm(PFS_FILL_ARGS) 537 { 538 struct kinfo_proc kp; 539 segsz_t lsize; 540 541 PROC_LOCK(p); 542 fill_kinfo_proc(p, &kp); 543 PROC_UNLOCK(p); 544 545 /* 546 * See comments in linprocfs_doprocstatus() regarding the 547 * computation of lsize. 548 */ 549 /* size resident share trs drs lrs dt */ 550 sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size)); 551 sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize); 552 sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */ 553 sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_tsize); 554 sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize)); 555 lsize = B2P(kp.ki_size) - kp.ki_dsize - 556 kp.ki_ssize - kp.ki_tsize - 1; 557 sbuf_printf(sb, "%ju ", (uintmax_t)lsize); 558 sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */ 559 560 return (0); 561 } 562 563 /* 564 * Filler function for proc/pid/status 565 */ 566 static int 567 linprocfs_doprocstatus(PFS_FILL_ARGS) 568 { 569 struct kinfo_proc kp; 570 char *state; 571 segsz_t lsize; 572 struct thread *td2; 573 struct sigacts *ps; 574 int i; 575 576 PROC_LOCK(p); 577 td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */ 578 579 if (P_SHOULDSTOP(p)) { 580 state = "T (stopped)"; 581 } else { 582 mtx_lock_spin(&sched_lock); 583 switch(p->p_state) { 584 case PRS_NEW: 585 state = "I (idle)"; 586 break; 587 case PRS_NORMAL: 588 if (p->p_flag & P_WEXIT) { 589 state = "X (exiting)"; 590 break; 591 } 592 switch(td2->td_state) { 593 case TDS_INHIBITED: 594 state = "S (sleeping)"; 595 break; 596 case TDS_RUNQ: 597 case TDS_RUNNING: 598 state = "R (running)"; 599 break; 600 default: 601 state = "? (unknown)"; 602 break; 603 } 604 break; 605 case PRS_ZOMBIE: 606 state = "Z (zombie)"; 607 break; 608 default: 609 state = "? (unknown)"; 610 break; 611 } 612 mtx_unlock_spin(&sched_lock); 613 } 614 615 fill_kinfo_proc(p, &kp); 616 sbuf_printf(sb, "Name:\t%s\n", p->p_comm); /* XXX escape */ 617 sbuf_printf(sb, "State:\t%s\n", state); 618 619 /* 620 * Credentials 621 */ 622 sbuf_printf(sb, "Pid:\t%d\n", p->p_pid); 623 sbuf_printf(sb, "PPid:\t%d\n", p->p_pptr ? 624 p->p_pptr->p_pid : 0); 625 sbuf_printf(sb, "Uid:\t%d %d %d %d\n", p->p_ucred->cr_ruid, 626 p->p_ucred->cr_uid, 627 p->p_ucred->cr_svuid, 628 /* FreeBSD doesn't have fsuid */ 629 p->p_ucred->cr_uid); 630 sbuf_printf(sb, "Gid:\t%d %d %d %d\n", p->p_ucred->cr_rgid, 631 p->p_ucred->cr_gid, 632 p->p_ucred->cr_svgid, 633 /* FreeBSD doesn't have fsgid */ 634 p->p_ucred->cr_gid); 635 sbuf_cat(sb, "Groups:\t"); 636 for (i = 0; i < p->p_ucred->cr_ngroups; i++) 637 sbuf_printf(sb, "%d ", p->p_ucred->cr_groups[i]); 638 PROC_UNLOCK(p); 639 sbuf_putc(sb, '\n'); 640 641 /* 642 * Memory 643 * 644 * While our approximation of VmLib may not be accurate (I 645 * don't know of a simple way to verify it, and I'm not sure 646 * it has much meaning anyway), I believe it's good enough. 647 * 648 * The same code that could (I think) accurately compute VmLib 649 * could also compute VmLck, but I don't really care enough to 650 * implement it. Submissions are welcome. 651 */ 652 sbuf_printf(sb, "VmSize:\t%8ju kB\n", B2K((uintmax_t)kp.ki_size)); 653 sbuf_printf(sb, "VmLck:\t%8u kB\n", P2K(0)); /* XXX */ 654 sbuf_printf(sb, "VmRss:\t%8ju kB\n", P2K((uintmax_t)kp.ki_rssize)); 655 sbuf_printf(sb, "VmData:\t%8ju kB\n", P2K((uintmax_t)kp.ki_dsize)); 656 sbuf_printf(sb, "VmStk:\t%8ju kB\n", P2K((uintmax_t)kp.ki_ssize)); 657 sbuf_printf(sb, "VmExe:\t%8ju kB\n", P2K((uintmax_t)kp.ki_tsize)); 658 lsize = B2P(kp.ki_size) - kp.ki_dsize - 659 kp.ki_ssize - kp.ki_tsize - 1; 660 sbuf_printf(sb, "VmLib:\t%8ju kB\n", P2K((uintmax_t)lsize)); 661 662 /* 663 * Signal masks 664 * 665 * We support up to 128 signals, while Linux supports 32, 666 * but we only define 32 (the same 32 as Linux, to boot), so 667 * just show the lower 32 bits of each mask. XXX hack. 668 * 669 * NB: on certain platforms (Sparc at least) Linux actually 670 * supports 64 signals, but this code is a long way from 671 * running on anything but i386, so ignore that for now. 672 */ 673 PROC_LOCK(p); 674 sbuf_printf(sb, "SigPnd:\t%08x\n", p->p_siglist.__bits[0]); 675 /* 676 * I can't seem to find out where the signal mask is in 677 * relation to struct proc, so SigBlk is left unimplemented. 678 */ 679 sbuf_printf(sb, "SigBlk:\t%08x\n", 0); /* XXX */ 680 ps = p->p_sigacts; 681 mtx_lock(&ps->ps_mtx); 682 sbuf_printf(sb, "SigIgn:\t%08x\n", ps->ps_sigignore.__bits[0]); 683 sbuf_printf(sb, "SigCgt:\t%08x\n", ps->ps_sigcatch.__bits[0]); 684 mtx_unlock(&ps->ps_mtx); 685 PROC_UNLOCK(p); 686 687 /* 688 * Linux also prints the capability masks, but we don't have 689 * capabilities yet, and when we do get them they're likely to 690 * be meaningless to Linux programs, so we lie. XXX 691 */ 692 sbuf_printf(sb, "CapInh:\t%016x\n", 0); 693 sbuf_printf(sb, "CapPrm:\t%016x\n", 0); 694 sbuf_printf(sb, "CapEff:\t%016x\n", 0); 695 696 return (0); 697 } 698 699 700 /* 701 * Filler function for proc/pid/cwd 702 */ 703 static int 704 linprocfs_doproccwd(PFS_FILL_ARGS) 705 { 706 char *fullpath = "unknown"; 707 char *freepath = NULL; 708 709 vn_fullpath(td, p->p_fd->fd_cdir, &fullpath, &freepath); 710 sbuf_printf(sb, "%s", fullpath); 711 if (freepath) 712 free(freepath, M_TEMP); 713 return (0); 714 } 715 716 /* 717 * Filler function for proc/pid/root 718 */ 719 static int 720 linprocfs_doprocroot(PFS_FILL_ARGS) 721 { 722 struct vnode *rvp; 723 char *fullpath = "unknown"; 724 char *freepath = NULL; 725 726 rvp = jailed(p->p_ucred) ? p->p_fd->fd_jdir : p->p_fd->fd_rdir; 727 vn_fullpath(td, rvp, &fullpath, &freepath); 728 sbuf_printf(sb, "%s", fullpath); 729 if (freepath) 730 free(freepath, M_TEMP); 731 return (0); 732 } 733 734 /* 735 * Filler function for proc/pid/cmdline 736 */ 737 static int 738 linprocfs_doproccmdline(PFS_FILL_ARGS) 739 { 740 struct ps_strings pstr; 741 char **ps_argvstr; 742 int error, i; 743 744 /* 745 * If we are using the ps/cmdline caching, use that. Otherwise 746 * revert back to the old way which only implements full cmdline 747 * for the currept process and just p->p_comm for all other 748 * processes. 749 * Note that if the argv is no longer available, we deliberately 750 * don't fall back on p->p_comm or return an error: the authentic 751 * Linux behaviour is to return zero-length in this case. 752 */ 753 754 PROC_LOCK(p); 755 if (p->p_args && p_cansee(td, p) == 0) { 756 sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length); 757 PROC_UNLOCK(p); 758 } else if (p != td->td_proc) { 759 PROC_UNLOCK(p); 760 sbuf_printf(sb, "%.*s", MAXCOMLEN, p->p_comm); 761 } else { 762 PROC_UNLOCK(p); 763 error = copyin((void *)p->p_sysent->sv_psstrings, &pstr, 764 sizeof(pstr)); 765 if (error) 766 return (error); 767 if (pstr.ps_nargvstr > ARG_MAX) 768 return (E2BIG); 769 ps_argvstr = malloc(pstr.ps_nargvstr * sizeof(char *), 770 M_TEMP, M_WAITOK); 771 error = copyin((void *)pstr.ps_argvstr, ps_argvstr, 772 pstr.ps_nargvstr * sizeof(char *)); 773 if (error) { 774 free(ps_argvstr, M_TEMP); 775 return (error); 776 } 777 for (i = 0; i < pstr.ps_nargvstr; i++) { 778 sbuf_copyin(sb, ps_argvstr[i], 0); 779 sbuf_printf(sb, "%c", '\0'); 780 } 781 free(ps_argvstr, M_TEMP); 782 } 783 784 return (0); 785 } 786 787 /* 788 * Filler function for proc/pid/environ 789 */ 790 static int 791 linprocfs_doprocenviron(PFS_FILL_ARGS) 792 { 793 sbuf_printf(sb, "doprocenviron\n%c", '\0'); 794 795 return (0); 796 } 797 798 /* 799 * Filler function for proc/pid/maps 800 */ 801 static int 802 linprocfs_doprocmaps(PFS_FILL_ARGS) 803 { 804 char mebuffer[512]; 805 vm_map_t map = &p->p_vmspace->vm_map; 806 vm_map_entry_t entry; 807 vm_object_t obj, tobj, lobj; 808 vm_ooffset_t off = 0; 809 char *name = "", *freename = NULL; 810 size_t len; 811 ino_t ino; 812 int ref_count, shadow_count, flags; 813 int error; 814 struct vnode *vp; 815 struct vattr vat; 816 int locked; 817 818 PROC_LOCK(p); 819 error = p_candebug(td, p); 820 PROC_UNLOCK(p); 821 if (error) 822 return (error); 823 824 if (uio->uio_rw != UIO_READ) 825 return (EOPNOTSUPP); 826 827 if (uio->uio_offset != 0) 828 return (0); 829 830 error = 0; 831 if (map != &curthread->td_proc->p_vmspace->vm_map) 832 vm_map_lock_read(map); 833 for (entry = map->header.next; 834 ((uio->uio_resid > 0) && (entry != &map->header)); 835 entry = entry->next) { 836 name = ""; 837 freename = NULL; 838 if (entry->eflags & MAP_ENTRY_IS_SUB_MAP) 839 continue; 840 obj = entry->object.vm_object; 841 for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) 842 lobj = tobj; 843 ino = 0; 844 if (lobj) { 845 VM_OBJECT_LOCK(lobj); 846 off = IDX_TO_OFF(lobj->size); 847 if (lobj->type == OBJT_VNODE) { 848 vp = lobj->handle; 849 if (vp) 850 vref(vp); 851 } 852 else 853 vp = NULL; 854 flags = obj->flags; 855 ref_count = obj->ref_count; 856 shadow_count = obj->shadow_count; 857 VM_OBJECT_UNLOCK(lobj); 858 if (vp) { 859 vn_fullpath(td, vp, &name, &freename); 860 locked = VFS_LOCK_GIANT(vp->v_mount); 861 vn_lock(vp, LK_SHARED | LK_RETRY, td); 862 VOP_GETATTR(vp, &vat, td->td_ucred, td); 863 ino = vat.va_fileid; 864 vput(vp); 865 VFS_UNLOCK_GIANT(locked); 866 } 867 } else { 868 flags = 0; 869 ref_count = 0; 870 shadow_count = 0; 871 } 872 873 /* 874 * format: 875 * start, end, access, offset, major, minor, inode, name. 876 */ 877 snprintf(mebuffer, sizeof mebuffer, 878 "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n", 879 (u_long)entry->start, (u_long)entry->end, 880 (entry->protection & VM_PROT_READ)?"r":"-", 881 (entry->protection & VM_PROT_WRITE)?"w":"-", 882 (entry->protection & VM_PROT_EXECUTE)?"x":"-", 883 "p", 884 (u_long)off, 885 0, 886 0, 887 (u_long)ino, 888 *name ? " " : "", 889 name 890 ); 891 if (freename) 892 free(freename, M_TEMP); 893 len = strlen(mebuffer); 894 if (len > uio->uio_resid) 895 len = uio->uio_resid; /* 896 * XXX We should probably return 897 * EFBIG here, as in procfs. 898 */ 899 error = uiomove(mebuffer, len, uio); 900 if (error) 901 break; 902 } 903 if (map != &curthread->td_proc->p_vmspace->vm_map) 904 vm_map_unlock_read(map); 905 906 return (error); 907 } 908 909 /* 910 * Filler function for proc/net/dev 911 */ 912 static int 913 linprocfs_donetdev(PFS_FILL_ARGS) 914 { 915 char ifname[16]; /* XXX LINUX_IFNAMSIZ */ 916 struct ifnet *ifp; 917 918 sbuf_printf(sb, "%6s|%58s|%s\n%6s|%58s|%58s\n", 919 "Inter-", " Receive", " Transmit", " face", 920 "bytes packets errs drop fifo frame compressed", 921 "bytes packets errs drop fifo frame compressed"); 922 923 IFNET_RLOCK(); 924 TAILQ_FOREACH(ifp, &ifnet, if_link) { 925 linux_ifname(ifp, ifname, sizeof ifname); 926 sbuf_printf(sb, "%6.6s:", ifname); 927 sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ", 928 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL); 929 sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n", 930 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL); 931 } 932 IFNET_RUNLOCK(); 933 934 return (0); 935 } 936 937 /* 938 * Filler function for proc/sys/kernel/msgmni 939 */ 940 static int 941 linprocfs_domsgmni(PFS_FILL_ARGS) 942 { 943 int msgmni; 944 size_t size; 945 946 size = sizeof(msgmni); 947 if (kernel_sysctlbyname(td, "kern.ipc.msgmni", &msgmni, &size, 948 0, 0, 0, 0) != 0) 949 msgmni = 0; 950 sbuf_printf(sb, "%i\n", msgmni); 951 952 return (0); 953 } 954 955 /* 956 * Filler function for proc/sys/kernel/pid_max 957 */ 958 static int 959 linprocfs_dopid_max(PFS_FILL_ARGS) 960 { 961 962 sbuf_printf(sb, "%i\n", PID_MAX); 963 964 return (0); 965 } 966 967 /* 968 * Filler function for proc/sys/kernel/sem 969 */ 970 static int 971 linprocfs_dosem(PFS_FILL_ARGS) 972 { 973 int semmsl, semmns, semopm, semmni; 974 size_t size; 975 976 /* Field 1: SEMMSL */ 977 size = sizeof(semmsl); 978 if (kernel_sysctlbyname(td, "kern.ipc.semmsl", &semmsl, &size, 979 0, 0, 0, 0) != 0) 980 semmsl = 0; 981 982 /* Field 2: SEMMNS */ 983 size = sizeof(semmns); 984 if (kernel_sysctlbyname(td, "kern.ipc.semmns", &semmns, &size, 985 0, 0, 0, 0) != 0) 986 semmns = 0; 987 988 /* Field 3: SEMOPM */ 989 size = sizeof(semopm); 990 if (kernel_sysctlbyname(td, "kern.ipc.semopm", &semopm, &size, 991 0, 0, 0, 0) != 0) 992 semopm = 0; 993 994 /* Field 4: SEMMNI */ 995 size = sizeof(semmni); 996 if (kernel_sysctlbyname(td, "kern.ipc.semmni", &semmni, &size, 997 0, 0, 0, 0) != 0) 998 semmni = 0; 999 1000 sbuf_printf(sb, "%i %i %i %i\n", semmsl, semmns, semopm, semmni); 1001 1002 return (0); 1003 } 1004 1005 /* 1006 * Filler function for proc/scsi/device_info 1007 */ 1008 static int 1009 linprocfs_doscsidevinfo(PFS_FILL_ARGS) 1010 { 1011 return (0); 1012 } 1013 1014 /* 1015 * Filler function for proc/scsi/scsi 1016 */ 1017 static int 1018 linprocfs_doscsiscsi(PFS_FILL_ARGS) 1019 { 1020 return (0); 1021 } 1022 1023 extern struct cdevsw *cdevsw[]; 1024 1025 /* 1026 * Filler function for proc/devices 1027 */ 1028 static int 1029 linprocfs_dodevices(PFS_FILL_ARGS) 1030 { 1031 char *char_devices; 1032 sbuf_printf(sb, "Character devices:\n"); 1033 1034 char_devices = linux_get_char_devices(); 1035 sbuf_printf(sb, "%s", char_devices); 1036 linux_free_get_char_devices(char_devices); 1037 1038 sbuf_printf(sb, "\nBlock devices:\n"); 1039 1040 return (0); 1041 } 1042 1043 /* 1044 * Filler function for proc/cmdline 1045 */ 1046 static int 1047 linprocfs_docmdline(PFS_FILL_ARGS) 1048 { 1049 sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname); 1050 sbuf_printf(sb, " ro root=302\n"); 1051 return (0); 1052 } 1053 1054 #if 0 1055 /* 1056 * Filler function for proc/modules 1057 */ 1058 static int 1059 linprocfs_domodules(PFS_FILL_ARGS) 1060 { 1061 struct linker_file *lf; 1062 1063 TAILQ_FOREACH(lf, &linker_files, link) { 1064 sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename, 1065 (unsigned long)lf->size, lf->refs); 1066 } 1067 return (0); 1068 } 1069 #endif 1070 1071 /* 1072 * Constructor 1073 */ 1074 static int 1075 linprocfs_init(PFS_INIT_ARGS) 1076 { 1077 struct pfs_node *root; 1078 struct pfs_node *dir; 1079 1080 root = pi->pi_root; 1081 1082 /* /proc/... */ 1083 pfs_create_file(root, "cmdline", &linprocfs_docmdline, 1084 NULL, NULL, PFS_RD); 1085 pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo, 1086 NULL, NULL, PFS_RD); 1087 pfs_create_file(root, "devices", &linprocfs_dodevices, 1088 NULL, NULL, PFS_RD); 1089 pfs_create_file(root, "loadavg", &linprocfs_doloadavg, 1090 NULL, NULL, PFS_RD); 1091 pfs_create_file(root, "meminfo", &linprocfs_domeminfo, 1092 NULL, NULL, PFS_RD); 1093 #if 0 1094 pfs_create_file(root, "modules", &linprocfs_domodules, 1095 NULL, NULL, PFS_RD); 1096 #endif 1097 pfs_create_file(root, "mounts", &linprocfs_domtab, 1098 NULL, NULL, PFS_RD); 1099 pfs_create_file(root, "mtab", &linprocfs_domtab, 1100 NULL, NULL, PFS_RD); 1101 pfs_create_link(root, "self", &procfs_docurproc, 1102 NULL, NULL, 0); 1103 pfs_create_file(root, "stat", &linprocfs_dostat, 1104 NULL, NULL, PFS_RD); 1105 pfs_create_file(root, "uptime", &linprocfs_douptime, 1106 NULL, NULL, PFS_RD); 1107 pfs_create_file(root, "version", &linprocfs_doversion, 1108 NULL, NULL, PFS_RD); 1109 1110 /* /proc/net/... */ 1111 dir = pfs_create_dir(root, "net", NULL, NULL, 0); 1112 pfs_create_file(dir, "dev", &linprocfs_donetdev, 1113 NULL, NULL, PFS_RD); 1114 1115 /* /proc/<pid>/... */ 1116 dir = pfs_create_dir(root, "pid", NULL, NULL, PFS_PROCDEP); 1117 pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline, 1118 NULL, NULL, PFS_RD); 1119 pfs_create_link(dir, "cwd", &linprocfs_doproccwd, 1120 NULL, NULL, 0); 1121 pfs_create_file(dir, "environ", &linprocfs_doprocenviron, 1122 NULL, NULL, PFS_RD); 1123 pfs_create_link(dir, "exe", &procfs_doprocfile, 1124 NULL, &procfs_notsystem, 0); 1125 pfs_create_file(dir, "maps", &linprocfs_doprocmaps, 1126 NULL, NULL, PFS_RD); 1127 pfs_create_file(dir, "mem", &procfs_doprocmem, 1128 &procfs_attr, &procfs_candebug, PFS_RDWR|PFS_RAW); 1129 pfs_create_link(dir, "root", &linprocfs_doprocroot, 1130 NULL, NULL, 0); 1131 pfs_create_file(dir, "stat", &linprocfs_doprocstat, 1132 NULL, NULL, PFS_RD); 1133 pfs_create_file(dir, "statm", &linprocfs_doprocstatm, 1134 NULL, NULL, PFS_RD); 1135 pfs_create_file(dir, "status", &linprocfs_doprocstatus, 1136 NULL, NULL, PFS_RD); 1137 1138 /* /proc/scsi/... */ 1139 dir = pfs_create_dir(root, "scsi", NULL, NULL, 0); 1140 pfs_create_file(dir, "device_info", &linprocfs_doscsidevinfo, 1141 NULL, NULL, PFS_RD); 1142 pfs_create_file(dir, "scsi", &linprocfs_doscsiscsi, 1143 NULL, NULL, PFS_RD); 1144 1145 /* /proc/sys/... */ 1146 dir = pfs_create_dir(root, "sys", NULL, NULL, 0); 1147 /* /proc/sys/kernel/... */ 1148 dir = pfs_create_dir(dir, "kernel", NULL, NULL, 0); 1149 pfs_create_file(dir, "msgmni", &linprocfs_domsgmni, 1150 NULL, NULL, PFS_RD); 1151 pfs_create_file(dir, "pid_max", &linprocfs_dopid_max, 1152 NULL, NULL, PFS_RD); 1153 pfs_create_file(dir, "sem", &linprocfs_dosem, 1154 NULL, NULL, PFS_RD); 1155 1156 return (0); 1157 } 1158 1159 /* 1160 * Destructor 1161 */ 1162 static int 1163 linprocfs_uninit(PFS_INIT_ARGS) 1164 { 1165 1166 /* nothing to do, pseudofs will GC */ 1167 return (0); 1168 } 1169 1170 PSEUDOFS(linprocfs, 1); 1171 MODULE_DEPEND(linprocfs, linux, 1, 1, 1); 1172 MODULE_DEPEND(linprocfs, procfs, 1, 1, 1); 1173