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 $
44 #include <sys/param.h>
45 #include <sys/blist.h>
46 #include <sys/kernel.h>
47 #include <sys/kinfo.h>
50 #include <sys/resourcevar.h>
51 #include <sys/systm.h>
53 #include <sys/vnode.h>
56 #include <sys/mount.h>
57 #include <sys/sysctl.h>
61 #include <vm/vm_map.h>
62 #include <vm/vm_param.h>
63 #include <vm/vm_object.h>
64 #include <vm/swap_pager.h>
65 #include <sys/vmmeter.h>
68 #include <machine/clock.h>
69 #include <machine/cputypes.h>
70 #include <machine/inttypes.h>
71 #include <machine/md_var.h>
72 #include <machine/vmparam.h>
74 #include "linprocfs.h"
76 #include "../../linux_ioctl.h"
77 #include "../../linux_mib.h"
80 * Various conversion macros
82 #define T2J(x) (((x) * 100) / (stathz ? stathz : hz)) /* ticks to jiffies */
83 #define T2S(x) ((x) / (stathz ? stathz : hz)) /* ticks to seconds */
84 #define B2K(x) ((unsigned long)((x) >> 10)) /* bytes to kbytes */
85 #define P2B(x) ((x) << PAGE_SHIFT) /* pages to bytes */
86 #define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */
89 linprocfs_domeminfo(struct proc *curp, struct proc *p, struct pfsnode *pfs,
93 char psbuf[512]; /* XXX - conservative */
94 unsigned long memtotal; /* total memory in bytes */
95 unsigned long memused; /* used memory in bytes */
96 unsigned long memfree; /* free memory in bytes */
97 unsigned long memshared; /* shared memory ??? */
98 unsigned long buffers, cached; /* buffer / cache memory ??? */
99 unsigned long long swaptotal; /* total swap space in bytes */
100 unsigned long long swapused; /* used swap space in bytes */
101 unsigned long long swapfree; /* free swap space in bytes */
104 if (uio->uio_rw != UIO_READ)
107 memtotal = Maxmem * PAGE_SIZE;
109 * The correct thing here would be:
111 memfree = vmstats.v_free_count * PAGE_SIZE;
112 memused = memtotal - memfree;
114 * but it might mislead linux binaries into thinking there
115 * is very little memory left, so we cheat and tell them that
116 * all memory that isn't wired down is free.
118 memused = vmstats.v_wire_count * PAGE_SIZE;
119 memfree = memtotal - memused;
120 if (swapblist == NULL) {
124 swaptotal = swapblist->bl_blocks * 1024LL; /* XXX why 1024? */
125 swapfree = (unsigned long long)swapblist->bl_root->u.bmu_avail * PAGE_SIZE;
127 swapused = swaptotal - swapfree;
130 lwkt_gettoken(&vmobj_token);
131 for (object = TAILQ_FIRST(&vm_object_list); object != NULL;
132 object = TAILQ_NEXT(object, object_list)) {
133 if (object->type == OBJT_MARKER)
135 if (object->shadow_count > 1)
136 memshared += object->resident_page_count;
138 lwkt_reltoken(&vmobj_token);
139 memshared *= PAGE_SIZE;
141 * We'd love to be able to write:
145 * but bufspace is internal to vfs_bio.c and we don't feel
146 * like unstaticizing it just for linprocfs's sake.
149 cached = vmstats.v_cache_count * PAGE_SIZE;
153 " total: used: free: shared: buffers: cached:\n"
154 "Mem: %lu %lu %lu %lu %lu %lu\n"
155 "Swap: %llu %llu %llu\n"
156 "MemTotal: %9lu kB\n"
158 "MemShared:%9lu kB\n"
161 "SwapTotal:%9lu kB\n"
162 "SwapFree: %9lu kB\n",
163 memtotal, memused, memfree, memshared, buffers, cached,
164 swaptotal, swapused, swapfree,
165 B2K(memtotal), B2K(memfree),
166 B2K(memshared), B2K(buffers), B2K(cached),
167 B2K(swaptotal), B2K(swapfree));
169 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
173 linprocfs_docpuinfo(struct proc *curp, struct proc *p, struct pfsnode *pfs,
179 size_t modellen = sizeof(hwmodel);
180 int mib[] = { CTL_HW, HW_MODEL };
186 extern char *cpu_model; /* Yuck */
188 /* We default the flags to include all non-conflicting flags,
189 and the Intel versions of conflicting flags. Note the space
190 before each name; that is significant, and should be
193 static char *flags[] = {
194 "fpu", "vme", "de", "pse", "tsc",
195 "msr", "pae", "mce", "cx8", "apic",
196 "sep", "sep", "mtrr", "pge", "mca",
197 "cmov", "pat", "pse36", "pn", "b19",
198 "b20", "b21", "mmxext", "mmx", "fxsr",
199 "xmm", "b26", "b27", "b28", "b29",
203 if (uio->uio_rw != UIO_READ)
229 error = kernel_sysctl(mib, 2, hwmodel, &modellen, NULL, 0, NULL);
231 strcpy(hwmodel, "unknown");
233 for (cpu = 0; cpu < ncpus; cpu++) {
236 "vendor_id\t: %.20s\n"
241 cpu, cpu_vendor, class, cpu, hwmodel, cpu_id & 0xf);
247 if (cpu_vendor_id == CPU_VENDOR_AMD && (class < 6)) {
249 } else if (cpu_vendor_id == CPU_VENDOR_CYRIX) {
253 for (i = 0; i < 32; i++)
254 if (cpu_feature & (1 << i))
255 ps += ksprintf(ps, " %s", flags[i]);
256 ps += ksprintf(ps, "\n");
259 "cpu MHz\t\t: %d.%02d\n"
260 "bogomips\t: %d.%02d\n",
261 (int)((tsc_frequency + 4999) / 1000000),
262 (int)((tsc_frequency + 4999) / 10000) % 100,
263 (int)((tsc_frequency + 4999) / 1000000),
264 (int)((tsc_frequency + 4999) / 10000) % 100);
267 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
276 for (i = 0; i < ncpus; ++i) {
277 struct globaldata *gd = globaldata_find(i);
278 count += *(unsigned int *)((char *)&gd->gd_cnt + offset);
284 linprocfs_domounts_callback(struct mount *mp, void *data)
287 struct sbuf *sb = (struct sbuf *)data;
288 char *to, *from, *fs;
292 from = st->f_mntfromname;
293 to = st->f_mntonname;
294 fs = st->f_fstypename;
296 if (!strcmp(st->f_fstypename, "linprocfs"))
298 else if (!strcmp(st->f_fstypename, "ext2fs"))
300 else if (!strcmp(st->f_fstypename, "msdos"))
302 else if (!strcmp(st->f_fstypename, "msdosfs"))
305 sbuf_printf(sb, "%s %s %s %s", from, to, fs,
306 st->f_flags & MNT_RDONLY ? "ro" : "rw");
308 #define OPT_ADD(name, flag) if (st->f_flags & (flag)) sbuf_printf(sb, "," name)
309 OPT_ADD("sync", MNT_SYNCHRONOUS);
310 OPT_ADD("noexec", MNT_NOEXEC);
311 OPT_ADD("nosuid", MNT_NOSUID);
312 OPT_ADD("nodev", MNT_NODEV);
313 OPT_ADD("async", MNT_ASYNC);
314 OPT_ADD("suiddir", MNT_SUIDDIR);
315 OPT_ADD("nosymfollow", MNT_NOSYMFOLLOW);
316 OPT_ADD("noatime", MNT_NOATIME);
319 sbuf_printf(sb, " 0 0\n");
325 linprocfs_domounts(struct proc *curp, struct proc *p, struct pfsnode *pfs,
331 sb = sbuf_new_auto();
333 error = mountlist_scan(linprocfs_domounts_callback, sb, MNTSCAN_FORWARD);
337 error = uiomove_frombuf(sbuf_data(sb), sbuf_len(sb), uio);
343 linprocfs_dostat(struct proc *curp, struct proc *p, struct pfsnode *pfs,
352 "cpu %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64"\n",
353 T2J(cpu_time.cp_user),
354 T2J(cpu_time.cp_nice),
355 T2J(cpu_time.cp_sys),
356 T2J(cpu_time.cp_idle));
358 for (cpu = 0; cpu < ncpus; cpu++) {
360 "cpu%d %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64"\n",
362 T2J(cputime_percpu[cpu].cp_user),
363 T2J(cputime_percpu[cpu].cp_nice),
364 T2J(cputime_percpu[cpu].cp_sys),
365 T2J(cputime_percpu[cpu].cp_idle));
375 cpucnt(offsetof(struct vmmeter, v_vnodepgsin)),
376 cpucnt(offsetof(struct vmmeter, v_vnodepgsout)),
377 cpucnt(offsetof(struct vmmeter, v_swappgsin)),
378 cpucnt(offsetof(struct vmmeter, v_swappgsout)),
379 cpucnt(offsetof(struct vmmeter, v_intr)),
380 cpucnt(offsetof(struct vmmeter, v_swtch)),
383 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
387 linprocfs_douptime(struct proc *curp, struct proc *p, struct pfsnode *pfs,
396 ps += ksprintf(ps, "%ld.%02ld %"PRIu64".%02"PRIu64"\n",
397 tv.tv_sec, tv.tv_usec / 10000,
398 T2S(cpu_time.cp_idle), T2J(cpu_time.cp_idle) % 100);
399 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
403 linprocfs_doversion(struct proc *curp, struct proc *p, struct pfsnode *pfs,
409 ps = version; /* XXX not entirely correct */
410 for (xlen = 0; ps[xlen] != '\n'; ++xlen)
413 return (uiomove_frombuf(ps, xlen, uio));
416 #define B2P(x) ((x) >> PAGE_SHIFT) /* bytes to pages */
418 linprocfs_dostatm(struct proc *curp, struct proc *p, struct pfsnode *pfs,
421 char *ps, psbuf[1024];
422 struct kinfo_proc kp;
424 lwkt_gettoken(&p->p_token);
425 fill_kinfo_proc(p, &kp);
428 ps += ksprintf(ps, "%d", p->p_pid);
429 #define PS_ADD(name, fmt, arg) ps += ksprintf(ps, " " fmt, arg)
430 PS_ADD("", "%ju", B2P((uintmax_t)(kp.kp_vm_tsize + kp.kp_vm_dsize + kp.kp_vm_ssize)));
431 PS_ADD("", "%ju", (uintmax_t)kp.kp_vm_rssize);
432 PS_ADD("", "%ju", (uintmax_t)0); /* XXX */
433 PS_ADD("", "%ju", (uintmax_t)kp.kp_vm_tsize);
434 PS_ADD("", "%ju", (uintmax_t)kp.kp_vm_dsize);
435 PS_ADD("", "%ju", (uintmax_t)kp.kp_vm_ssize);
436 PS_ADD("", "%ju", (uintmax_t)0); /* XXX */
438 ps += ksprintf(ps, "\n");
439 lwkt_reltoken(&p->p_token);
441 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
444 #define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */
446 linprocfs_doprocstat(struct proc *curp, struct proc *p, struct pfsnode *pfs,
449 vm_map_t map = &p->p_vmspace->vm_map;
450 vm_map_entry_t entry;
451 vm_offset_t start, end;
452 char *ps, psbuf[1024];
453 struct kinfo_proc kp;
455 lwkt_gettoken(&p->p_token);
456 fill_kinfo_proc(p, &kp);
460 vm_map_lock_read(map);
461 for (entry = map->header.next; entry != &map->header;
462 entry = entry->next) {
463 if (entry->maptype != VM_MAPTYPE_NORMAL &&
464 entry->maptype != VM_MAPTYPE_VPAGETABLE) {
467 /* Assuming that text is the first entry */
468 start = entry->start;
471 vm_map_unlock_read(map);
474 ps += ksprintf(ps, "%d", p->p_pid);
475 #define PS_ADD(name, fmt, arg) ps += ksprintf(ps, " " fmt, arg)
476 PS_ADD("comm", "(%s)", p->p_comm);
477 PS_ADD("statr", "%c", '0'); /* XXX */
478 PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0);
479 PS_ADD("pgrp", "%d", p->p_pgid);
480 PS_ADD("session", "%d", p->p_session->s_sid);
481 PS_ADD("tty", "%d", 0); /* XXX */
482 PS_ADD("tpgid", "%d", kp.kp_tpgid); /* XXX */
483 PS_ADD("flags", "%u", 0); /* XXX */
484 PS_ADD("minflt", "%lu", kp.kp_ru.ru_minflt); /* XXX */
485 PS_ADD("cminflt", "%lu", kp.kp_cru.ru_minflt); /* XXX */
486 PS_ADD("majflt", "%lu", kp.kp_ru.ru_majflt); /* XXX */
487 PS_ADD("cmajflt", "%lu", kp.kp_cru.ru_majflt); /* XXX */
488 PS_ADD("utime", "%d", T2J(tvtohz_high(&kp.kp_ru.ru_utime))); /* XXX */
489 PS_ADD("stime", "%d", T2J(tvtohz_high(&kp.kp_ru.ru_stime))); /* XXX */
490 PS_ADD("cutime", "%d", T2J(tvtohz_high(&kp.kp_cru.ru_utime))); /* XXX */
491 PS_ADD("cstime", "%d", T2J(tvtohz_high(&kp.kp_cru.ru_stime))); /* XXX */
492 PS_ADD("priority", "%d", 0); /* XXX */
493 PS_ADD("nice", "%d", kp.kp_nice);
494 PS_ADD("timeout", "%u", 0); /* XXX */
495 PS_ADD("itrealvalue", "%u", 0); /* XXX */
496 PS_ADD("starttime", "%d", T2J(tvtohz_high(&kp.kp_start))); /* XXX */
497 PS_ADD("vsize", "%ju", P2K((uintmax_t)(kp.kp_vm_tsize + kp.kp_vm_dsize + kp.kp_vm_ssize))); /* XXX: not sure */
498 PS_ADD("rss", "%ju", (uintmax_t)kp.kp_vm_rssize); /* XXX */
499 PS_ADD("rlim", "%lu", kp.kp_ru.ru_maxrss); /* XXX */
500 PS_ADD("startcode", "%lu", start); /* XXX */
501 PS_ADD("endcode", "%lu", end); /* XXX */
502 PS_ADD("startstack", "%lu", (u_long)p->p_vmspace->vm_minsaddr); /* XXX */
503 PS_ADD("kstkesp", "%u", 0); /* XXX */
504 PS_ADD("kstkeip", "%u", 0); /* XXX */
505 PS_ADD("signal", "%d", 0); /* XXX */
506 PS_ADD("blocked", "%d", 0); /* XXX */
507 PS_ADD("sigignore", "%d", 0); /* XXX */
508 PS_ADD("sigcatch", "%d", 0); /* XXX */
509 PS_ADD("wchan", "%u", 0); /* XXX */
510 PS_ADD("nswap", "%lu", kp.kp_ru.ru_nswap); /* XXX */
511 PS_ADD("cnswap", "%lu", kp.kp_cru.ru_nswap); /* XXX */
512 PS_ADD("exitsignal", "%d", 0); /* XXX */
513 PS_ADD("processor", "%u", kp.kp_lwp.kl_cpuid); /* XXX */
514 PS_ADD("rt_priority", "%u", 0); /* XXX */ /* >= 2.5.19 */
515 PS_ADD("policy", "%u", kp.kp_nice); /* XXX */ /* >= 2.5.19 */
517 ps += ksprintf(ps, "\n");
518 lwkt_reltoken(&p->p_token);
520 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
524 * Map process state to descriptive letter. Note that this does not
525 * quite correspond to what Linux outputs, but it's close enough.
527 static char *state_str[] = {
539 linprocfs_doprocstatus(struct proc *curp, struct proc *p, struct pfsnode *pfs,
542 char *ps, psbuf[1024];
548 lwkt_gettoken(&p->p_token);
549 if (p->p_stat > NELEM(state_str))
550 state = state_str[0];
552 state = state_str[(int)p->p_stat];
554 #define PS_ADD ps += ksprintf
555 PS_ADD(ps, "Name:\t%s\n", p->p_comm); /* XXX escape */
556 PS_ADD(ps, "State:\t%s\n", state);
561 PS_ADD(ps, "Pid:\t%d\n", p->p_pid);
562 PS_ADD(ps, "PPid:\t%d\n", p->p_pptr ? p->p_pptr->p_pid : 0);
563 PS_ADD(ps, "Uid:\t%d %d %d %d\n", p->p_ucred->cr_ruid,
565 p->p_ucred->cr_svuid,
566 /* FreeBSD doesn't have fsuid */
568 PS_ADD(ps, "Gid:\t%d %d %d %d\n", p->p_ucred->cr_rgid,
570 p->p_ucred->cr_svgid,
571 /* FreeBSD doesn't have fsgid */
573 PS_ADD(ps, "Groups:\t");
574 for (i = 0; i < p->p_ucred->cr_ngroups; i++)
575 PS_ADD(ps, "%d ", p->p_ucred->cr_groups[i]);
581 PS_ADD(ps, "VmSize:\t%8lu kB\n", B2K(p->p_vmspace->vm_map.size));
582 PS_ADD(ps, "VmLck:\t%8u kB\n", P2K(0)); /* XXX */
583 /* XXX vm_rssize seems to always be zero, how can this be? */
584 PS_ADD(ps, "VmRss:\t%8u kB\n", P2K(p->p_vmspace->vm_rssize));
585 PS_ADD(ps, "VmData:\t%8u kB\n", P2K(p->p_vmspace->vm_dsize));
586 PS_ADD(ps, "VmStk:\t%8u kB\n", P2K(p->p_vmspace->vm_ssize));
587 PS_ADD(ps, "VmExe:\t%8u kB\n", P2K(p->p_vmspace->vm_tsize));
588 PS_ADD(ps, "VmLib:\t%8u kB\n", P2K(0)); /* XXX */
593 * We support up to 128 signals, while Linux supports 32,
594 * but we only define 32 (the same 32 as Linux, to boot), so
595 * just show the lower 32 bits of each mask. XXX hack.
597 * NB: on certain platforms (Sparc at least) Linux actually
598 * supports 64 signals, but this code is a long way from
599 * running on anything but i386, so ignore that for now.
601 PS_ADD(ps, "SigPnd:\t%08x\n", p->p_siglist.__bits[0]);
602 PS_ADD(ps, "SigBlk:\t%08x\n", 0); /* XXX */
603 PS_ADD(ps, "SigIgn:\t%08x\n", p->p_sigignore.__bits[0]);
604 PS_ADD(ps, "SigCgt:\t%08x\n", p->p_sigcatch.__bits[0]);
607 * Linux also prints the capability masks, but we don't have
608 * capabilities yet, and when we do get them they're likely to
609 * be meaningless to Linux programs, so we lie. XXX
611 PS_ADD(ps, "CapInh:\t%016x\n", 0);
612 PS_ADD(ps, "CapPrm:\t%016x\n", 0);
613 PS_ADD(ps, "CapEff:\t%016x\n", 0);
615 lwkt_reltoken(&p->p_token);
617 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
621 linprocfs_doloadavg(struct proc *curp, struct proc *p,
622 struct pfsnode *pfs, struct uio *uio)
624 char *ps, psbuf[512];
627 ps += ksprintf(ps, "%d.%02d %d.%02d %d.%02d %d/%d %d\n",
628 (int)(averunnable.ldavg[0] / averunnable.fscale),
629 (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100),
630 (int)(averunnable.ldavg[1] / averunnable.fscale),
631 (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100),
632 (int)(averunnable.ldavg[2] / averunnable.fscale),
633 (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100),
634 1, /* number of running tasks */
635 -1, /* number of tasks */
636 1 /* The last pid, just kidding */
638 return(uiomove_frombuf(psbuf, ps - psbuf, uio));
642 linprocfs_donetdev(struct proc *curp, struct proc *p, struct pfsnode *pfs,
646 char ifname[16]; /* XXX LINUX_IFNAMSIZ */
650 sb = sbuf_new_auto();
652 sbuf_printf(sb, "%6s|%58s|%s\n%6s|%58s|%58s\n",
653 "Inter-", " Receive", " Transmit", " face",
654 "bytes packets errs drop fifo frame compressed",
655 "bytes packets errs drop fifo frame compressed");
658 TAILQ_FOREACH(ifp, &ifnet, if_link) {
659 linux_ifname(ifp, ifname, sizeof ifname);
660 sbuf_printf(sb, "%6.6s:", ifname);
661 sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ",
662 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
663 sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
664 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
668 error = uiomove_frombuf(sbuf_data(sb), sbuf_len(sb), uio);
674 linprocfs_dodevices(struct proc *curp, struct proc *p, struct pfsnode *pfs,
681 linprocfs_doosrelease(struct proc *curp, struct proc *p, struct pfsnode *pfs,
686 osrelease = linux_get_osrelease(curthread);
687 return(uiomove_frombuf(osrelease, strlen(osrelease)+1, uio));
691 linprocfs_doostype(struct proc *curp, struct proc *p, struct pfsnode *pfs,
696 osname = linux_get_osname(curthread);
697 return(uiomove_frombuf(osname, strlen(osname)+1, uio));
701 linprocfs_dopidmax(struct proc *curp, struct proc *p, struct pfsnode *pfs,
706 ksnprintf(buf, sizeof(buf), "%d", PID_MAX);
707 return(uiomove_frombuf(buf, strlen(buf)+1, uio));
712 linprocfs_domaps(struct proc *curp, struct proc *p, struct pfsnode *pfs,
716 vm_map_t map = &p->p_vmspace->vm_map;
717 vm_map_entry_t entry;
718 vm_ooffset_t off = 0;
720 char *name = "", *freename = NULL;
726 if (uio->uio_rw != UIO_READ)
729 sb = sbuf_new_auto();
732 vm_map_lock_read(map);
733 for (entry = map->header.next;
734 ((uio->uio_resid > 0) && (entry != &map->header));
735 entry = entry->next) {
736 vm_object_t obj, tobj, lobj;
741 if (entry->maptype != VM_MAPTYPE_NORMAL &&
742 entry->maptype != VM_MAPTYPE_VPAGETABLE) {
746 * Use map->hint as a poor man's ripout detector.
749 ostart = entry->start;
752 * Find the bottom-most object, leaving the base object
753 * and the bottom-most object held (but only one hold
754 * if they happen to be the same).
756 obj = entry->object.vm_object;
760 while (lobj && (tobj = lobj->backing_object) != NULL) {
761 KKASSERT(tobj != obj);
762 vm_object_hold(tobj);
763 if (tobj == lobj->backing_object) {
765 vm_object_lock_swap();
766 vm_object_drop(lobj);
770 vm_object_drop(tobj);
775 off = IDX_TO_OFF(lobj->size);
776 if (lobj->type == OBJT_VNODE) {
785 vn_fullpath(curproc, vp, &name, &freename, 1);
786 vn_lock(vp, LK_SHARED | LK_RETRY);
787 VOP_GETATTR(vp, &vat);
789 major = vat.va_rmajor;
790 minor = vat.va_rminor;
794 if (freename == NULL) {
795 if (entry->eflags & MAP_ENTRY_STACK)
800 vm_object_drop(lobj);
804 * We cannot safely hold the map locked while accessing
805 * userspace as a VM fault might recurse the locked map.
807 vm_map_unlock_read(map);
811 * start-end access offset major:minor inode [.text file]
813 error = sbuf_printf(sb,
814 "%08lx-%08lx %s%s%s%s %08llx %02x:%02x %llu%s%s\n",
815 (u_long)entry->start, (u_long)entry->end,
816 (entry->protection & VM_PROT_READ)?"r":"-",
817 (entry->protection & VM_PROT_WRITE)?"w":"-",
818 (entry->protection & VM_PROT_EXECUTE)?"x":"-",
824 (name && *name) ? " " : "",
829 kfree(freename, M_TEMP);
831 vm_map_lock_read(map);
836 * We use map->hint as a poor man's ripout detector. If
837 * it does not match the entry we set it to prior to
838 * unlocking the map the entry MIGHT now be stale. In
839 * this case we do an expensive lookup to find our place
840 * in the iteration again.
842 if (map->hint != entry) {
843 vm_map_entry_t reentry;
845 vm_map_lookup_entry(map, ostart, &reentry);
849 vm_map_unlock_read(map);
853 error = uiomove_frombuf(sbuf_data(sb) + uio->uio_offset,
854 sbuf_len(sb) - uio->uio_offset, uio);