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