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>
67 #include <sys/devfs.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;
131 lwkt_gettoken(&vmobj_token);
132 for (object = TAILQ_FIRST(&vm_object_list); object != NULL;
133 object = TAILQ_NEXT(object, object_list)) {
134 if (object->type == OBJT_MARKER)
136 if (object->shadow_count > 1)
137 memshared += object->resident_page_count;
139 lwkt_reltoken(&vmobj_token);
140 memshared *= PAGE_SIZE;
142 * We'd love to be able to write:
146 * but bufspace is internal to vfs_bio.c and we don't feel
147 * like unstaticizing it just for linprocfs's sake.
150 cached = vmstats.v_cache_count * PAGE_SIZE;
154 " total: used: free: shared: buffers: cached:\n"
155 "Mem: %lu %lu %lu %lu %lu %lu\n"
156 "Swap: %llu %llu %llu\n"
157 "MemTotal: %9lu kB\n"
159 "MemShared:%9lu kB\n"
162 "SwapTotal:%9lu kB\n"
163 "SwapFree: %9lu kB\n",
164 memtotal, memused, memfree, memshared, buffers, cached,
165 swaptotal, swapused, swapfree,
166 B2K(memtotal), B2K(memfree),
167 B2K(memshared), B2K(buffers), B2K(cached),
168 B2K(swaptotal), B2K(swapfree));
170 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
174 linprocfs_docpuinfo(struct proc *curp, struct proc *p, struct pfsnode *pfs,
180 size_t modellen = sizeof(hwmodel);
181 int mib[] = { CTL_HW, HW_MODEL };
187 extern char *cpu_model; /* Yuck */
189 /* We default the flags to include all non-conflicting flags,
190 and the Intel versions of conflicting flags. Note the space
191 before each name; that is significant, and should be
194 static char *flags[] = {
195 "fpu", "vme", "de", "pse", "tsc",
196 "msr", "pae", "mce", "cx8", "apic",
197 "sep", "sep", "mtrr", "pge", "mca",
198 "cmov", "pat", "pse36", "pn", "b19",
199 "b20", "b21", "mmxext", "mmx", "fxsr",
200 "xmm", "b26", "b27", "b28", "b29",
204 if (uio->uio_rw != UIO_READ)
230 error = kernel_sysctl(mib, 2, hwmodel, &modellen, NULL, 0, NULL);
232 strcpy(hwmodel, "unknown");
234 for (cpu = 0; cpu < ncpus; cpu++) {
237 "vendor_id\t: %.20s\n"
242 cpu, cpu_vendor, class, cpu, hwmodel, cpu_id & 0xf);
248 if (cpu_vendor_id == CPU_VENDOR_AMD && (class < 6)) {
250 } else if (cpu_vendor_id == CPU_VENDOR_CYRIX) {
254 for (i = 0; i < 32; i++)
255 if (cpu_feature & (1 << i))
256 ps += ksprintf(ps, " %s", flags[i]);
257 ps += ksprintf(ps, "\n");
260 "cpu MHz\t\t: %d.%02d\n"
261 "bogomips\t: %d.%02d\n",
262 (int)((tsc_frequency + 4999) / 1000000),
263 (int)((tsc_frequency + 4999) / 10000) % 100,
264 (int)((tsc_frequency + 4999) / 1000000),
265 (int)((tsc_frequency + 4999) / 10000) % 100);
268 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
277 for (i = 0; i < ncpus; ++i) {
278 struct globaldata *gd = globaldata_find(i);
279 count += *(unsigned int *)((char *)&gd->gd_cnt + offset);
285 linprocfs_domounts_callback(struct mount *mp, void *data)
288 struct sbuf *sb = (struct sbuf *)data;
289 char *to, *from, *fs;
293 from = st->f_mntfromname;
294 to = st->f_mntonname;
295 fs = st->f_fstypename;
297 if (!strcmp(st->f_fstypename, "linprocfs"))
299 else if (!strcmp(st->f_fstypename, "ext2fs"))
301 else if (!strcmp(st->f_fstypename, "msdos"))
303 else if (!strcmp(st->f_fstypename, "msdosfs"))
306 sbuf_printf(sb, "%s %s %s %s", from, to, fs,
307 st->f_flags & MNT_RDONLY ? "ro" : "rw");
309 #define OPT_ADD(name, flag) if (st->f_flags & (flag)) sbuf_printf(sb, "," name)
310 OPT_ADD("sync", MNT_SYNCHRONOUS);
311 OPT_ADD("noexec", MNT_NOEXEC);
312 OPT_ADD("nosuid", MNT_NOSUID);
313 OPT_ADD("nodev", MNT_NODEV);
314 OPT_ADD("async", MNT_ASYNC);
315 OPT_ADD("suiddir", MNT_SUIDDIR);
316 OPT_ADD("nosymfollow", MNT_NOSYMFOLLOW);
317 OPT_ADD("noatime", MNT_NOATIME);
320 sbuf_printf(sb, " 0 0\n");
326 linprocfs_domounts(struct proc *curp, struct proc *p, struct pfsnode *pfs,
332 sb = sbuf_new_auto();
334 error = mountlist_scan(linprocfs_domounts_callback, sb, MNTSCAN_FORWARD);
338 error = uiomove_frombuf(sbuf_data(sb), sbuf_len(sb), uio);
344 linprocfs_dostat(struct proc *curp, struct proc *p, struct pfsnode *pfs,
353 "cpu %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64"\n",
354 T2J(cpu_time.cp_user),
355 T2J(cpu_time.cp_nice),
356 T2J(cpu_time.cp_sys),
357 T2J(cpu_time.cp_idle));
359 for (cpu = 0; cpu < ncpus; cpu++) {
361 "cpu%d %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64"\n",
363 T2J(cputime_percpu[cpu].cp_user),
364 T2J(cputime_percpu[cpu].cp_nice),
365 T2J(cputime_percpu[cpu].cp_sys),
366 T2J(cputime_percpu[cpu].cp_idle));
376 cpucnt(offsetof(struct vmmeter, v_vnodepgsin)),
377 cpucnt(offsetof(struct vmmeter, v_vnodepgsout)),
378 cpucnt(offsetof(struct vmmeter, v_swappgsin)),
379 cpucnt(offsetof(struct vmmeter, v_swappgsout)),
380 cpucnt(offsetof(struct vmmeter, v_intr)),
381 cpucnt(offsetof(struct vmmeter, v_swtch)),
384 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
388 linprocfs_douptime(struct proc *curp, struct proc *p, struct pfsnode *pfs,
397 ps += ksprintf(ps, "%ld.%02ld %"PRIu64".%02"PRIu64"\n",
398 tv.tv_sec, tv.tv_usec / 10000,
399 T2S(cpu_time.cp_idle), T2J(cpu_time.cp_idle) % 100);
400 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
404 linprocfs_doversion(struct proc *curp, struct proc *p, struct pfsnode *pfs,
410 ps = version; /* XXX not entirely correct */
411 for (xlen = 0; ps[xlen] != '\n'; ++xlen)
414 return (uiomove_frombuf(ps, xlen, uio));
417 #define B2P(x) ((x) >> PAGE_SHIFT) /* bytes to pages */
419 linprocfs_dostatm(struct proc *curp, struct proc *p, struct pfsnode *pfs,
422 char *ps, psbuf[1024];
423 struct kinfo_proc kp;
425 lwkt_gettoken(&p->p_token);
426 fill_kinfo_proc(p, &kp);
429 ps += ksprintf(ps, "%d", p->p_pid);
430 #define PS_ADD(name, fmt, arg) ps += ksprintf(ps, " " fmt, arg)
431 PS_ADD("", "%ju", B2P((uintmax_t)(kp.kp_vm_tsize + kp.kp_vm_dsize + kp.kp_vm_ssize)));
432 PS_ADD("", "%ju", (uintmax_t)kp.kp_vm_rssize);
433 PS_ADD("", "%ju", (uintmax_t)0); /* XXX */
434 PS_ADD("", "%ju", (uintmax_t)kp.kp_vm_tsize);
435 PS_ADD("", "%ju", (uintmax_t)kp.kp_vm_dsize);
436 PS_ADD("", "%ju", (uintmax_t)kp.kp_vm_ssize);
437 PS_ADD("", "%ju", (uintmax_t)0); /* XXX */
439 ps += ksprintf(ps, "\n");
440 lwkt_reltoken(&p->p_token);
442 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
445 #define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */
447 linprocfs_doprocstat(struct proc *curp, struct proc *p, struct pfsnode *pfs,
450 vm_map_t map = &p->p_vmspace->vm_map;
451 vm_map_entry_t entry;
452 vm_offset_t start, end;
453 char *ps, psbuf[1024];
454 struct kinfo_proc kp;
456 lwkt_gettoken(&p->p_token);
457 fill_kinfo_proc(p, &kp);
461 vm_map_lock_read(map);
462 for (entry = map->header.next; entry != &map->header;
463 entry = entry->next) {
464 if (entry->maptype != VM_MAPTYPE_NORMAL &&
465 entry->maptype != VM_MAPTYPE_VPAGETABLE) {
468 /* Assuming that text is the first entry */
469 start = entry->start;
472 vm_map_unlock_read(map);
475 ps += ksprintf(ps, "%d", p->p_pid);
476 #define PS_ADD(name, fmt, arg) ps += ksprintf(ps, " " fmt, arg)
477 PS_ADD("comm", "(%s)", p->p_comm);
478 PS_ADD("statr", "%c", '0'); /* XXX */
479 PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0);
480 PS_ADD("pgrp", "%d", p->p_pgid);
481 PS_ADD("session", "%d", p->p_session->s_sid);
482 PS_ADD("tty", "%d", 0); /* XXX */
483 PS_ADD("tpgid", "%d", kp.kp_tpgid); /* XXX */
484 PS_ADD("flags", "%u", 0); /* XXX */
485 PS_ADD("minflt", "%lu", kp.kp_ru.ru_minflt); /* XXX */
486 PS_ADD("cminflt", "%lu", kp.kp_cru.ru_minflt); /* XXX */
487 PS_ADD("majflt", "%lu", kp.kp_ru.ru_majflt); /* XXX */
488 PS_ADD("cmajflt", "%lu", kp.kp_cru.ru_majflt); /* XXX */
489 PS_ADD("utime", "%d", T2J(tvtohz_high(&kp.kp_ru.ru_utime))); /* XXX */
490 PS_ADD("stime", "%d", T2J(tvtohz_high(&kp.kp_ru.ru_stime))); /* XXX */
491 PS_ADD("cutime", "%d", T2J(tvtohz_high(&kp.kp_cru.ru_utime))); /* XXX */
492 PS_ADD("cstime", "%d", T2J(tvtohz_high(&kp.kp_cru.ru_stime))); /* XXX */
493 PS_ADD("priority", "%d", 0); /* XXX */
494 PS_ADD("nice", "%d", kp.kp_nice);
495 PS_ADD("timeout", "%u", 0); /* XXX */
496 PS_ADD("itrealvalue", "%u", 0); /* XXX */
497 PS_ADD("starttime", "%d", T2J(tvtohz_high(&kp.kp_start))); /* XXX */
498 PS_ADD("vsize", "%ju", P2K((uintmax_t)(kp.kp_vm_tsize + kp.kp_vm_dsize + kp.kp_vm_ssize))); /* XXX: not sure */
499 PS_ADD("rss", "%ju", (uintmax_t)kp.kp_vm_rssize); /* XXX */
500 PS_ADD("rlim", "%lu", kp.kp_ru.ru_maxrss); /* XXX */
501 PS_ADD("startcode", "%lu", start); /* XXX */
502 PS_ADD("endcode", "%lu", end); /* XXX */
503 PS_ADD("startstack", "%lu", (u_long)p->p_vmspace->vm_minsaddr); /* XXX */
504 PS_ADD("kstkesp", "%u", 0); /* XXX */
505 PS_ADD("kstkeip", "%u", 0); /* XXX */
506 PS_ADD("signal", "%d", 0); /* XXX */
507 PS_ADD("blocked", "%d", 0); /* XXX */
508 PS_ADD("sigignore", "%d", 0); /* XXX */
509 PS_ADD("sigcatch", "%d", 0); /* XXX */
510 PS_ADD("wchan", "%u", 0); /* XXX */
511 PS_ADD("nswap", "%lu", kp.kp_ru.ru_nswap); /* XXX */
512 PS_ADD("cnswap", "%lu", kp.kp_cru.ru_nswap); /* XXX */
513 PS_ADD("exitsignal", "%d", 0); /* XXX */
514 PS_ADD("processor", "%u", kp.kp_lwp.kl_cpuid); /* XXX */
515 PS_ADD("rt_priority", "%u", 0); /* XXX */ /* >= 2.5.19 */
516 PS_ADD("policy", "%u", kp.kp_nice); /* XXX */ /* >= 2.5.19 */
518 ps += ksprintf(ps, "\n");
519 lwkt_reltoken(&p->p_token);
521 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
525 * Map process state to descriptive letter. Note that this does not
526 * quite correspond to what Linux outputs, but it's close enough.
528 static char *state_str[] = {
540 linprocfs_doprocstatus(struct proc *curp, struct proc *p, struct pfsnode *pfs,
543 char *ps, psbuf[1024];
549 lwkt_gettoken(&p->p_token);
550 if (p->p_stat > NELEM(state_str))
551 state = state_str[0];
553 state = state_str[(int)p->p_stat];
555 #define PS_ADD ps += ksprintf
556 PS_ADD(ps, "Name:\t%s\n", p->p_comm); /* XXX escape */
557 PS_ADD(ps, "State:\t%s\n", state);
562 PS_ADD(ps, "Pid:\t%d\n", p->p_pid);
563 PS_ADD(ps, "PPid:\t%d\n", p->p_pptr ? p->p_pptr->p_pid : 0);
564 PS_ADD(ps, "Uid:\t%d %d %d %d\n", p->p_ucred->cr_ruid,
566 p->p_ucred->cr_svuid,
567 /* FreeBSD doesn't have fsuid */
569 PS_ADD(ps, "Gid:\t%d %d %d %d\n", p->p_ucred->cr_rgid,
571 p->p_ucred->cr_svgid,
572 /* FreeBSD doesn't have fsgid */
574 PS_ADD(ps, "Groups:\t");
575 for (i = 0; i < p->p_ucred->cr_ngroups; i++)
576 PS_ADD(ps, "%d ", p->p_ucred->cr_groups[i]);
582 PS_ADD(ps, "VmSize:\t%8lu kB\n", B2K(p->p_vmspace->vm_map.size));
583 PS_ADD(ps, "VmLck:\t%8u kB\n", P2K(0)); /* XXX */
584 /* XXX vm_rssize seems to always be zero, how can this be? */
585 PS_ADD(ps, "VmRss:\t%8u kB\n", P2K(p->p_vmspace->vm_rssize));
586 PS_ADD(ps, "VmData:\t%8u kB\n", P2K(p->p_vmspace->vm_dsize));
587 PS_ADD(ps, "VmStk:\t%8u kB\n", P2K(p->p_vmspace->vm_ssize));
588 PS_ADD(ps, "VmExe:\t%8u kB\n", P2K(p->p_vmspace->vm_tsize));
589 PS_ADD(ps, "VmLib:\t%8u kB\n", P2K(0)); /* XXX */
594 * We support up to 128 signals, while Linux supports 32,
595 * but we only define 32 (the same 32 as Linux, to boot), so
596 * just show the lower 32 bits of each mask. XXX hack.
598 * NB: on certain platforms (Sparc at least) Linux actually
599 * supports 64 signals, but this code is a long way from
600 * running on anything but i386, so ignore that for now.
602 PS_ADD(ps, "SigPnd:\t%08x\n", p->p_siglist.__bits[0]);
603 PS_ADD(ps, "SigBlk:\t%08x\n", 0); /* XXX */
604 PS_ADD(ps, "SigIgn:\t%08x\n", p->p_sigignore.__bits[0]);
605 PS_ADD(ps, "SigCgt:\t%08x\n", p->p_sigcatch.__bits[0]);
608 * Linux also prints the capability masks, but we don't have
609 * capabilities yet, and when we do get them they're likely to
610 * be meaningless to Linux programs, so we lie. XXX
612 PS_ADD(ps, "CapInh:\t%016x\n", 0);
613 PS_ADD(ps, "CapPrm:\t%016x\n", 0);
614 PS_ADD(ps, "CapEff:\t%016x\n", 0);
616 lwkt_reltoken(&p->p_token);
618 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
622 linprocfs_doloadavg(struct proc *curp, struct proc *p,
623 struct pfsnode *pfs, struct uio *uio)
625 char *ps, psbuf[512];
628 ps += ksprintf(ps, "%d.%02d %d.%02d %d.%02d %d/%d %d\n",
629 (int)(averunnable.ldavg[0] / averunnable.fscale),
630 (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100),
631 (int)(averunnable.ldavg[1] / averunnable.fscale),
632 (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100),
633 (int)(averunnable.ldavg[2] / averunnable.fscale),
634 (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100),
635 1, /* number of running tasks */
636 -1, /* number of tasks */
637 1 /* The last pid, just kidding */
639 return(uiomove_frombuf(psbuf, ps - psbuf, uio));
643 linprocfs_donetdev(struct proc *curp, struct proc *p, struct pfsnode *pfs,
647 char ifname[16]; /* XXX LINUX_IFNAMSIZ */
651 sb = sbuf_new_auto();
653 sbuf_printf(sb, "%6s|%58s|%s\n%6s|%58s|%58s\n",
654 "Inter-", " Receive", " Transmit", " face",
655 "bytes packets errs drop fifo frame compressed",
656 "bytes packets errs drop fifo frame compressed");
659 TAILQ_FOREACH(ifp, &ifnet, if_link) {
660 linux_ifname(ifp, ifname, sizeof ifname);
661 sbuf_printf(sb, "%6.6s:", ifname);
662 sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ",
663 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
664 sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
665 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
669 error = uiomove_frombuf(sbuf_data(sb), sbuf_len(sb), uio);
675 linprocfs_dodevices_callback(char *name, cdev_t dev, bool is_alias, void *arg)
677 struct sbuf *sb = arg;
679 sbuf_printf(sb, "%3d %s\n", dev->si_umajor, name);
683 linprocfs_dodevices(struct proc *curp, struct proc *p, struct pfsnode *pfs,
689 sb = sbuf_new_auto();
690 sbuf_printf(sb, "Character devices:\n");
691 devfs_scan_callback(linprocfs_dodevices_callback, sb);
692 sbuf_printf(sb, "\nBlock devices:\n");
694 error = uiomove_frombuf(sbuf_data(sb), sbuf_len(sb), uio);
700 linprocfs_doosrelease(struct proc *curp, struct proc *p, struct pfsnode *pfs,
705 osrelease = linux_get_osrelease(curthread);
706 return(uiomove_frombuf(osrelease, strlen(osrelease)+1, uio));
710 linprocfs_doostype(struct proc *curp, struct proc *p, struct pfsnode *pfs,
715 osname = linux_get_osname(curthread);
716 return(uiomove_frombuf(osname, strlen(osname)+1, uio));
720 linprocfs_dopidmax(struct proc *curp, struct proc *p, struct pfsnode *pfs,
725 ksnprintf(buf, sizeof(buf), "%d", PID_MAX);
726 return(uiomove_frombuf(buf, strlen(buf)+1, uio));
730 linprocfs_domaps(struct proc *curp, struct proc *p, struct pfsnode *pfs,
734 vm_map_t map = &p->p_vmspace->vm_map;
735 vm_map_entry_t entry;
736 vm_ooffset_t off = 0;
738 char *name = "", *freename = NULL;
744 if (uio->uio_rw != UIO_READ)
747 sb = sbuf_new_auto();
750 vm_map_lock_read(map);
751 for (entry = map->header.next;
752 ((uio->uio_resid > 0) && (entry != &map->header));
753 entry = entry->next) {
754 vm_object_t obj, tobj, lobj;
759 if (entry->maptype != VM_MAPTYPE_NORMAL &&
760 entry->maptype != VM_MAPTYPE_VPAGETABLE) {
764 * Use map->hint as a poor man's ripout detector.
767 ostart = entry->start;
770 * Find the bottom-most object, leaving the base object
771 * and the bottom-most object held (but only one hold
772 * if they happen to be the same).
774 obj = entry->object.vm_object;
779 while (lobj && (tobj = lobj->backing_object) != NULL) {
780 KKASSERT(tobj != obj);
781 vm_object_hold(tobj);
782 if (tobj == lobj->backing_object) {
784 vm_object_lock_swap();
785 vm_object_drop(lobj);
789 vm_object_drop(tobj);
794 off = IDX_TO_OFF(lobj->size);
795 if (lobj->type == OBJT_VNODE) {
804 vn_fullpath(curproc, vp, &name, &freename, 1);
805 vn_lock(vp, LK_SHARED | LK_RETRY);
806 VOP_GETATTR(vp, &vat);
808 major = vat.va_rmajor;
809 minor = vat.va_rminor;
813 if (freename == NULL) {
814 if (entry->eflags & MAP_ENTRY_STACK)
819 vm_object_drop(lobj);
824 * We cannot safely hold the map locked while accessing
825 * userspace as a VM fault might recurse the locked map.
827 vm_map_unlock_read(map);
831 * start-end access offset major:minor inode [.text file]
833 error = sbuf_printf(sb,
834 "%08lx-%08lx %s%s%s%s %08llx %02x:%02x %llu%s%s\n",
835 (u_long)entry->start, (u_long)entry->end,
836 (entry->protection & VM_PROT_READ)?"r":"-",
837 (entry->protection & VM_PROT_WRITE)?"w":"-",
838 (entry->protection & VM_PROT_EXECUTE)?"x":"-",
844 (name && *name) ? " " : "",
849 kfree(freename, M_TEMP);
851 vm_map_lock_read(map);
856 * We use map->hint as a poor man's ripout detector. If
857 * it does not match the entry we set it to prior to
858 * unlocking the map the entry MIGHT now be stale. In
859 * this case we do an expensive lookup to find our place
860 * in the iteration again.
862 if (map->hint != entry) {
863 vm_map_entry_t reentry;
865 vm_map_lookup_entry(map, ostart, &reentry);
869 vm_map_unlock_read(map);
873 error = uiomove_frombuf(sbuf_data(sb) + uio->uio_offset,
874 sbuf_len(sb) - uio->uio_offset, uio);