linprocfs.c revision 78025
159412Smsmith/*
265577Sdes * Copyright (c) 2000 Dag-Erling Co�dan Sm�rgrav
365577Sdes * Copyright (c) 1999 Pierre Beyssac
459412Smsmith * Copyright (c) 1993 Jan-Simon Pendry
559412Smsmith * Copyright (c) 1993
659412Smsmith *	The Regents of the University of California.  All rights reserved.
759412Smsmith *
859412Smsmith * This code is derived from software contributed to Berkeley by
959412Smsmith * Jan-Simon Pendry.
1059412Smsmith *
1159412Smsmith * Redistribution and use in source and binary forms, with or without
1259412Smsmith * modification, are permitted provided that the following conditions
1359412Smsmith * are met:
1459412Smsmith * 1. Redistributions of source code must retain the above copyright
1559412Smsmith *    notice, this list of conditions and the following disclaimer.
1659412Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1759412Smsmith *    notice, this list of conditions and the following disclaimer in the
1859412Smsmith *    documentation and/or other materials provided with the distribution.
1959412Smsmith * 3. All advertising materials mentioning features or use of this software
2059412Smsmith *    must display the following acknowledgement:
2159412Smsmith *	This product includes software developed by the University of
2259412Smsmith *	California, Berkeley and its contributors.
2359412Smsmith * 4. Neither the name of the University nor the names of its contributors
2459412Smsmith *    may be used to endorse or promote products derived from this software
2559412Smsmith *    without specific prior written permission.
2659412Smsmith *
2759412Smsmith * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2859412Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2959412Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3059412Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3159412Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3259412Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3359412Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3459412Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3559412Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3659412Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3759412Smsmith * SUCH DAMAGE.
3859412Smsmith *
3959412Smsmith *	@(#)procfs_status.c	8.4 (Berkeley) 6/15/94
4059412Smsmith *
4159412Smsmith * $FreeBSD: head/sys/compat/linprocfs/linprocfs.c 78025 2001-06-10 23:23:59Z des $
4259412Smsmith */
4359412Smsmith
4459412Smsmith#include <sys/param.h>
4576166Smarkm#include <sys/systm.h>
4676166Smarkm#include <sys/blist.h>
4774135Sjlemon#include <sys/conf.h>
4865633Sdes#include <sys/dkstat.h>
4976166Smarkm#include <sys/jail.h>
5065633Sdes#include <sys/kernel.h>
5176166Smarkm#include <sys/lock.h>
5274135Sjlemon#include <sys/malloc.h>
5378025Sdes#include <sys/mount.h>
5476827Salfred#include <sys/mutex.h>
5565633Sdes#include <sys/proc.h>
5665633Sdes#include <sys/resourcevar.h>
5769995Sdes#include <sys/sbuf.h>
5876839Sjlemon#include <sys/sysctl.h>
5965633Sdes#include <sys/tty.h>
6059412Smsmith#include <sys/vnode.h>
6159412Smsmith
6259412Smsmith#include <vm/vm.h>
6359412Smsmith#include <vm/pmap.h>
6467588Sdes#include <vm/vm_map.h>
6559412Smsmith#include <vm/vm_param.h>
6660860Sdes#include <vm/vm_object.h>
6769995Sdes#include <vm/vm_zone.h>
6859412Smsmith#include <vm/swap_pager.h>
6969799Sdes
7069799Sdes#include <sys/exec.h>
7169799Sdes#include <sys/user.h>
7259412Smsmith#include <sys/vmmeter.h>
7359412Smsmith
7467589Sdes#include <machine/clock.h>
7567589Sdes#include <machine/cputypes.h>
7659412Smsmith#include <machine/md_var.h>
7759412Smsmith
7874135Sjlemon#include <sys/socket.h>
7974135Sjlemon#include <net/if.h>
8074135Sjlemon
8169995Sdes#include <compat/linux/linux_mib.h>
8278025Sdes#include <fs/pseudofs/pseudofs.h>
8359412Smsmith
8474135Sjlemonextern struct 	cdevsw *cdevsw[];
8574135Sjlemon
8667588Sdes/*
8767588Sdes * Various conversion macros
8867588Sdes */
8976405Sdes#define T2J(x) (((x) * 100UL) / (stathz ? stathz : hz))	/* ticks to jiffies */
9067588Sdes#define T2S(x) ((x) / (stathz ? stathz : hz))		/* ticks to seconds */
9167588Sdes#define B2K(x) ((x) >> 10)				/* bytes to kbytes */
9269799Sdes#define B2P(x) ((x) >> PAGE_SHIFT)			/* bytes to pages */
9367588Sdes#define P2B(x) ((x) << PAGE_SHIFT)			/* pages to bytes */
9467588Sdes#define P2K(x) ((x) << (PAGE_SHIFT - 10))		/* pages to kbytes */
9574135Sjlemon
9678025Sdesstatic int
9778025Sdeslinprocfs_domeminfo(PFS_FILL_ARGS)
9859412Smsmith{
9959412Smsmith	unsigned long memtotal;		/* total memory in bytes */
10059412Smsmith	unsigned long memused;		/* used memory in bytes */
10159412Smsmith	unsigned long memfree;		/* free memory in bytes */
10259412Smsmith	unsigned long memshared;	/* shared memory ??? */
10359412Smsmith	unsigned long buffers, cached;	/* buffer / cache memory ??? */
10476839Sjlemon	u_quad_t swaptotal;		/* total swap space in bytes */
10576839Sjlemon	u_quad_t swapused;		/* used swap space in bytes */
10676839Sjlemon	u_quad_t swapfree;		/* free swap space in bytes */
10760860Sdes	vm_object_t object;
10859412Smsmith
10959412Smsmith	memtotal = physmem * PAGE_SIZE;
11059412Smsmith	/*
11159412Smsmith	 * The correct thing here would be:
11259412Smsmith	 *
11359412Smsmith	memfree = cnt.v_free_count * PAGE_SIZE;
11459412Smsmith	memused = memtotal - memfree;
11559412Smsmith	 *
11659412Smsmith	 * but it might mislead linux binaries into thinking there
11759412Smsmith	 * is very little memory left, so we cheat and tell them that
11859412Smsmith	 * all memory that isn't wired down is free.
11959412Smsmith	 */
12059412Smsmith	memused = cnt.v_wire_count * PAGE_SIZE;
12159412Smsmith	memfree = memtotal - memused;
12264560Sbde	if (swapblist == NULL) {
12364560Sbde		swaptotal = 0;
12464560Sbde		swapfree = 0;
12564560Sbde	} else {
12676839Sjlemon		swaptotal = (u_quad_t)swapblist->bl_blocks * 1024; /* XXX why 1024? */
12776839Sjlemon		swapfree = (u_quad_t)swapblist->bl_root->u.bmu_avail * PAGE_SIZE;
12864560Sbde	}
12959412Smsmith	swapused = swaptotal - swapfree;
13060860Sdes	memshared = 0;
13171471Sjhb	TAILQ_FOREACH(object, &vm_object_list, object_list)
13260860Sdes		if (object->shadow_count > 1)
13360860Sdes			memshared += object->resident_page_count;
13460860Sdes	memshared *= PAGE_SIZE;
13559412Smsmith	/*
13659412Smsmith	 * We'd love to be able to write:
13759412Smsmith	 *
13859412Smsmith	buffers = bufspace;
13959412Smsmith	 *
14059412Smsmith	 * but bufspace is internal to vfs_bio.c and we don't feel
14159412Smsmith	 * like unstaticizing it just for linprocfs's sake.
14259412Smsmith	 */
14359412Smsmith	buffers = 0;
14459412Smsmith	cached = cnt.v_cache_count * PAGE_SIZE;
14559412Smsmith
14678025Sdes	sbuf_printf(sb,
14769799Sdes	    "        total:    used:    free:  shared: buffers:  cached:\n"
14869799Sdes	    "Mem:  %lu %lu %lu %lu %lu %lu\n"
14976839Sjlemon	    "Swap: %llu %llu %llu\n"
15069799Sdes	    "MemTotal: %9lu kB\n"
15169799Sdes	    "MemFree:  %9lu kB\n"
15269799Sdes	    "MemShared:%9lu kB\n"
15369799Sdes	    "Buffers:  %9lu kB\n"
15469799Sdes	    "Cached:   %9lu kB\n"
15576839Sjlemon	    "SwapTotal:%9llu kB\n"
15676839Sjlemon	    "SwapFree: %9llu kB\n",
15769799Sdes	    memtotal, memused, memfree, memshared, buffers, cached,
15869799Sdes	    swaptotal, swapused, swapfree,
15969799Sdes	    B2K(memtotal), B2K(memfree),
16069799Sdes	    B2K(memshared), B2K(buffers), B2K(cached),
16169799Sdes	    B2K(swaptotal), B2K(swapfree));
16259412Smsmith
16378025Sdes	return (0);
16459412Smsmith}
16559412Smsmith
16678025Sdesstatic int
16778025Sdeslinprocfs_docpuinfo(PFS_FILL_ARGS)
16859412Smsmith{
16969799Sdes	int class, i, fqmhz, fqkhz;
17059412Smsmith
17169799Sdes	/*
17269799Sdes         * We default the flags to include all non-conflicting flags,
17369799Sdes         * and the Intel versions of conflicting flags.
17469799Sdes	 */
17567589Sdes        static char *flags[] = {
17667589Sdes		"fpu",      "vme",     "de",       "pse",      "tsc",
17767589Sdes		"msr",      "pae",     "mce",      "cx8",      "apic",
17867589Sdes		"sep",      "sep",     "mtrr",     "pge",      "mca",
17967589Sdes		"cmov",     "pat",     "pse36",    "pn",       "b19",
18067589Sdes		"b20",      "b21",     "mmxext",   "mmx",      "fxsr",
18167589Sdes		"xmm",      "b26",     "b27",      "b28",      "b29",
18267589Sdes		"3dnowext", "3dnow"
18367589Sdes	};
18467589Sdes
18559412Smsmith	switch (cpu_class) {
18659412Smsmith	case CPUCLASS_286:
18767589Sdes		class = 2;
18859412Smsmith		break;
18959412Smsmith	case CPUCLASS_386:
19067589Sdes		class = 3;
19159412Smsmith		break;
19259412Smsmith	case CPUCLASS_486:
19367589Sdes		class = 4;
19459412Smsmith		break;
19559412Smsmith	case CPUCLASS_586:
19667589Sdes		class = 5;
19759412Smsmith		break;
19859412Smsmith	case CPUCLASS_686:
19967589Sdes		class = 6;
20059412Smsmith		break;
20159412Smsmith	default:
20267589Sdes                class = 0;
20359412Smsmith		break;
20459412Smsmith	}
20559412Smsmith
20678025Sdes	sbuf_printf(sb,
20769799Sdes            "processor\t: %d\n"
20869799Sdes	    "vendor_id\t: %.20s\n"
20969799Sdes	    "cpu family\t: %d\n"
21069799Sdes	    "model\t\t: %d\n"
21169799Sdes	    "stepping\t: %d\n",
21269799Sdes	    0, cpu_vendor, class, cpu, cpu_id & 0xf);
21359412Smsmith
21478025Sdes        sbuf_cat(sb,
21569799Sdes            "flags\t\t:");
21667589Sdes
21767589Sdes        if (!strcmp(cpu_vendor, "AuthenticAMD") && (class < 6)) {
21867589Sdes		flags[16] = "fcmov";
21967589Sdes        } else if (!strcmp(cpu_vendor, "CyrixInstead")) {
22067589Sdes		flags[24] = "cxmmx";
22167589Sdes        }
22267589Sdes
22367589Sdes        for (i = 0; i < 32; i++)
22467589Sdes		if (cpu_feature & (1 << i))
22578025Sdes			sbuf_printf(sb, " %s", flags[i]);
22678025Sdes	sbuf_cat(sb, "\n");
22767589Sdes        if (class >= 5) {
22869799Sdes		fqmhz = (tsc_freq + 4999) / 1000000;
22969799Sdes		fqkhz = ((tsc_freq + 4999) / 10000) % 100;
23078025Sdes		sbuf_printf(sb,
23169799Sdes		    "cpu MHz\t\t: %d.%02d\n"
23269799Sdes		    "bogomips\t: %d.%02d\n",
23369799Sdes		    fqmhz, fqkhz, fqmhz, fqkhz);
23467589Sdes        }
23569995Sdes
23678025Sdes	return (0);
23759412Smsmith}
23865633Sdes
23978025Sdesstatic int
24078025Sdeslinprocfs_dostat(PFS_FILL_ARGS)
24165633Sdes{
24278025Sdes	sbuf_printf(sb,
24369799Sdes	    "cpu %ld %ld %ld %ld\n"
24469799Sdes	    "disk 0 0 0 0\n"
24569799Sdes	    "page %u %u\n"
24669799Sdes	    "swap %u %u\n"
24769799Sdes	    "intr %u\n"
24869799Sdes	    "ctxt %u\n"
24969799Sdes	    "btime %ld\n",
25069799Sdes	    T2J(cp_time[CP_USER]),
25169799Sdes	    T2J(cp_time[CP_NICE]),
25269799Sdes	    T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/),
25369799Sdes	    T2J(cp_time[CP_IDLE]),
25469799Sdes	    cnt.v_vnodepgsin,
25569799Sdes	    cnt.v_vnodepgsout,
25669799Sdes	    cnt.v_swappgsin,
25769799Sdes	    cnt.v_swappgsout,
25869799Sdes	    cnt.v_intr,
25969799Sdes	    cnt.v_swtch,
26069799Sdes	    boottime.tv_sec);
26178025Sdes	return (0);
26265633Sdes}
26365633Sdes
26478025Sdesstatic int
26578025Sdeslinprocfs_douptime(PFS_FILL_ARGS)
26665633Sdes{
26765633Sdes	struct timeval tv;
26865633Sdes
26965633Sdes	getmicrouptime(&tv);
27078025Sdes	sbuf_printf(sb, "%ld.%02ld %ld.%02ld\n",
27169799Sdes	    tv.tv_sec, tv.tv_usec / 10000,
27269799Sdes	    T2S(cp_time[CP_IDLE]), T2J(cp_time[CP_IDLE]) % 100);
27378025Sdes	return (0);
27465633Sdes}
27565633Sdes
27678025Sdesstatic int
27778025Sdeslinprocfs_doversion(PFS_FILL_ARGS)
27865633Sdes{
27978025Sdes	sbuf_printf(sb,
28069995Sdes	    "%s version %s (des@freebsd.org) (gcc version " __VERSION__ ")"
28169995Sdes	    " #4 Sun Dec 18 04:30:00 CET 1977\n",
28269995Sdes	    linux_get_osname(curp),
28369995Sdes	    linux_get_osrelease(curp));
28478025Sdes	return (0);
28565633Sdes}
28665633Sdes
28778025Sdesstatic int
28878025Sdeslinprocfs_doloadavg(PFS_FILL_ARGS)
28976839Sjlemon{
29076839Sjlemon	int lastpid, ilen;
29176839Sjlemon
29276839Sjlemon	ilen = sizeof(lastpid);
29376839Sjlemon	if (kernel_sysctlbyname(p, "kern.lastpid",
29476839Sjlemon	    &lastpid, &ilen, NULL, 0, NULL) != 0)
29576839Sjlemon		lastpid = -1;				/* fake it */
29676839Sjlemon
29778025Sdes	sbuf_printf(sb,
29876839Sjlemon	    "%d.%02d %d.%02d %d.%02d %d/%d %d\n",
29976839Sjlemon	    (int)(averunnable.ldavg[0] / averunnable.fscale),
30076839Sjlemon	    (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100),
30176839Sjlemon	    (int)(averunnable.ldavg[1] / averunnable.fscale),
30276839Sjlemon	    (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100),
30376839Sjlemon	    (int)(averunnable.ldavg[2] / averunnable.fscale),
30476839Sjlemon	    (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100),
30576839Sjlemon	    1,				/* number of running tasks */
30676839Sjlemon	    nprocs,			/* number of tasks */
30776839Sjlemon	    lastpid			/* the last pid */
30876839Sjlemon	);
30978025Sdes
31078025Sdes	return (0);
31176839Sjlemon}
31276839Sjlemon
31378025Sdesstatic int
31478025Sdeslinprocfs_doprocstat(PFS_FILL_ARGS)
31567588Sdes{
31669995Sdes	struct kinfo_proc kp;
31767588Sdes
31869995Sdes	fill_kinfo_proc(p, &kp);
31978025Sdes	sbuf_printf(sb, "%d", p->p_pid);
32078025Sdes#define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg)
32167588Sdes	PS_ADD("comm",		"(%s)",	p->p_comm);
32267588Sdes	PS_ADD("statr",		"%c",	'0'); /* XXX */
32373923Sjhb	PROC_LOCK(p);
32473923Sjhb	PS_ADD("ppid",		"%d",	p->p_pptr ? p->p_pptr->p_pid : 0);
32573923Sjhb	PROC_UNLOCK(p);
32667588Sdes	PS_ADD("pgrp",		"%d",	p->p_pgid);
32767588Sdes	PS_ADD("session",	"%d",	p->p_session->s_sid);
32867588Sdes	PS_ADD("tty",		"%d",	0); /* XXX */
32967588Sdes	PS_ADD("tpgid",		"%d",	0); /* XXX */
33067588Sdes	PS_ADD("flags",		"%u",	0); /* XXX */
33167588Sdes	PS_ADD("minflt",	"%u",	0); /* XXX */
33267588Sdes	PS_ADD("cminflt",	"%u",	0); /* XXX */
33367588Sdes	PS_ADD("majflt",	"%u",	0); /* XXX */
33467588Sdes	PS_ADD("cminflt",	"%u",	0); /* XXX */
33567588Sdes	PS_ADD("utime",		"%d",	0); /* XXX */
33667588Sdes	PS_ADD("stime",		"%d",	0); /* XXX */
33767588Sdes	PS_ADD("cutime",	"%d",	0); /* XXX */
33867588Sdes	PS_ADD("cstime",	"%d",	0); /* XXX */
33967588Sdes	PS_ADD("counter",	"%d",	0); /* XXX */
34067588Sdes	PS_ADD("priority",	"%d",	0); /* XXX */
34167588Sdes	PS_ADD("timeout",	"%u",	0); /* XXX */
34267588Sdes	PS_ADD("itrealvalue",	"%u",	0); /* XXX */
34367588Sdes	PS_ADD("starttime",	"%d",	0); /* XXX */
34469995Sdes	PS_ADD("vsize",		"%u",	kp.ki_size);
34569995Sdes	PS_ADD("rss",		"%u",	P2K(kp.ki_rssize));
34667588Sdes	PS_ADD("rlim",		"%u",	0); /* XXX */
34769995Sdes	PS_ADD("startcode",	"%u",	(unsigned)0);
34867588Sdes	PS_ADD("endcode",	"%u",	0); /* XXX */
34967588Sdes	PS_ADD("startstack",	"%u",	0); /* XXX */
35069799Sdes	PS_ADD("esp",		"%u",	0); /* XXX */
35169799Sdes	PS_ADD("eip",		"%u",	0); /* XXX */
35267588Sdes	PS_ADD("signal",	"%d",	0); /* XXX */
35367588Sdes	PS_ADD("blocked",	"%d",	0); /* XXX */
35467588Sdes	PS_ADD("sigignore",	"%d",	0); /* XXX */
35567588Sdes	PS_ADD("sigcatch",	"%d",	0); /* XXX */
35667588Sdes	PS_ADD("wchan",		"%u",	0); /* XXX */
35769799Sdes	PS_ADD("nswap",		"%lu",	(long unsigned)0); /* XXX */
35869799Sdes	PS_ADD("cnswap",	"%lu",	(long unsigned)0); /* XXX */
35969799Sdes	PS_ADD("exitsignal",	"%d",	0); /* XXX */
36069799Sdes	PS_ADD("processor",	"%d",	0); /* XXX */
36167588Sdes#undef PS_ADD
36278025Sdes	sbuf_putc(sb, '\n');
36367588Sdes
36478025Sdes	return (0);
36567588Sdes}
36667588Sdes
36767588Sdes/*
36867588Sdes * Map process state to descriptive letter. Note that this does not
36967588Sdes * quite correspond to what Linux outputs, but it's close enough.
37067588Sdes */
37167588Sdesstatic char *state_str[] = {
37267588Sdes	"? (unknown)",
37367588Sdes	"I (idle)",
37467588Sdes	"R (running)",
37567588Sdes	"S (sleeping)",
37667588Sdes	"T (stopped)",
37767588Sdes	"Z (zombie)",
37867588Sdes	"W (waiting)",
37967588Sdes	"M (mutex)"
38067588Sdes};
38167588Sdes
38278025Sdesstatic int
38378025Sdeslinprocfs_doprocstatus(PFS_FILL_ARGS)
38467588Sdes{
38569995Sdes	struct kinfo_proc kp;
38667588Sdes	char *state;
38769799Sdes	segsz_t lsize;
38874135Sjlemon	int i;
38967588Sdes
39072200Sbmilekic	mtx_lock_spin(&sched_lock);
39167588Sdes	if (p->p_stat > sizeof state_str / sizeof *state_str)
39267588Sdes		state = state_str[0];
39367588Sdes	else
39467588Sdes		state = state_str[(int)p->p_stat];
39572200Sbmilekic	mtx_unlock_spin(&sched_lock);
39667588Sdes
39769995Sdes	fill_kinfo_proc(p, &kp);
39878025Sdes	sbuf_printf(sb, "Name:\t%s\n",		p->p_comm); /* XXX escape */
39978025Sdes	sbuf_printf(sb, "State:\t%s\n",	state);
40067588Sdes
40167588Sdes	/*
40267588Sdes	 * Credentials
40367588Sdes	 */
40478025Sdes	sbuf_printf(sb, "Pid:\t%d\n",		p->p_pid);
40571471Sjhb	PROC_LOCK(p);
40678025Sdes	sbuf_printf(sb, "PPid:\t%d\n",		p->p_pptr ?
40773923Sjhb						p->p_pptr->p_pid : 0);
40878025Sdes	sbuf_printf(sb, "Uid:\t%d %d %d %d\n", p->p_ucred->cr_ruid,
40969995Sdes			                        p->p_ucred->cr_uid,
41077183Srwatson			                        p->p_ucred->cr_svuid,
41169995Sdes			                        /* FreeBSD doesn't have fsuid */
41269995Sdes				                p->p_ucred->cr_uid);
41378025Sdes	sbuf_printf(sb, "Gid:\t%d %d %d %d\n", p->p_ucred->cr_rgid,
41469995Sdes			                        p->p_ucred->cr_gid,
41577183Srwatson			                        p->p_ucred->cr_svgid,
41669995Sdes			                        /* FreeBSD doesn't have fsgid */
41769995Sdes				                p->p_ucred->cr_gid);
41878025Sdes	sbuf_cat(sb, "Groups:\t");
41967588Sdes	for (i = 0; i < p->p_ucred->cr_ngroups; i++)
42078025Sdes		sbuf_printf(sb, "%d ", p->p_ucred->cr_groups[i]);
42171471Sjhb	PROC_UNLOCK(p);
42278025Sdes	sbuf_putc(sb, '\n');
42367588Sdes
42467588Sdes	/*
42567588Sdes	 * Memory
42669799Sdes	 *
42769799Sdes	 * While our approximation of VmLib may not be accurate (I
42869799Sdes	 * don't know of a simple way to verify it, and I'm not sure
42969799Sdes	 * it has much meaning anyway), I believe it's good enough.
43069799Sdes	 *
43169799Sdes	 * The same code that could (I think) accurately compute VmLib
43269799Sdes	 * could also compute VmLck, but I don't really care enough to
43369799Sdes	 * implement it. Submissions are welcome.
43467588Sdes	 */
43578025Sdes	sbuf_printf(sb, "VmSize:\t%8u kB\n",	B2K(kp.ki_size));
43678025Sdes	sbuf_printf(sb, "VmLck:\t%8u kB\n",	P2K(0)); /* XXX */
43778025Sdes	sbuf_printf(sb, "VmRss:\t%8u kB\n",	P2K(kp.ki_rssize));
43878025Sdes	sbuf_printf(sb, "VmData:\t%8u kB\n",	P2K(kp.ki_dsize));
43978025Sdes	sbuf_printf(sb, "VmStk:\t%8u kB\n",	P2K(kp.ki_ssize));
44078025Sdes	sbuf_printf(sb, "VmExe:\t%8u kB\n",	P2K(kp.ki_tsize));
44169995Sdes	lsize = B2P(kp.ki_size) - kp.ki_dsize -
44269995Sdes	    kp.ki_ssize - kp.ki_tsize - 1;
44378025Sdes	sbuf_printf(sb, "VmLib:\t%8u kB\n",	P2K(lsize));
44467588Sdes
44567588Sdes	/*
44667588Sdes	 * Signal masks
44767588Sdes	 *
44867588Sdes	 * We support up to 128 signals, while Linux supports 32,
44967588Sdes	 * but we only define 32 (the same 32 as Linux, to boot), so
45067588Sdes	 * just show the lower 32 bits of each mask. XXX hack.
45167588Sdes	 *
45267588Sdes	 * NB: on certain platforms (Sparc at least) Linux actually
45367588Sdes	 * supports 64 signals, but this code is a long way from
45467588Sdes	 * running on anything but i386, so ignore that for now.
45567588Sdes	 */
45671471Sjhb	PROC_LOCK(p);
45778025Sdes	sbuf_printf(sb, "SigPnd:\t%08x\n",	p->p_siglist.__bits[0]);
45869799Sdes	/*
45969799Sdes	 * I can't seem to find out where the signal mask is in
46069799Sdes	 * relation to struct proc, so SigBlk is left unimplemented.
46169799Sdes	 */
46278025Sdes	sbuf_printf(sb, "SigBlk:\t%08x\n",	0); /* XXX */
46378025Sdes	sbuf_printf(sb, "SigIgn:\t%08x\n",	p->p_sigignore.__bits[0]);
46478025Sdes	sbuf_printf(sb, "SigCgt:\t%08x\n",	p->p_sigcatch.__bits[0]);
46571471Sjhb	PROC_UNLOCK(p);
46667588Sdes
46767588Sdes	/*
46867588Sdes	 * Linux also prints the capability masks, but we don't have
46967588Sdes	 * capabilities yet, and when we do get them they're likely to
47067588Sdes	 * be meaningless to Linux programs, so we lie. XXX
47167588Sdes	 */
47278025Sdes	sbuf_printf(sb, "CapInh:\t%016x\n",	0);
47378025Sdes	sbuf_printf(sb, "CapPrm:\t%016x\n",	0);
47478025Sdes	sbuf_printf(sb, "CapEff:\t%016x\n",	0);
47578025Sdes
47678025Sdes	return (0);
47767588Sdes}
47874135Sjlemon
47978025Sdesstatic int
48078025Sdeslinprocfs_doselflink(PFS_FILL_ARGS)
48174135Sjlemon{
48278025Sdes	sbuf_printf(sb, "%ld", (long)curp->p_pid);
48378025Sdes	return (0);
48474135Sjlemon}
48574135Sjlemon
48678025Sdesstatic int
48778025Sdeslinprocfs_doexelink(PFS_FILL_ARGS)
48874135Sjlemon{
48974135Sjlemon	char *fullpath = "unknown";
49074135Sjlemon	char *freepath = NULL;
49174135Sjlemon
49278025Sdes	textvp_fullpath(p, &fullpath, &freepath);
49378025Sdes	sbuf_printf(sb, "%s", fullpath);
49474135Sjlemon	if (freepath)
49574135Sjlemon		free(freepath, M_TEMP);
49678025Sdes	return (0);
49774135Sjlemon}
49874135Sjlemon
49978025Sdesstatic int
50078025Sdeslinprocfs_donetdev(PFS_FILL_ARGS)
50174135Sjlemon{
50274135Sjlemon	struct ifnet *ifp;
50374135Sjlemon	int eth_index = 0;
50474135Sjlemon
50578025Sdes	sbuf_printf(sb,
50674135Sjlemon	    "Inter-|   Receive                                       "
50774135Sjlemon	    "         |  Transmit\n"
50874135Sjlemon	    " face |bytes    packets errs drop fifo frame compressed "
50974135Sjlemon	    "multicast|bytes    packets errs drop fifo colls carrier "
51074135Sjlemon	    "compressed\n");
51174135Sjlemon
51274135Sjlemon	TAILQ_FOREACH(ifp, &ifnet, if_link) {
51374135Sjlemon		if (strcmp(ifp->if_name, "lo") == 0) {
51478025Sdes			sbuf_printf(sb, "%6.6s:", ifp->if_name);
51574135Sjlemon		} else {
51678025Sdes			sbuf_printf(sb, "%5.5s%d:", "eth", eth_index);
51774135Sjlemon			eth_index++;
51874135Sjlemon		}
51978025Sdes		sbuf_printf(sb,
52074135Sjlemon		    "%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu "
52174135Sjlemon		    "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
52274135Sjlemon		    0, 0, 0, 0, 0, 0, 0, 0,
52374135Sjlemon		    0, 0, 0, 0, 0, 0, 0, 0);
52474135Sjlemon	}
52578025Sdes
52678025Sdes	return (0);
52774135Sjlemon}
52874135Sjlemon
52978025Sdesstatic int
53078025Sdeslinprocfs_dodevices(PFS_FILL_ARGS)
53174135Sjlemon{
53274135Sjlemon	int i;
53374135Sjlemon
53478025Sdes	sbuf_printf(sb, "Character devices:\n");
53574135Sjlemon
53678025Sdes	for (i = 0; i < NUMCDEVSW; i++)
53774135Sjlemon		if (cdevsw[i] != NULL)
53878025Sdes			sbuf_printf(sb, "%3d %s\n", i, cdevsw[i]->d_name);
53974135Sjlemon
54078025Sdes	sbuf_printf(sb, "\nBlock devices:\n");
54178025Sdes
54278025Sdes	return (0);
54374135Sjlemon}
54474135Sjlemon
54578025Sdesstatic int
54678025Sdeslinprocfs_docmdline(PFS_FILL_ARGS)
54774135Sjlemon{
54878025Sdes	sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname);
54978025Sdes	sbuf_printf(sb, " ro root=302\n");
55078025Sdes	return (0);
55178025Sdes}
55274135Sjlemon
55378025Sdes/*
55478025Sdes * Directory structure
55578025Sdes */
55674135Sjlemon
55778025Sdesstatic struct pfs_node linprocfs_proc_nodes[] = {
55878025Sdes	PFS_THIS,
55978025Sdes	PFS_PARENT,
56078025Sdes	/*	    name	flags	uid  gid  mode	data */
56178025Sdes     /* PFS_FILE(   "cmdline",  0,	0,   0,   0444, procfs_doproccmdline), */
56278025Sdes	PFS_SYMLINK("exe",	0,	0,   0,	  0444, linprocfs_doexelink),
56378025Sdes     /* PFS_FILE(   "mem",      0,	0,   0,   0444, procfs_domem), */
56478025Sdes	PFS_FILE(   "stat",     0,	0,   0,   0444, linprocfs_doprocstat),
56578025Sdes	PFS_FILE(   "status",   0,	0,   0,   0444, linprocfs_doprocstatus),
56678025Sdes	PFS_LASTNODE
56778025Sdes};
56878025Sdes
56978025Sdesstatic struct pfs_node linprocfs_net_nodes[] = {
57078025Sdes	PFS_THIS,
57178025Sdes	PFS_PARENT,
57278025Sdes	/*	    name	flags	uid  gid  mode	data */
57378025Sdes	PFS_FILE(   "dev",	0,	0,   0,   0444,	linprocfs_donetdev),
57478025Sdes	PFS_LASTNODE
57578025Sdes};
57678025Sdes
57778025Sdesstatic struct pfs_node linprocfs_root_nodes[] = {
57878025Sdes	PFS_THIS,
57978025Sdes	PFS_PARENT,
58078025Sdes	/*	    name	flags	uid  gid  mode	data */
58178025Sdes	PFS_FILE(   "cmdline",  0,      0,   0,   0444, linprocfs_docmdline),
58278025Sdes	PFS_FILE(   "cpuinfo",  0,      0,   0,   0444, linprocfs_docpuinfo),
58378025Sdes	PFS_FILE(   "devices",  0,      0,   0,   0444, linprocfs_dodevices),
58478025Sdes	PFS_FILE(   "loadavg",  0,      0,   0,   0444, linprocfs_doloadavg),
58578025Sdes	PFS_FILE(   "meminfo",  0,      0,   0,   0444, linprocfs_domeminfo),
58678025Sdes	PFS_FILE(   "stat",     0,      0,   0,   0444, linprocfs_dostat),
58778025Sdes	PFS_FILE(   "uptime",   0,      0,   0,   0444, linprocfs_douptime),
58878025Sdes	PFS_FILE(   "version",  0,      0,   0,   0444, linprocfs_doversion),
58978025Sdes	PFS_DIR(    "net",	0,	0,   0,   0555, linprocfs_net_nodes),
59078025Sdes	PFS_PROCDIR(            0,	0,   0,   0555, linprocfs_proc_nodes),
59178025Sdes	PFS_SYMLINK("self",	0,	0,   0,	  0555, linprocfs_doselflink),
59278025Sdes	PFS_LASTNODE
59378025Sdes};
59478025Sdes
59578025Sdesstatic struct pfs_node linprocfs_root =
59678025Sdes	PFS_ROOT(linprocfs_root_nodes);
59778025Sdes
59878025SdesPSEUDOFS(linprocfs, linprocfs_root);
59978025SdesMODULE_DEPEND(linprocfs, linux, 1, 1, 1);
60078025SdesMODULE_DEPEND(linprocfs, procfs, 1, 1, 1);
601