2 * Copyright (c) 2000 Dag-Erling Coïdan Smørgrav
3 * Copyright (c) 1999 Pierre Beyssac
4 * Copyright (c) 1993 Jan-Simon Pendry
6 * The Regents of the University of California. All rights reserved.
8 * This code is derived from software contributed to Berkeley by
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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
39 * @(#)procfs_status.c 8.4 (Berkeley) 6/15/94
41 * $FreeBSD: src/sys/i386/linux/linprocfs/linprocfs_misc.c,v 1.3.2.8 2001/06/25 19:46:47 pirzyk Exp $
42 * $DragonFly: src/sys/emulation/linux/i386/linprocfs/linprocfs_misc.c,v 1.19 2008/05/10 17:24:05 dillon Exp $
45 #include <sys/param.h>
46 #include <sys/blist.h>
47 #include <sys/kernel.h>
48 #include <sys/kinfo.h>
51 #include <sys/resourcevar.h>
52 #include <sys/systm.h>
54 #include <sys/vnode.h>
57 #include <sys/mount.h>
58 #include <sys/sysctl.h>
62 #include <vm/vm_map.h>
63 #include <vm/vm_param.h>
64 #include <vm/vm_object.h>
65 #include <vm/swap_pager.h>
66 #include <sys/vmmeter.h>
69 #include <machine/clock.h>
70 #include <machine/cputypes.h>
71 #include <machine/inttypes.h>
72 #include <machine/md_var.h>
73 #include <machine/vmparam.h>
75 #include "linprocfs.h"
77 #include "../../linux_ioctl.h"
78 #include "../../linux_mib.h"
81 * Various conversion macros
83 #define T2J(x) (((x) * 100) / (stathz ? stathz : hz)) /* ticks to jiffies */
84 #define T2S(x) ((x) / (stathz ? stathz : hz)) /* ticks to seconds */
85 #define B2K(x) ((unsigned long)((x) >> 10)) /* bytes to kbytes */
86 #define P2B(x) ((x) << PAGE_SHIFT) /* pages to bytes */
87 #define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */
90 linprocfs_domeminfo(struct proc *curp, struct proc *p, struct pfsnode *pfs,
94 char psbuf[512]; /* XXX - conservative */
95 unsigned long memtotal; /* total memory in bytes */
96 unsigned long memused; /* used memory in bytes */
97 unsigned long memfree; /* free memory in bytes */
98 unsigned long memshared; /* shared memory ??? */
99 unsigned long buffers, cached; /* buffer / cache memory ??? */
100 unsigned long long swaptotal; /* total swap space in bytes */
101 unsigned long long swapused; /* used swap space in bytes */
102 unsigned long long swapfree; /* free swap space in bytes */
105 if (uio->uio_rw != UIO_READ)
108 memtotal = Maxmem * PAGE_SIZE;
110 * The correct thing here would be:
112 memfree = vmstats.v_free_count * PAGE_SIZE;
113 memused = memtotal - memfree;
115 * but it might mislead linux binaries into thinking there
116 * is very little memory left, so we cheat and tell them that
117 * all memory that isn't wired down is free.
119 memused = vmstats.v_wire_count * PAGE_SIZE;
120 memfree = memtotal - memused;
121 if (swapblist == NULL) {
125 swaptotal = swapblist->bl_blocks * 1024LL; /* XXX why 1024? */
126 swapfree = (unsigned long long)swapblist->bl_root->u.bmu_avail * PAGE_SIZE;
128 swapused = swaptotal - swapfree;
130 for (object = TAILQ_FIRST(&vm_object_list); object != NULL;
131 object = TAILQ_NEXT(object, object_list)) {
132 if (object->type == OBJT_MARKER)
134 if (object->shadow_count > 1)
135 memshared += object->resident_page_count;
137 memshared *= PAGE_SIZE;
139 * We'd love to be able to write:
143 * but bufspace is internal to vfs_bio.c and we don't feel
144 * like unstaticizing it just for linprocfs's sake.
147 cached = vmstats.v_cache_count * PAGE_SIZE;
151 " total: used: free: shared: buffers: cached:\n"
152 "Mem: %lu %lu %lu %lu %lu %lu\n"
153 "Swap: %llu %llu %llu\n"
154 "MemTotal: %9lu kB\n"
156 "MemShared:%9lu kB\n"
159 "SwapTotal:%9lu kB\n"
160 "SwapFree: %9lu kB\n",
161 memtotal, memused, memfree, memshared, buffers, cached,
162 swaptotal, swapused, swapfree,
163 B2K(memtotal), B2K(memfree),
164 B2K(memshared), B2K(buffers), B2K(cached),
165 B2K(swaptotal), B2K(swapfree));
167 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
171 linprocfs_docpuinfo(struct proc *curp, struct proc *p, struct pfsnode *pfs,
177 size_t modellen = sizeof(hwmodel);
178 int mib[] = { CTL_HW, HW_MODEL };
184 extern char *cpu_model; /* Yuck */
186 /* We default the flags to include all non-conflicting flags,
187 and the Intel versions of conflicting flags. Note the space
188 before each name; that is significant, and should be
191 static char *flags[] = {
192 "fpu", "vme", "de", "pse", "tsc",
193 "msr", "pae", "mce", "cx8", "apic",
194 "sep", "sep", "mtrr", "pge", "mca",
195 "cmov", "pat", "pse36", "pn", "b19",
196 "b20", "b21", "mmxext", "mmx", "fxsr",
197 "xmm", "b26", "b27", "b28", "b29",
201 if (uio->uio_rw != UIO_READ)
227 error = kernel_sysctl(mib, 2, hwmodel, &modellen, NULL, 0, NULL);
229 strcpy(hwmodel, "unknown");
231 for (cpu = 0; cpu < ncpus; cpu++) {
234 "vendor_id\t: %.20s\n"
239 cpu, cpu_vendor, class, cpu, hwmodel, cpu_id & 0xf);
245 if (!strcmp(cpu_vendor, "AuthenticAMD") && (class < 6)) {
247 } else if (!strcmp(cpu_vendor, "CyrixInstead")) {
251 for (i = 0; i < 32; i++)
252 if (cpu_feature & (1 << i))
253 ps += ksprintf(ps, " %s", flags[i]);
254 ps += ksprintf(ps, "\n");
257 "cpu MHz\t\t: %d.%02d\n"
258 "bogomips\t: %d.%02d\n",
259 (int)((tsc_frequency + 4999) / 1000000),
260 (int)((tsc_frequency + 4999) / 10000) % 100,
261 (int)((tsc_frequency + 4999) / 1000000),
262 (int)((tsc_frequency + 4999) / 10000) % 100);
265 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
274 for (i = 0; i < ncpus; ++i) {
275 struct globaldata *gd = globaldata_find(i);
276 count += *(unsigned int *)((char *)&gd->gd_cnt + offset);
282 linprocfs_domounts_callback(struct mount *mp, void *data)
285 struct sbuf *sb = (struct sbuf *)data;
286 char *to, *from, *fs;
290 from = st->f_mntfromname;
291 to = st->f_mntonname;
292 fs = st->f_fstypename;
294 if (!strcmp(st->f_fstypename, "linprocfs"))
296 else if (!strcmp(st->f_fstypename, "ext2fs"))
298 else if (!strcmp(st->f_fstypename, "msdos"))
300 else if (!strcmp(st->f_fstypename, "msdosfs"))
303 sbuf_printf(sb, "%s %s %s %s", from, to, fs,
304 st->f_flags & MNT_RDONLY ? "ro" : "rw");
306 #define OPT_ADD(name, flag) if (st->f_flags & (flag)) sbuf_printf(sb, "," name)
307 OPT_ADD("sync", MNT_SYNCHRONOUS);
308 OPT_ADD("noexec", MNT_NOEXEC);
309 OPT_ADD("nosuid", MNT_NOSUID);
310 OPT_ADD("nodev", MNT_NODEV);
311 OPT_ADD("async", MNT_ASYNC);
312 OPT_ADD("suiddir", MNT_SUIDDIR);
313 OPT_ADD("nosymfollow", MNT_NOSYMFOLLOW);
314 OPT_ADD("noatime", MNT_NOATIME);
317 sbuf_printf(sb, " 0 0\n");
323 linprocfs_domounts(struct proc *curp, struct proc *p, struct pfsnode *pfs,
329 sb = sbuf_new_auto();
331 error = mountlist_scan(linprocfs_domounts_callback, sb, MNTSCAN_FORWARD);
335 error = uiomove_frombuf(sbuf_data(sb), sbuf_len(sb), uio);
341 linprocfs_dostat(struct proc *curp, struct proc *p, struct pfsnode *pfs,
350 "cpu %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64"\n",
351 T2J(cpu_time.cp_user),
352 T2J(cpu_time.cp_nice),
353 T2J(cpu_time.cp_sys),
354 T2J(cpu_time.cp_idle));
356 for (cpu = 0; cpu < ncpus; cpu++) {
358 "cpu%d %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64"\n",
360 T2J(cputime_percpu[cpu].cp_user),
361 T2J(cputime_percpu[cpu].cp_nice),
362 T2J(cputime_percpu[cpu].cp_sys),
363 T2J(cputime_percpu[cpu].cp_idle));
373 cpucnt(offsetof(struct vmmeter, v_vnodepgsin)),
374 cpucnt(offsetof(struct vmmeter, v_vnodepgsout)),
375 cpucnt(offsetof(struct vmmeter, v_swappgsin)),
376 cpucnt(offsetof(struct vmmeter, v_swappgsout)),
377 cpucnt(offsetof(struct vmmeter, v_intr)),
378 cpucnt(offsetof(struct vmmeter, v_swtch)),
381 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
385 linprocfs_douptime(struct proc *curp, struct proc *p, struct pfsnode *pfs,
394 ps += ksprintf(ps, "%ld.%02ld %"PRIu64".%02"PRIu64"\n",
395 tv.tv_sec, tv.tv_usec / 10000,
396 T2S(cpu_time.cp_idle), T2J(cpu_time.cp_idle) % 100);
397 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
401 linprocfs_doversion(struct proc *curp, struct proc *p, struct pfsnode *pfs,
407 ps = version; /* XXX not entirely correct */
408 for (xlen = 0; ps[xlen] != '\n'; ++xlen)
411 return (uiomove_frombuf(ps, xlen, uio));
414 #define B2P(x) ((x) >> PAGE_SHIFT) /* bytes to pages */
416 linprocfs_dostatm(struct proc *curp, struct proc *p, struct pfsnode *pfs,
419 char *ps, psbuf[1024];
420 struct kinfo_proc kp;
422 fill_kinfo_proc(p, &kp);
425 ps += ksprintf(ps, "%d", p->p_pid);
426 #define PS_ADD(name, fmt, arg) ps += ksprintf(ps, " " fmt, arg)
427 PS_ADD("", "%ju", B2P((uintmax_t)(kp.kp_vm_tsize + kp.kp_vm_dsize + kp.kp_vm_ssize)));
428 PS_ADD("", "%ju", (uintmax_t)kp.kp_vm_rssize);
429 PS_ADD("", "%ju", (uintmax_t)0); /* XXX */
430 PS_ADD("", "%ju", (uintmax_t)kp.kp_vm_tsize);
431 PS_ADD("", "%ju", (uintmax_t)kp.kp_vm_dsize);
432 PS_ADD("", "%ju", (uintmax_t)kp.kp_vm_ssize);
433 PS_ADD("", "%ju", (uintmax_t)0); /* XXX */
435 ps += ksprintf(ps, "\n");
437 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
440 #define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */
442 linprocfs_doprocstat(struct proc *curp, struct proc *p, struct pfsnode *pfs,
445 vm_map_t map = &p->p_vmspace->vm_map;
446 vm_map_entry_t entry;
447 vm_offset_t start, end;
448 char *ps, psbuf[1024];
449 struct kinfo_proc kp;
451 fill_kinfo_proc(p, &kp);
455 vm_map_lock_read(map);
456 for (entry = map->header.next; entry != &map->header;
457 entry = entry->next) {
458 if (entry->maptype != VM_MAPTYPE_NORMAL &&
459 entry->maptype != VM_MAPTYPE_VPAGETABLE) {
462 /* Assuming that text is the first entry */
463 start = entry->start;
466 vm_map_unlock_read(map);
469 ps += ksprintf(ps, "%d", p->p_pid);
470 #define PS_ADD(name, fmt, arg) ps += ksprintf(ps, " " fmt, arg)
471 PS_ADD("comm", "(%s)", p->p_comm);
472 PS_ADD("statr", "%c", '0'); /* XXX */
473 PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0);
474 PS_ADD("pgrp", "%d", p->p_pgid);
475 PS_ADD("session", "%d", p->p_session->s_sid);
476 PS_ADD("tty", "%d", 0); /* XXX */
477 PS_ADD("tpgid", "%d", kp.kp_tpgid); /* XXX */
478 PS_ADD("flags", "%u", 0); /* XXX */
479 PS_ADD("minflt", "%lu", kp.kp_ru.ru_minflt); /* XXX */
480 PS_ADD("cminflt", "%lu", kp.kp_cru.ru_minflt); /* XXX */
481 PS_ADD("majflt", "%lu", kp.kp_ru.ru_majflt); /* XXX */
482 PS_ADD("cmajflt", "%lu", kp.kp_cru.ru_majflt); /* XXX */
483 PS_ADD("utime", "%d", T2J(tvtohz_high(&kp.kp_ru.ru_utime))); /* XXX */
484 PS_ADD("stime", "%d", T2J(tvtohz_high(&kp.kp_ru.ru_stime))); /* XXX */
485 PS_ADD("cutime", "%d", T2J(tvtohz_high(&kp.kp_cru.ru_utime))); /* XXX */
486 PS_ADD("cstime", "%d", T2J(tvtohz_high(&kp.kp_cru.ru_stime))); /* XXX */
487 PS_ADD("priority", "%d", 0); /* XXX */
488 PS_ADD("nice", "%d", kp.kp_nice);
489 PS_ADD("timeout", "%u", 0); /* XXX */
490 PS_ADD("itrealvalue", "%u", 0); /* XXX */
491 PS_ADD("starttime", "%d", T2J(tvtohz_high(&kp.kp_start))); /* XXX */
492 PS_ADD("vsize", "%ju", P2K((uintmax_t)(kp.kp_vm_tsize + kp.kp_vm_dsize + kp.kp_vm_ssize))); /* XXX: not sure */
493 PS_ADD("rss", "%ju", (uintmax_t)kp.kp_vm_rssize); /* XXX */
494 PS_ADD("rlim", "%lu", kp.kp_ru.ru_maxrss); /* XXX */
495 PS_ADD("startcode", "%lu", start); /* XXX */
496 PS_ADD("endcode", "%lu", end); /* XXX */
497 PS_ADD("startstack", "%lu", (u_long)p->p_vmspace->vm_minsaddr); /* XXX */
498 PS_ADD("kstkesp", "%u", 0); /* XXX */
499 PS_ADD("kstkeip", "%u", 0); /* XXX */
500 PS_ADD("signal", "%d", 0); /* XXX */
501 PS_ADD("blocked", "%d", 0); /* XXX */
502 PS_ADD("sigignore", "%d", 0); /* XXX */
503 PS_ADD("sigcatch", "%d", 0); /* XXX */
504 PS_ADD("wchan", "%u", 0); /* XXX */
505 PS_ADD("nswap", "%lu", kp.kp_ru.ru_nswap); /* XXX */
506 PS_ADD("cnswap", "%lu", kp.kp_cru.ru_nswap); /* XXX */
507 PS_ADD("exitsignal", "%d", 0); /* XXX */
508 PS_ADD("processor", "%u", kp.kp_lwp.kl_cpuid); /* XXX */
509 PS_ADD("rt_priority", "%u", 0); /* XXX */ /* >= 2.5.19 */
510 PS_ADD("policy", "%u", kp.kp_nice); /* XXX */ /* >= 2.5.19 */
512 ps += ksprintf(ps, "\n");
514 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
518 * Map process state to descriptive letter. Note that this does not
519 * quite correspond to what Linux outputs, but it's close enough.
521 static char *state_str[] = {
533 linprocfs_doprocstatus(struct proc *curp, struct proc *p, struct pfsnode *pfs,
536 char *ps, psbuf[1024];
542 if (p->p_stat > sizeof state_str / sizeof *state_str)
543 state = state_str[0];
545 state = state_str[(int)p->p_stat];
547 #define PS_ADD ps += ksprintf
548 PS_ADD(ps, "Name:\t%s\n", p->p_comm); /* XXX escape */
549 PS_ADD(ps, "State:\t%s\n", state);
554 PS_ADD(ps, "Pid:\t%d\n", p->p_pid);
555 PS_ADD(ps, "PPid:\t%d\n", p->p_pptr ? p->p_pptr->p_pid : 0);
556 PS_ADD(ps, "Uid:\t%d %d %d %d\n", p->p_ucred->cr_ruid,
558 p->p_ucred->cr_svuid,
559 /* FreeBSD doesn't have fsuid */
561 PS_ADD(ps, "Gid:\t%d %d %d %d\n", p->p_ucred->cr_rgid,
563 p->p_ucred->cr_svgid,
564 /* FreeBSD doesn't have fsgid */
566 PS_ADD(ps, "Groups:\t");
567 for (i = 0; i < p->p_ucred->cr_ngroups; i++)
568 PS_ADD(ps, "%d ", p->p_ucred->cr_groups[i]);
574 PS_ADD(ps, "VmSize:\t%8lu kB\n", B2K(p->p_vmspace->vm_map.size));
575 PS_ADD(ps, "VmLck:\t%8u kB\n", P2K(0)); /* XXX */
576 /* XXX vm_rssize seems to always be zero, how can this be? */
577 PS_ADD(ps, "VmRss:\t%8u kB\n", P2K(p->p_vmspace->vm_rssize));
578 PS_ADD(ps, "VmData:\t%8u kB\n", P2K(p->p_vmspace->vm_dsize));
579 PS_ADD(ps, "VmStk:\t%8u kB\n", P2K(p->p_vmspace->vm_ssize));
580 PS_ADD(ps, "VmExe:\t%8u kB\n", P2K(p->p_vmspace->vm_tsize));
581 PS_ADD(ps, "VmLib:\t%8u kB\n", P2K(0)); /* XXX */
586 * We support up to 128 signals, while Linux supports 32,
587 * but we only define 32 (the same 32 as Linux, to boot), so
588 * just show the lower 32 bits of each mask. XXX hack.
590 * NB: on certain platforms (Sparc at least) Linux actually
591 * supports 64 signals, but this code is a long way from
592 * running on anything but i386, so ignore that for now.
594 PS_ADD(ps, "SigPnd:\t%08x\n", p->p_siglist.__bits[0]);
595 PS_ADD(ps, "SigBlk:\t%08x\n", 0); /* XXX */
596 PS_ADD(ps, "SigIgn:\t%08x\n", p->p_sigignore.__bits[0]);
597 PS_ADD(ps, "SigCgt:\t%08x\n", p->p_sigcatch.__bits[0]);
600 * Linux also prints the capability masks, but we don't have
601 * capabilities yet, and when we do get them they're likely to
602 * be meaningless to Linux programs, so we lie. XXX
604 PS_ADD(ps, "CapInh:\t%016x\n", 0);
605 PS_ADD(ps, "CapPrm:\t%016x\n", 0);
606 PS_ADD(ps, "CapEff:\t%016x\n", 0);
609 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
613 linprocfs_doloadavg(struct proc *curp, struct proc *p,
614 struct pfsnode *pfs, struct uio *uio)
616 char *ps, psbuf[512];
619 ps += ksprintf(ps, "%d.%02d %d.%02d %d.%02d %d/%d %d\n",
620 (int)(averunnable.ldavg[0] / averunnable.fscale),
621 (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100),
622 (int)(averunnable.ldavg[1] / averunnable.fscale),
623 (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100),
624 (int)(averunnable.ldavg[2] / averunnable.fscale),
625 (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100),
626 1, /* number of running tasks */
627 -1, /* number of tasks */
628 1 /* The last pid, just kidding */
630 return(uiomove_frombuf(psbuf, ps - psbuf, uio));
634 linprocfs_donetdev(struct proc *curp, struct proc *p, struct pfsnode *pfs,
638 char ifname[16]; /* XXX LINUX_IFNAMSIZ */
642 sb = sbuf_new_auto();
644 sbuf_printf(sb, "%6s|%58s|%s\n%6s|%58s|%58s\n",
645 "Inter-", " Receive", " Transmit", " face",
646 "bytes packets errs drop fifo frame compressed",
647 "bytes packets errs drop fifo frame compressed");
650 TAILQ_FOREACH(ifp, &ifnet, if_link) {
651 linux_ifname(ifp, ifname, sizeof ifname);
652 sbuf_printf(sb, "%6.6s:", ifname);
653 sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ",
654 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
655 sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
656 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
660 error = uiomove_frombuf(sbuf_data(sb), sbuf_len(sb), uio);
666 linprocfs_dodevices(struct proc *curp, struct proc *p, struct pfsnode *pfs,
673 linprocfs_doosrelease(struct proc *curp, struct proc *p, struct pfsnode *pfs,
678 osrelease = linux_get_osrelease(curthread);
679 return(uiomove_frombuf(osrelease, strlen(osrelease)+1, uio));
683 linprocfs_doostype(struct proc *curp, struct proc *p, struct pfsnode *pfs,
688 osname = linux_get_osname(curthread);
689 return(uiomove_frombuf(osname, strlen(osname)+1, uio));
693 linprocfs_dopidmax(struct proc *curp, struct proc *p, struct pfsnode *pfs,
698 ksnprintf(buf, sizeof(buf), "%d", PID_MAX);
699 return(uiomove_frombuf(buf, strlen(buf)+1, uio));
704 linprocfs_domaps(struct proc *curp, struct proc *p, struct pfsnode *pfs,
708 vm_map_t map = &p->p_vmspace->vm_map;
709 vm_map_entry_t entry;
710 vm_ooffset_t off = 0;
712 char *name = "", *freename = NULL;
718 if (uio->uio_rw != UIO_READ)
721 sb = sbuf_new_auto();
724 vm_map_lock_read(map);
725 for (entry = map->header.next;
726 ((uio->uio_resid > 0) && (entry != &map->header));
727 entry = entry->next) {
728 vm_object_t obj, tobj, lobj;
733 if (entry->maptype != VM_MAPTYPE_NORMAL &&
734 entry->maptype != VM_MAPTYPE_VPAGETABLE) {
738 * Use map->hint as a poor man's ripout detector.
741 ostart = entry->start;
742 obj = entry->object.vm_object;
744 for( lobj = tobj = obj; tobj; tobj = tobj->backing_object)
748 off = IDX_TO_OFF(lobj->size);
749 if (lobj->type == OBJT_VNODE) {
758 vn_fullpath(curproc, vp, &name, &freename, 1);
759 vn_lock(vp, LK_SHARED | LK_RETRY);
760 VOP_GETATTR(vp, &vat);
762 major = vat.va_rmajor;
763 minor = vat.va_rminor;
767 if (freename == NULL) {
768 if (entry->eflags & MAP_ENTRY_STACK)
773 * We cannot safely hold the map locked while accessing
774 * userspace as a VM fault might recurse the locked map.
776 vm_map_unlock_read(map);
780 * start-end access offset major:minor inode [.text file]
782 error = sbuf_printf(sb,
783 "%08lx-%08lx %s%s%s%s %08llx %02x:%02x %llu%s%s\n",
784 (u_long)entry->start, (u_long)entry->end,
785 (entry->protection & VM_PROT_READ)?"r":"-",
786 (entry->protection & VM_PROT_WRITE)?"w":"-",
787 (entry->protection & VM_PROT_EXECUTE)?"x":"-",
793 (name && *name) ? " " : "",
798 kfree(freename, M_TEMP);
800 vm_map_lock_read(map);
805 * We use map->hint as a poor man's ripout detector. If
806 * it does not match the entry we set it to prior to
807 * unlocking the map the entry MIGHT now be stale. In
808 * this case we do an expensive lookup to find our place
809 * in the iteration again.
811 if (map->hint != entry) {
812 vm_map_entry_t reentry;
814 vm_map_lookup_entry(map, ostart, &reentry);
818 vm_map_unlock_read(map);
822 error = uiomove_frombuf(sbuf_data(sb) + uio->uio_offset,
823 sbuf_len(sb) - uio->uio_offset, uio);