linprocfs.c revision 119923
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
42116173Sobrien#include <sys/cdefs.h>
43116173Sobrien__FBSDID("$FreeBSD: head/sys/compat/linprocfs/linprocfs.c 119923 2003-09-09 19:22:55Z des $");
44116173Sobrien
4559412Smsmith#include <sys/param.h>
4683926Sdes#include <sys/queue.h>
4776166Smarkm#include <sys/blist.h>
4874135Sjlemon#include <sys/conf.h>
4983926Sdes#include <sys/exec.h>
50119911Sdes#include <sys/filedesc.h>
5176166Smarkm#include <sys/jail.h>
5265633Sdes#include <sys/kernel.h>
5383926Sdes#include <sys/linker.h>
5476166Smarkm#include <sys/lock.h>
5574135Sjlemon#include <sys/malloc.h>
5678025Sdes#include <sys/mount.h>
5776827Salfred#include <sys/mutex.h>
5885289Sdes#include <sys/namei.h>
5965633Sdes#include <sys/proc.h>
6065633Sdes#include <sys/resourcevar.h>
6169995Sdes#include <sys/sbuf.h>
6283926Sdes#include <sys/socket.h>
6376839Sjlemon#include <sys/sysctl.h>
6483926Sdes#include <sys/systm.h>
6565633Sdes#include <sys/tty.h>
6683926Sdes#include <sys/user.h>
6783926Sdes#include <sys/vmmeter.h>
6859412Smsmith#include <sys/vnode.h>
6959412Smsmith
7083926Sdes#include <net/if.h>
7183926Sdes
7259412Smsmith#include <vm/vm.h>
7359412Smsmith#include <vm/pmap.h>
7467588Sdes#include <vm/vm_map.h>
7559412Smsmith#include <vm/vm_param.h>
7660860Sdes#include <vm/vm_object.h>
7759412Smsmith#include <vm/swap_pager.h>
7869799Sdes
7967589Sdes#include <machine/clock.h>
8078113Sdes
8178113Sdes#ifdef __alpha__
8278113Sdes#include <machine/alpha_cpu.h>
8378113Sdes#include <machine/cpuconf.h>
8478113Sdes#include <machine/rpb.h>
8578113Sdesextern int ncpus;
8678113Sdes#endif /* __alpha__ */
8778113Sdes
8878113Sdes#ifdef __i386__
8967589Sdes#include <machine/cputypes.h>
9059412Smsmith#include <machine/md_var.h>
9178113Sdes#endif /* __i386__ */
9259412Smsmith
9387275Srwatson#include <machine/../linux/linux.h>
9485129Sdes#include <compat/linux/linux_ioctl.h>
9569995Sdes#include <compat/linux/linux_mib.h>
9685289Sdes#include <compat/linux/linux_util.h>
9778025Sdes#include <fs/pseudofs/pseudofs.h>
9884248Sdes#include <fs/procfs/procfs.h>
9959412Smsmith
10067588Sdes/*
10167588Sdes * Various conversion macros
10267588Sdes */
10376405Sdes#define T2J(x) (((x) * 100UL) / (stathz ? stathz : hz))	/* ticks to jiffies */
10467588Sdes#define T2S(x) ((x) / (stathz ? stathz : hz))		/* ticks to seconds */
10567588Sdes#define B2K(x) ((x) >> 10)				/* bytes to kbytes */
10669799Sdes#define B2P(x) ((x) >> PAGE_SHIFT)			/* bytes to pages */
10767588Sdes#define P2B(x) ((x) << PAGE_SHIFT)			/* pages to bytes */
10867588Sdes#define P2K(x) ((x) << (PAGE_SHIFT - 10))		/* pages to kbytes */
10974135Sjlemon
11078113Sdes/*
11178113Sdes * Filler function for proc/meminfo
11278113Sdes */
11378025Sdesstatic int
11478025Sdeslinprocfs_domeminfo(PFS_FILL_ARGS)
11559412Smsmith{
11659412Smsmith	unsigned long memtotal;		/* total memory in bytes */
11759412Smsmith	unsigned long memused;		/* used memory in bytes */
11859412Smsmith	unsigned long memfree;		/* free memory in bytes */
11959412Smsmith	unsigned long memshared;	/* shared memory ??? */
12059412Smsmith	unsigned long buffers, cached;	/* buffer / cache memory ??? */
121113574Sjhb	unsigned long long swaptotal;	/* total swap space in bytes */
122113574Sjhb	unsigned long long swapused;	/* used swap space in bytes */
123113574Sjhb	unsigned long long swapfree;	/* free swap space in bytes */
12460860Sdes	vm_object_t object;
125117723Sphk	int i, j;
12659412Smsmith
12759412Smsmith	memtotal = physmem * PAGE_SIZE;
12859412Smsmith	/*
12959412Smsmith	 * The correct thing here would be:
13059412Smsmith	 *
13159412Smsmith	memfree = cnt.v_free_count * PAGE_SIZE;
13259412Smsmith	memused = memtotal - memfree;
13359412Smsmith	 *
13459412Smsmith	 * but it might mislead linux binaries into thinking there
13559412Smsmith	 * is very little memory left, so we cheat and tell them that
13659412Smsmith	 * all memory that isn't wired down is free.
13759412Smsmith	 */
13859412Smsmith	memused = cnt.v_wire_count * PAGE_SIZE;
13959412Smsmith	memfree = memtotal - memused;
140117723Sphk	swap_pager_status(&i, &j);
141117723Sphk	swaptotal = i * PAGE_SIZE;
142117723Sphk	swapused = j * PAGE_SIZE;
143117723Sphk	swapfree = swaptotal - swapused;
14460860Sdes	memshared = 0;
14571471Sjhb	TAILQ_FOREACH(object, &vm_object_list, object_list)
14660860Sdes		if (object->shadow_count > 1)
14760860Sdes			memshared += object->resident_page_count;
14860860Sdes	memshared *= PAGE_SIZE;
14959412Smsmith	/*
15059412Smsmith	 * We'd love to be able to write:
15159412Smsmith	 *
15259412Smsmith	buffers = bufspace;
15359412Smsmith	 *
15459412Smsmith	 * but bufspace is internal to vfs_bio.c and we don't feel
15559412Smsmith	 * like unstaticizing it just for linprocfs's sake.
15659412Smsmith	 */
15759412Smsmith	buffers = 0;
15859412Smsmith	cached = cnt.v_cache_count * PAGE_SIZE;
15959412Smsmith
16078025Sdes	sbuf_printf(sb,
16178031Sdes	    "	     total:    used:	free:  shared: buffers:	 cached:\n"
16269799Sdes	    "Mem:  %lu %lu %lu %lu %lu %lu\n"
16376839Sjlemon	    "Swap: %llu %llu %llu\n"
16469799Sdes	    "MemTotal: %9lu kB\n"
16569799Sdes	    "MemFree:  %9lu kB\n"
16669799Sdes	    "MemShared:%9lu kB\n"
16769799Sdes	    "Buffers:  %9lu kB\n"
16869799Sdes	    "Cached:   %9lu kB\n"
16976839Sjlemon	    "SwapTotal:%9llu kB\n"
17076839Sjlemon	    "SwapFree: %9llu kB\n",
17169799Sdes	    memtotal, memused, memfree, memshared, buffers, cached,
17269799Sdes	    swaptotal, swapused, swapfree,
17369799Sdes	    B2K(memtotal), B2K(memfree),
17469799Sdes	    B2K(memshared), B2K(buffers), B2K(cached),
17569799Sdes	    B2K(swaptotal), B2K(swapfree));
17659412Smsmith
17778025Sdes	return (0);
17859412Smsmith}
17959412Smsmith
18078113Sdes#ifdef __alpha__
181119008Smarcelextern struct rpb *hwrpb;
18278113Sdes/*
18378113Sdes * Filler function for proc/cpuinfo (Alpha version)
18478113Sdes */
18578025Sdesstatic int
18678025Sdeslinprocfs_docpuinfo(PFS_FILL_ARGS)
18759412Smsmith{
18878113Sdes	u_int64_t type, major;
18978113Sdes	struct pcs *pcsp;
19078113Sdes	const char *model, *sysname;
19178113Sdes
19278113Sdes	static const char *cpuname[] = {
19378113Sdes		"EV3", "EV4", "Simulate", "LCA4", "EV5", "EV45", "EV56",
19478113Sdes		"EV6", "PCA56", "PCA57", "EV67", "EV68CB", "EV68AL"
19578113Sdes	};
19678113Sdes
19778113Sdes	pcsp = LOCATE_PCS(hwrpb, hwrpb->rpb_primary_cpu_id);
19878113Sdes	type = pcsp->pcs_proc_type;
19978113Sdes	major = (type & PCS_PROC_MAJOR) >> PCS_PROC_MAJORSHIFT;
20078113Sdes	if (major < sizeof(cpuname)/sizeof(char *)) {
20178113Sdes		model = cpuname[major - 1];
20278113Sdes	} else {
20378113Sdes		model = "unknown";
20478113Sdes	}
205119068Sdes
20678113Sdes	sysname = alpha_dsr_sysname();
207119068Sdes
20878113Sdes	sbuf_printf(sb,
20978113Sdes	    "cpu\t\t\t: Alpha\n"
21078113Sdes	    "cpu model\t\t: %s\n"
21178113Sdes	    "cpu variation\t\t: %ld\n"
212113574Sjhb	    "cpu revision\t\t: %d\n"
21378113Sdes	    "cpu serial number\t: %s\n"
21478113Sdes	    "system type\t\t: %s\n"
21578113Sdes	    "system variation\t: %s\n"
216113574Sjhb	    "system revision\t\t: %d\n"
21778113Sdes	    "system serial number\t: %s\n"
21878113Sdes	    "cycle frequency [Hz]\t: %lu\n"
219113574Sjhb	    "timer frequency [Hz]\t: %u\n"
22078113Sdes	    "page size [bytes]\t: %ld\n"
22178113Sdes	    "phys. address bits\t: %ld\n"
22278113Sdes	    "max. addr. space #\t: %ld\n"
223113574Sjhb	    "BogoMIPS\t\t: %u.%02u\n"
224113574Sjhb	    "kernel unaligned acc\t: %d (pc=%x,va=%x)\n"
225113574Sjhb	    "user unaligned acc\t: %d (pc=%x,va=%x)\n"
22678113Sdes	    "platform string\t\t: %s\n"
22778113Sdes	    "cpus detected\t\t: %d\n"
22878113Sdes	    ,
22978113Sdes	    model,
23078113Sdes	    pcsp->pcs_proc_var,
23178113Sdes	    *(int *)hwrpb->rpb_revision,
23278113Sdes	    " ",
23378113Sdes	    " ",
23478113Sdes	    "0",
23578113Sdes	    0,
23678113Sdes	    " ",
23778113Sdes	    hwrpb->rpb_cc_freq,
23878113Sdes	    hz,
23978113Sdes	    hwrpb->rpb_page_size,
24078113Sdes	    hwrpb->rpb_phys_addr_size,
24178113Sdes	    hwrpb->rpb_max_asn,
24278113Sdes	    0, 0,
24378113Sdes	    0, 0, 0,
24478113Sdes	    0, 0, 0,
24578113Sdes	    sysname,
24678113Sdes	    ncpus);
24778113Sdes	return (0);
24878113Sdes}
24978113Sdes#endif /* __alpha__ */
25078113Sdes
25178113Sdes#ifdef __i386__
25278113Sdes/*
25378113Sdes * Filler function for proc/cpuinfo (i386 version)
25478113Sdes */
25578113Sdesstatic int
25678113Sdeslinprocfs_docpuinfo(PFS_FILL_ARGS)
25778113Sdes{
258118421Sdes	int class, fqmhz, fqkhz, ncpu;
259118421Sdes	int name[2], olen, plen;
260118421Sdes	int i;
26159412Smsmith
262118421Sdes	name[0] = CTL_HW;
263118421Sdes	name[1] = HW_NCPU;
264118421Sdes	if (kernel_sysctl(td, name, 2, &ncpu, &olen, NULL, 0, &plen) != 0)
265118421Sdes		ncpu = 1;
266118421Sdes
26769799Sdes	/*
26878031Sdes	 * We default the flags to include all non-conflicting flags,
26978031Sdes	 * and the Intel versions of conflicting flags.
27069799Sdes	 */
27178031Sdes	static char *flags[] = {
27278031Sdes		"fpu",	    "vme",     "de",	   "pse",      "tsc",
27378031Sdes		"msr",	    "pae",     "mce",	   "cx8",      "apic",
27478031Sdes		"sep",	    "sep",     "mtrr",	   "pge",      "mca",
27578031Sdes		"cmov",	    "pat",     "pse36",	   "pn",       "b19",
27678031Sdes		"b20",	    "b21",     "mmxext",   "mmx",      "fxsr",
27778031Sdes		"xmm",	    "b26",     "b27",	   "b28",      "b29",
27867589Sdes		"3dnowext", "3dnow"
27967589Sdes	};
28067589Sdes
28159412Smsmith	switch (cpu_class) {
28259412Smsmith	case CPUCLASS_286:
28367589Sdes		class = 2;
28459412Smsmith		break;
28559412Smsmith	case CPUCLASS_386:
28667589Sdes		class = 3;
28759412Smsmith		break;
28859412Smsmith	case CPUCLASS_486:
28967589Sdes		class = 4;
29059412Smsmith		break;
29159412Smsmith	case CPUCLASS_586:
29267589Sdes		class = 5;
29359412Smsmith		break;
29459412Smsmith	case CPUCLASS_686:
29567589Sdes		class = 6;
29659412Smsmith		break;
29759412Smsmith	default:
29878031Sdes		class = 0;
29959412Smsmith		break;
30059412Smsmith	}
30159412Smsmith
302118421Sdes	for (i = 0; i < ncpu; ++i) {
303118421Sdes		sbuf_printf(sb,
304118421Sdes		    "processor\t: %d\n"
305118421Sdes		    "vendor_id\t: %.20s\n"
306118421Sdes		    "cpu family\t: %d\n"
307118421Sdes		    "model\t\t: %d\n"
308118421Sdes		    "stepping\t: %d\n",
309118421Sdes		    i, cpu_vendor, class, cpu, cpu_id & 0xf);
310118421Sdes		/* XXX per-cpu vendor / class / id? */
311118421Sdes	}
31259412Smsmith
31378031Sdes	sbuf_cat(sb,
31478031Sdes	    "flags\t\t:");
31567589Sdes
31678031Sdes	if (!strcmp(cpu_vendor, "AuthenticAMD") && (class < 6)) {
31767589Sdes		flags[16] = "fcmov";
31878031Sdes	} else if (!strcmp(cpu_vendor, "CyrixInstead")) {
31967589Sdes		flags[24] = "cxmmx";
32078031Sdes	}
321119068Sdes
32278031Sdes	for (i = 0; i < 32; i++)
32367589Sdes		if (cpu_feature & (1 << i))
32478025Sdes			sbuf_printf(sb, " %s", flags[i]);
32578025Sdes	sbuf_cat(sb, "\n");
32678031Sdes	if (class >= 5) {
32769799Sdes		fqmhz = (tsc_freq + 4999) / 1000000;
32869799Sdes		fqkhz = ((tsc_freq + 4999) / 10000) % 100;
32978025Sdes		sbuf_printf(sb,
33069799Sdes		    "cpu MHz\t\t: %d.%02d\n"
33169799Sdes		    "bogomips\t: %d.%02d\n",
33269799Sdes		    fqmhz, fqkhz, fqmhz, fqkhz);
33378031Sdes	}
33469995Sdes
33578025Sdes	return (0);
33659412Smsmith}
33778113Sdes#endif /* __i386__ */
33865633Sdes
33978113Sdes/*
34085289Sdes * Filler function for proc/mtab
34185289Sdes *
34285289Sdes * This file doesn't exist in Linux' procfs, but is included here so
34385289Sdes * users can symlink /compat/linux/etc/mtab to /proc/mtab
34485289Sdes */
34585289Sdesstatic int
34685289Sdeslinprocfs_domtab(PFS_FILL_ARGS)
34785289Sdes{
34885289Sdes	struct nameidata nd;
34985289Sdes	struct mount *mp;
35091334Sjulian	const char *lep;
35191334Sjulian	char *dlep, *flep, *mntto, *mntfrom, *fstype;
35285289Sdes	size_t lep_len;
35385289Sdes	int error;
35485289Sdes
35585289Sdes	/* resolve symlinks etc. in the emulation tree prefix */
35685289Sdes	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, td);
35785289Sdes	flep = NULL;
35891334Sjulian	if (namei(&nd) != 0 || vn_fullpath(td, nd.ni_vp, &dlep, &flep) == -1)
35985289Sdes		lep = linux_emul_path;
36091334Sjulian	else
36191334Sjulian		lep = dlep;
36285289Sdes	lep_len = strlen(lep);
363119068Sdes
36485289Sdes	mtx_lock(&mountlist_mtx);
36585289Sdes	error = 0;
36685289Sdes	TAILQ_FOREACH(mp, &mountlist, mnt_list) {
36785289Sdes		error = VFS_STATFS(mp, &mp->mnt_stat, td);
36885289Sdes		if (error)
36985289Sdes			break;
37085289Sdes
37185289Sdes		/* determine device name */
37285289Sdes		mntfrom = mp->mnt_stat.f_mntfromname;
373119068Sdes
37485289Sdes		/* determine mount point */
37585289Sdes		mntto = mp->mnt_stat.f_mntonname;
37685289Sdes		if (strncmp(mntto, lep, lep_len) == 0 &&
37785289Sdes		    mntto[lep_len] == '/')
37885289Sdes			mntto += lep_len;
37985289Sdes
38085289Sdes		/* determine fs type */
38185289Sdes		fstype = mp->mnt_stat.f_fstypename;
38285289Sdes		if (strcmp(fstype, pn->pn_info->pi_name) == 0)
38385289Sdes			mntfrom = fstype = "proc";
38485289Sdes		else if (strcmp(fstype, "procfs") == 0)
38585289Sdes			continue;
386119068Sdes
38785289Sdes		sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype,
38885289Sdes		    mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
38985289Sdes#define ADD_OPTION(opt, name) \
39085289Sdes	if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name);
39185289Sdes		ADD_OPTION(MNT_SYNCHRONOUS,	"sync");
39285289Sdes		ADD_OPTION(MNT_NOEXEC,		"noexec");
39385289Sdes		ADD_OPTION(MNT_NOSUID,		"nosuid");
39485289Sdes		ADD_OPTION(MNT_NODEV,		"nodev");
39585289Sdes		ADD_OPTION(MNT_UNION,		"union");
39685289Sdes		ADD_OPTION(MNT_ASYNC,		"async");
39785289Sdes		ADD_OPTION(MNT_SUIDDIR,		"suiddir");
39885289Sdes		ADD_OPTION(MNT_NOSYMFOLLOW,	"nosymfollow");
39985289Sdes		ADD_OPTION(MNT_NOATIME,		"noatime");
40085289Sdes#undef ADD_OPTION
40185289Sdes		/* a real Linux mtab will also show NFS options */
40285289Sdes		sbuf_printf(sb, " 0 0\n");
40385289Sdes	}
40485289Sdes	mtx_unlock(&mountlist_mtx);
40585289Sdes	if (flep != NULL)
40685289Sdes		free(flep, M_TEMP);
40785289Sdes	return (error);
40885289Sdes}
40985289Sdes
41085289Sdes/*
41178113Sdes * Filler function for proc/stat
41278113Sdes */
41378025Sdesstatic int
41478025Sdeslinprocfs_dostat(PFS_FILL_ARGS)
41565633Sdes{
41678025Sdes	sbuf_printf(sb,
41769799Sdes	    "cpu %ld %ld %ld %ld\n"
41869799Sdes	    "disk 0 0 0 0\n"
41969799Sdes	    "page %u %u\n"
42069799Sdes	    "swap %u %u\n"
42169799Sdes	    "intr %u\n"
42269799Sdes	    "ctxt %u\n"
42385657Sdillon	    "btime %lld\n",
42469799Sdes	    T2J(cp_time[CP_USER]),
42569799Sdes	    T2J(cp_time[CP_NICE]),
42669799Sdes	    T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/),
42769799Sdes	    T2J(cp_time[CP_IDLE]),
42869799Sdes	    cnt.v_vnodepgsin,
42969799Sdes	    cnt.v_vnodepgsout,
43069799Sdes	    cnt.v_swappgsin,
43169799Sdes	    cnt.v_swappgsout,
43269799Sdes	    cnt.v_intr,
43369799Sdes	    cnt.v_swtch,
434113574Sjhb	    (long long)boottime.tv_sec);
43578025Sdes	return (0);
43665633Sdes}
43765633Sdes
43878113Sdes/*
43978113Sdes * Filler function for proc/uptime
44078113Sdes */
44178025Sdesstatic int
44278025Sdeslinprocfs_douptime(PFS_FILL_ARGS)
44365633Sdes{
44465633Sdes	struct timeval tv;
44565633Sdes
44665633Sdes	getmicrouptime(&tv);
44785657Sdillon	sbuf_printf(sb, "%lld.%02ld %ld.%02ld\n",
448113574Sjhb	    (long long)tv.tv_sec, tv.tv_usec / 10000,
44969799Sdes	    T2S(cp_time[CP_IDLE]), T2J(cp_time[CP_IDLE]) % 100);
45078025Sdes	return (0);
45165633Sdes}
45265633Sdes
45378113Sdes/*
45478113Sdes * Filler function for proc/version
45578113Sdes */
45678025Sdesstatic int
45778025Sdeslinprocfs_doversion(PFS_FILL_ARGS)
45865633Sdes{
45987275Srwatson	char osname[LINUX_MAX_UTSNAME];
46087275Srwatson	char osrelease[LINUX_MAX_UTSNAME];
46187275Srwatson
462112206Sjhb	linux_get_osname(td, osname);
463112206Sjhb	linux_get_osrelease(td, osrelease);
46487275Srwatson
46578025Sdes	sbuf_printf(sb,
46669995Sdes	    "%s version %s (des@freebsd.org) (gcc version " __VERSION__ ")"
46787275Srwatson	    " #4 Sun Dec 18 04:30:00 CET 1977\n", osname, osrelease);
46878025Sdes	return (0);
46965633Sdes}
47065633Sdes
47178113Sdes/*
47278113Sdes * Filler function for proc/loadavg
47378113Sdes */
47478025Sdesstatic int
47578025Sdeslinprocfs_doloadavg(PFS_FILL_ARGS)
47676839Sjlemon{
47778025Sdes	sbuf_printf(sb,
47876839Sjlemon	    "%d.%02d %d.%02d %d.%02d %d/%d %d\n",
47976839Sjlemon	    (int)(averunnable.ldavg[0] / averunnable.fscale),
48076839Sjlemon	    (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100),
48176839Sjlemon	    (int)(averunnable.ldavg[1] / averunnable.fscale),
48276839Sjlemon	    (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100),
48376839Sjlemon	    (int)(averunnable.ldavg[2] / averunnable.fscale),
48476839Sjlemon	    (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100),
48576839Sjlemon	    1,				/* number of running tasks */
48676839Sjlemon	    nprocs,			/* number of tasks */
48778116Sdes	    lastpid			/* the last pid */
48876839Sjlemon	);
489119068Sdes
49078025Sdes	return (0);
49176839Sjlemon}
49276839Sjlemon
49378113Sdes/*
49478113Sdes * Filler function for proc/pid/stat
49578113Sdes */
49678025Sdesstatic int
49778025Sdeslinprocfs_doprocstat(PFS_FILL_ARGS)
49867588Sdes{
49969995Sdes	struct kinfo_proc kp;
50067588Sdes
50194307Sjhb	PROC_LOCK(p);
50269995Sdes	fill_kinfo_proc(p, &kp);
50378025Sdes	sbuf_printf(sb, "%d", p->p_pid);
50478025Sdes#define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg)
50567588Sdes	PS_ADD("comm",		"(%s)",	p->p_comm);
50667588Sdes	PS_ADD("statr",		"%c",	'0'); /* XXX */
50773923Sjhb	PS_ADD("ppid",		"%d",	p->p_pptr ? p->p_pptr->p_pid : 0);
50867588Sdes	PS_ADD("pgrp",		"%d",	p->p_pgid);
50967588Sdes	PS_ADD("session",	"%d",	p->p_session->s_sid);
51091140Stanimura	PROC_UNLOCK(p);
51167588Sdes	PS_ADD("tty",		"%d",	0); /* XXX */
51267588Sdes	PS_ADD("tpgid",		"%d",	0); /* XXX */
51367588Sdes	PS_ADD("flags",		"%u",	0); /* XXX */
51467588Sdes	PS_ADD("minflt",	"%u",	0); /* XXX */
51567588Sdes	PS_ADD("cminflt",	"%u",	0); /* XXX */
51667588Sdes	PS_ADD("majflt",	"%u",	0); /* XXX */
51767588Sdes	PS_ADD("cminflt",	"%u",	0); /* XXX */
51867588Sdes	PS_ADD("utime",		"%d",	0); /* XXX */
51967588Sdes	PS_ADD("stime",		"%d",	0); /* XXX */
52067588Sdes	PS_ADD("cutime",	"%d",	0); /* XXX */
52167588Sdes	PS_ADD("cstime",	"%d",	0); /* XXX */
52267588Sdes	PS_ADD("counter",	"%d",	0); /* XXX */
52367588Sdes	PS_ADD("priority",	"%d",	0); /* XXX */
52467588Sdes	PS_ADD("timeout",	"%u",	0); /* XXX */
52567588Sdes	PS_ADD("itrealvalue",	"%u",	0); /* XXX */
52667588Sdes	PS_ADD("starttime",	"%d",	0); /* XXX */
527113574Sjhb	PS_ADD("vsize",		"%ju",	(uintmax_t)kp.ki_size);
528113574Sjhb	PS_ADD("rss",		"%ju",	P2K((uintmax_t)kp.ki_rssize));
52967588Sdes	PS_ADD("rlim",		"%u",	0); /* XXX */
53069995Sdes	PS_ADD("startcode",	"%u",	(unsigned)0);
53167588Sdes	PS_ADD("endcode",	"%u",	0); /* XXX */
53267588Sdes	PS_ADD("startstack",	"%u",	0); /* XXX */
53369799Sdes	PS_ADD("esp",		"%u",	0); /* XXX */
53469799Sdes	PS_ADD("eip",		"%u",	0); /* XXX */
53567588Sdes	PS_ADD("signal",	"%d",	0); /* XXX */
53667588Sdes	PS_ADD("blocked",	"%d",	0); /* XXX */
53767588Sdes	PS_ADD("sigignore",	"%d",	0); /* XXX */
53867588Sdes	PS_ADD("sigcatch",	"%d",	0); /* XXX */
53967588Sdes	PS_ADD("wchan",		"%u",	0); /* XXX */
54069799Sdes	PS_ADD("nswap",		"%lu",	(long unsigned)0); /* XXX */
54169799Sdes	PS_ADD("cnswap",	"%lu",	(long unsigned)0); /* XXX */
54269799Sdes	PS_ADD("exitsignal",	"%d",	0); /* XXX */
54369799Sdes	PS_ADD("processor",	"%d",	0); /* XXX */
54467588Sdes#undef PS_ADD
54578025Sdes	sbuf_putc(sb, '\n');
546119068Sdes
54778025Sdes	return (0);
54867588Sdes}
54967588Sdes
55067588Sdes/*
551119911Sdes * Filler function for proc/pid/statm
552119911Sdes */
553119911Sdesstatic int
554119911Sdeslinprocfs_doprocstatm(PFS_FILL_ARGS)
555119911Sdes{
556119911Sdes	struct kinfo_proc kp;
557119911Sdes	segsz_t lsize;
558119911Sdes
559119911Sdes	PROC_LOCK(p);
560119911Sdes	fill_kinfo_proc(p, &kp);
561119911Sdes	PROC_UNLOCK(p);
562119911Sdes
563119911Sdes	/*
564119911Sdes	 * See comments in linprocfs_doprocstatus() regarding the
565119911Sdes	 * computation of lsize.
566119911Sdes	 */
567119911Sdes	/* size resident share trs drs lrs dt */
568119911Sdes	sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size));
569119911Sdes	sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize);
570119911Sdes	sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */
571119911Sdes	sbuf_printf(sb, "%ju ",	(uintmax_t)kp.ki_tsize);
572119911Sdes	sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize));
573119911Sdes	lsize = B2P(kp.ki_size) - kp.ki_dsize -
574119911Sdes	    kp.ki_ssize - kp.ki_tsize - 1;
575119911Sdes	sbuf_printf(sb, "%ju ", (uintmax_t)lsize);
576119911Sdes	sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */
577119911Sdes
578119911Sdes	return (0);
579119911Sdes}
580119911Sdes
581119911Sdes/*
58278113Sdes * Filler function for proc/pid/status
58378113Sdes */
58478025Sdesstatic int
58578025Sdeslinprocfs_doprocstatus(PFS_FILL_ARGS)
58667588Sdes{
58769995Sdes	struct kinfo_proc kp;
58867588Sdes	char *state;
58969799Sdes	segsz_t lsize;
59099072Sjulian	struct thread *td2;
591114983Sjhb	struct sigacts *ps;
59274135Sjlemon	int i;
59367588Sdes
594113611Sjhb	PROC_LOCK(p);
59599072Sjulian	td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */
59699072Sjulian
59799072Sjulian	if (P_SHOULDSTOP(p)) {
59899072Sjulian		state = "T (stopped)";
59999072Sjulian	} else {
600113611Sjhb		mtx_lock_spin(&sched_lock);
60199072Sjulian		switch(p->p_state) {
60299072Sjulian		case PRS_NEW:
60399072Sjulian			state = "I (idle)";
60499072Sjulian			break;
60599072Sjulian		case PRS_NORMAL:
60699072Sjulian			if (p->p_flag & P_WEXIT) {
60799072Sjulian				state = "X (exiting)";
60899072Sjulian				break;
60999072Sjulian			}
61099072Sjulian			switch(td2->td_state) {
611103216Sjulian			case TDS_INHIBITED:
61299072Sjulian				state = "S (sleeping)";
61399072Sjulian				break;
61499072Sjulian			case TDS_RUNQ:
61599072Sjulian			case TDS_RUNNING:
61699072Sjulian				state = "R (running)";
61799072Sjulian				break;
61899072Sjulian			default:
61999072Sjulian				state = "? (unknown)";
62099072Sjulian				break;
62199072Sjulian			}
62299072Sjulian			break;
62399072Sjulian		case PRS_ZOMBIE:
62499072Sjulian			state = "Z (zombie)";
62599072Sjulian			break;
62699072Sjulian		default:
62799072Sjulian			state = "? (unknown)";
62899072Sjulian			break;
62999072Sjulian		}
630113611Sjhb		mtx_unlock_spin(&sched_lock);
63199072Sjulian	}
63267588Sdes
63369995Sdes	fill_kinfo_proc(p, &kp);
63478025Sdes	sbuf_printf(sb, "Name:\t%s\n",		p->p_comm); /* XXX escape */
63578031Sdes	sbuf_printf(sb, "State:\t%s\n",		state);
63667588Sdes
63767588Sdes	/*
63867588Sdes	 * Credentials
63967588Sdes	 */
64078025Sdes	sbuf_printf(sb, "Pid:\t%d\n",		p->p_pid);
64178025Sdes	sbuf_printf(sb, "PPid:\t%d\n",		p->p_pptr ?
64273923Sjhb						p->p_pptr->p_pid : 0);
64378031Sdes	sbuf_printf(sb, "Uid:\t%d %d %d %d\n",	p->p_ucred->cr_ruid,
64478031Sdes						p->p_ucred->cr_uid,
64578031Sdes						p->p_ucred->cr_svuid,
64678031Sdes						/* FreeBSD doesn't have fsuid */
64778031Sdes						p->p_ucred->cr_uid);
64878031Sdes	sbuf_printf(sb, "Gid:\t%d %d %d %d\n",	p->p_ucred->cr_rgid,
64978031Sdes						p->p_ucred->cr_gid,
65078031Sdes						p->p_ucred->cr_svgid,
65178031Sdes						/* FreeBSD doesn't have fsgid */
65278031Sdes						p->p_ucred->cr_gid);
65378025Sdes	sbuf_cat(sb, "Groups:\t");
65467588Sdes	for (i = 0; i < p->p_ucred->cr_ngroups; i++)
65578031Sdes		sbuf_printf(sb, "%d ",		p->p_ucred->cr_groups[i]);
65671471Sjhb	PROC_UNLOCK(p);
65778025Sdes	sbuf_putc(sb, '\n');
658119068Sdes
65967588Sdes	/*
66067588Sdes	 * Memory
66169799Sdes	 *
66269799Sdes	 * While our approximation of VmLib may not be accurate (I
66369799Sdes	 * don't know of a simple way to verify it, and I'm not sure
66469799Sdes	 * it has much meaning anyway), I believe it's good enough.
66569799Sdes	 *
66669799Sdes	 * The same code that could (I think) accurately compute VmLib
66769799Sdes	 * could also compute VmLck, but I don't really care enough to
66869799Sdes	 * implement it. Submissions are welcome.
66967588Sdes	 */
670113574Sjhb	sbuf_printf(sb, "VmSize:\t%8ju kB\n",	B2K((uintmax_t)kp.ki_size));
67178025Sdes	sbuf_printf(sb, "VmLck:\t%8u kB\n",	P2K(0)); /* XXX */
672113574Sjhb	sbuf_printf(sb, "VmRss:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_rssize));
673113574Sjhb	sbuf_printf(sb, "VmData:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_dsize));
674113574Sjhb	sbuf_printf(sb, "VmStk:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_ssize));
675113574Sjhb	sbuf_printf(sb, "VmExe:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_tsize));
67669995Sdes	lsize = B2P(kp.ki_size) - kp.ki_dsize -
67769995Sdes	    kp.ki_ssize - kp.ki_tsize - 1;
678113574Sjhb	sbuf_printf(sb, "VmLib:\t%8ju kB\n",	P2K((uintmax_t)lsize));
67967588Sdes
68067588Sdes	/*
68167588Sdes	 * Signal masks
68267588Sdes	 *
68367588Sdes	 * We support up to 128 signals, while Linux supports 32,
68467588Sdes	 * but we only define 32 (the same 32 as Linux, to boot), so
68567588Sdes	 * just show the lower 32 bits of each mask. XXX hack.
68667588Sdes	 *
68767588Sdes	 * NB: on certain platforms (Sparc at least) Linux actually
68867588Sdes	 * supports 64 signals, but this code is a long way from
68967588Sdes	 * running on anything but i386, so ignore that for now.
69067588Sdes	 */
69171471Sjhb	PROC_LOCK(p);
692104306Sjmallett	sbuf_printf(sb, "SigPnd:\t%08x\n",	p->p_siglist.__bits[0]);
69369799Sdes	/*
69469799Sdes	 * I can't seem to find out where the signal mask is in
69569799Sdes	 * relation to struct proc, so SigBlk is left unimplemented.
69669799Sdes	 */
69778025Sdes	sbuf_printf(sb, "SigBlk:\t%08x\n",	0); /* XXX */
698114983Sjhb	ps = p->p_sigacts;
699114983Sjhb	mtx_lock(&ps->ps_mtx);
700114983Sjhb	sbuf_printf(sb, "SigIgn:\t%08x\n",	ps->ps_sigignore.__bits[0]);
701114983Sjhb	sbuf_printf(sb, "SigCgt:\t%08x\n",	ps->ps_sigcatch.__bits[0]);
702114983Sjhb	mtx_unlock(&ps->ps_mtx);
70371471Sjhb	PROC_UNLOCK(p);
704119068Sdes
70567588Sdes	/*
70667588Sdes	 * Linux also prints the capability masks, but we don't have
70767588Sdes	 * capabilities yet, and when we do get them they're likely to
70867588Sdes	 * be meaningless to Linux programs, so we lie. XXX
70967588Sdes	 */
71078025Sdes	sbuf_printf(sb, "CapInh:\t%016x\n",	0);
71178025Sdes	sbuf_printf(sb, "CapPrm:\t%016x\n",	0);
71278025Sdes	sbuf_printf(sb, "CapEff:\t%016x\n",	0);
713119068Sdes
71478025Sdes	return (0);
71567588Sdes}
71674135Sjlemon
717119911Sdes
71878113Sdes/*
719119911Sdes * Filler function for proc/pid/cwd
720119911Sdes */
721119911Sdesstatic int
722119911Sdeslinprocfs_doproccwd(PFS_FILL_ARGS)
723119911Sdes{
724119911Sdes	char *fullpath = "unknown";
725119911Sdes	char *freepath = NULL;
726119911Sdes
727119911Sdes	vn_fullpath(td, p->p_fd->fd_cdir, &fullpath, &freepath);
728119911Sdes	sbuf_printf(sb, "%s", fullpath);
729119911Sdes	if (freepath)
730119911Sdes		free(freepath, M_TEMP);
731119911Sdes	return (0);
732119911Sdes}
733119911Sdes
734119911Sdes/*
735119911Sdes * Filler function for proc/pid/root
736119911Sdes */
737119911Sdesstatic int
738119911Sdeslinprocfs_doprocroot(PFS_FILL_ARGS)
739119911Sdes{
740119911Sdes	struct vnode *rvp;
741119911Sdes	char *fullpath = "unknown";
742119911Sdes	char *freepath = NULL;
743119911Sdes
744119911Sdes	rvp = jailed(p->p_ucred) ? p->p_fd->fd_jdir : p->p_fd->fd_rdir;
745119911Sdes	vn_fullpath(td, rvp, &fullpath, &freepath);
746119911Sdes	sbuf_printf(sb, "%s", fullpath);
747119911Sdes	if (freepath)
748119911Sdes		free(freepath, M_TEMP);
749119911Sdes	return (0);
750119911Sdes}
751119911Sdes
752119911Sdes/*
75378113Sdes * Filler function for proc/pid/cmdline
75478113Sdes */
75578025Sdesstatic int
75678113Sdeslinprocfs_doproccmdline(PFS_FILL_ARGS)
75778113Sdes{
75878113Sdes	struct ps_strings pstr;
75978113Sdes	int error, i;
76078113Sdes
76178113Sdes	/*
76278113Sdes	 * If we are using the ps/cmdline caching, use that.  Otherwise
76378113Sdes	 * revert back to the old way which only implements full cmdline
76478113Sdes	 * for the currept process and just p->p_comm for all other
76578113Sdes	 * processes.
76678113Sdes	 * Note that if the argv is no longer available, we deliberately
76778113Sdes	 * don't fall back on p->p_comm or return an error: the authentic
76878113Sdes	 * Linux behaviour is to return zero-length in this case.
76978113Sdes	 */
77078113Sdes
77194620Sjhb	PROC_LOCK(p);
77296886Sjhb	if (p->p_args && (ps_argsopen || !p_cansee(td, p))) {
77394620Sjhb		sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length);
77494620Sjhb		PROC_UNLOCK(p);
77594620Sjhb	} else if (p != td->td_proc) {
77694620Sjhb		PROC_UNLOCK(p);
77794620Sjhb		sbuf_printf(sb, "%.*s", MAXCOMLEN, p->p_comm);
77894620Sjhb	} else {
77994620Sjhb		PROC_UNLOCK(p);
780103767Sjake		error = copyin((void *)p->p_sysent->sv_psstrings, &pstr,
781103767Sjake		    sizeof(pstr));
78294620Sjhb		if (error)
78394620Sjhb			return (error);
78494620Sjhb		for (i = 0; i < pstr.ps_nargvstr; i++) {
78594620Sjhb			sbuf_copyin(sb, pstr.ps_argvstr[i], 0);
78694620Sjhb			sbuf_printf(sb, "%c", '\0');
78778113Sdes		}
78878113Sdes	}
78978113Sdes
79078113Sdes	return (0);
79178113Sdes}
79278113Sdes
79378113Sdes/*
794116173Sobrien * Filler function for proc/pid/environ
795116173Sobrien */
796116173Sobrienstatic int
797116173Sobrienlinprocfs_doprocenviron(PFS_FILL_ARGS)
798116173Sobrien{
799116173Sobrien	sbuf_printf(sb, "doprocenviron\n%c", '\0');
800116173Sobrien
801116173Sobrien	return (0);
802116173Sobrien}
803116173Sobrien
804116173Sobrien/*
805116173Sobrien * Filler function for proc/pid/maps
806116173Sobrien */
807116173Sobrienstatic int
808116173Sobrienlinprocfs_doprocmaps(PFS_FILL_ARGS)
809116173Sobrien{
810116173Sobrien	sbuf_printf(sb, "doprocmaps\n%c", '\0');
811116173Sobrien
812116173Sobrien	return (0);
813116173Sobrien}
814116173Sobrien
815116173Sobrien/*
81678113Sdes * Filler function for proc/net/dev
81778113Sdes */
81878025Sdesstatic int
81978025Sdeslinprocfs_donetdev(PFS_FILL_ARGS)
82074135Sjlemon{
82185129Sdes	char ifname[16]; /* XXX LINUX_IFNAMSIZ */
82274135Sjlemon	struct ifnet *ifp;
82374135Sjlemon
82485129Sdes	sbuf_printf(sb, "%6s|%58s|%s\n%6s|%58s|%58s\n",
82583926Sdes	    "Inter-", "   Receive", "  Transmit", " face",
82685129Sdes	    "bytes    packets errs drop fifo frame compressed",
82783926Sdes	    "bytes    packets errs drop fifo frame compressed");
82874135Sjlemon
829108172Shsu	IFNET_RLOCK();
83074135Sjlemon	TAILQ_FOREACH(ifp, &ifnet, if_link) {
83185129Sdes		linux_ifname(ifp, ifname, sizeof ifname);
83285129Sdes			sbuf_printf(sb, "%6.6s:", ifname);
83383926Sdes		sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ",
83483926Sdes		    0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
83583926Sdes		sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
83683926Sdes		    0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
83774135Sjlemon	}
838108172Shsu	IFNET_RUNLOCK();
839119068Sdes
84078025Sdes	return (0);
84174135Sjlemon}
84274135Sjlemon
84385538Sphk#if 0
84485538Sphkextern struct cdevsw *cdevsw[];
84585538Sphk
84678113Sdes/*
84778113Sdes * Filler function for proc/devices
84878113Sdes */
84978025Sdesstatic int
85078025Sdeslinprocfs_dodevices(PFS_FILL_ARGS)
85174135Sjlemon{
85274135Sjlemon	int i;
85374135Sjlemon
85478025Sdes	sbuf_printf(sb, "Character devices:\n");
85574135Sjlemon
85678025Sdes	for (i = 0; i < NUMCDEVSW; i++)
85774135Sjlemon		if (cdevsw[i] != NULL)
85878025Sdes			sbuf_printf(sb, "%3d %s\n", i, cdevsw[i]->d_name);
85974135Sjlemon
86078025Sdes	sbuf_printf(sb, "\nBlock devices:\n");
861119068Sdes
86278025Sdes	return (0);
86374135Sjlemon}
86485538Sphk#endif
86574135Sjlemon
86678113Sdes/*
86778113Sdes * Filler function for proc/cmdline
86878113Sdes */
86978025Sdesstatic int
87078025Sdeslinprocfs_docmdline(PFS_FILL_ARGS)
87174135Sjlemon{
87278025Sdes	sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname);
87378025Sdes	sbuf_printf(sb, " ro root=302\n");
87478025Sdes	return (0);
87578025Sdes}
87674135Sjlemon
87783926Sdes#if 0
87878025Sdes/*
87983926Sdes * Filler function for proc/modules
88083926Sdes */
88183926Sdesstatic int
88283926Sdeslinprocfs_domodules(PFS_FILL_ARGS)
88383926Sdes{
88483926Sdes	struct linker_file *lf;
885119068Sdes
88683926Sdes	TAILQ_FOREACH(lf, &linker_files, link) {
88783926Sdes		sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename,
88883926Sdes		    (unsigned long)lf->size, lf->refs);
88983926Sdes	}
89083926Sdes	return (0);
89183926Sdes}
89283926Sdes#endif
89383926Sdes
89483926Sdes/*
89585129Sdes * Constructor
89678025Sdes */
89785129Sdesstatic int
89885129Sdeslinprocfs_init(PFS_INIT_ARGS)
89985129Sdes{
90085129Sdes	struct pfs_node *root;
90185129Sdes	struct pfs_node *dir;
90274135Sjlemon
90385129Sdes	root = pi->pi_root;
90478025Sdes
905119923Sdes	/* /proc/... */
906119911Sdes	pfs_create_file(root, "cmdline", &linprocfs_docmdline,
907119911Sdes	    NULL, NULL, PFS_RD);
908119911Sdes	pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo,
909119911Sdes	    NULL, NULL, PFS_RD);
91085538Sphk#if 0
911119911Sdes	pfs_create_file(root, "devices", &linprocfs_dodevices,
912119911Sdes	    NULL, NULL, PFS_RD);
91385538Sphk#endif
914119911Sdes	pfs_create_file(root, "loadavg", &linprocfs_doloadavg,
915119911Sdes	    NULL, NULL, PFS_RD);
916119911Sdes	pfs_create_file(root, "meminfo", &linprocfs_domeminfo,
917119911Sdes	    NULL, NULL, PFS_RD);
91883926Sdes#if 0
919119911Sdes	pfs_create_file(root, "modules", &linprocfs_domodules,
920119911Sdes	    NULL, NULL, PFS_RD);
92183926Sdes#endif
922119911Sdes	pfs_create_file(root, "mtab", &linprocfs_domtab,
923119911Sdes	    NULL, NULL, PFS_RD);
92487543Sdes	pfs_create_link(root, "self", &procfs_docurproc,
92585129Sdes	    NULL, NULL, 0);
926119911Sdes	pfs_create_file(root, "stat", &linprocfs_dostat,
927119911Sdes	    NULL, NULL, PFS_RD);
928119911Sdes	pfs_create_file(root, "uptime", &linprocfs_douptime,
929119911Sdes	    NULL, NULL, PFS_RD);
930119911Sdes	pfs_create_file(root, "version", &linprocfs_doversion,
931119911Sdes	    NULL, NULL, PFS_RD);
93278025Sdes
933119923Sdes	/* /proc/net/... */
93485129Sdes	dir = pfs_create_dir(root, "net", NULL, NULL, 0);
93585129Sdes	pfs_create_file(dir, "dev", &linprocfs_donetdev,
93685129Sdes	    NULL, NULL, PFS_RD);
93778025Sdes
938119923Sdes	/* /proc/<pid>/... */
93985129Sdes	dir = pfs_create_dir(root, "pid", NULL, NULL, PFS_PROCDEP);
94085129Sdes	pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline,
94185129Sdes	    NULL, NULL, PFS_RD);
942119911Sdes	pfs_create_link(dir, "cwd", &linprocfs_doproccwd,
943119911Sdes	    NULL, NULL, 0);
944116173Sobrien	pfs_create_file(dir, "environ", &linprocfs_doprocenviron,
945116173Sobrien	    NULL, NULL, PFS_RD);
94687543Sdes	pfs_create_link(dir, "exe", &procfs_doprocfile,
94787543Sdes	    NULL, &procfs_notsystem, 0);
948116173Sobrien	pfs_create_file(dir, "maps", &linprocfs_doprocmaps,
949116173Sobrien	    NULL, NULL, PFS_RD);
95085129Sdes	pfs_create_file(dir, "mem", &procfs_doprocmem,
95185129Sdes	    &procfs_attr, &procfs_candebug, PFS_RDWR|PFS_RAW);
952119911Sdes	pfs_create_link(dir, "root", &linprocfs_doprocroot,
953119911Sdes	    NULL, NULL, 0);
95485129Sdes	pfs_create_file(dir, "stat", &linprocfs_doprocstat,
95585129Sdes	    NULL, NULL, PFS_RD);
956119911Sdes	pfs_create_file(dir, "statm", &linprocfs_doprocstatm,
957119911Sdes	    NULL, NULL, PFS_RD);
95885129Sdes	pfs_create_file(dir, "status", &linprocfs_doprocstatus,
95985129Sdes	    NULL, NULL, PFS_RD);
96085129Sdes
96185129Sdes	return (0);
96285129Sdes}
96385129Sdes
96485129Sdes/*
96585129Sdes * Destructor
96685129Sdes */
96785129Sdesstatic int
96885129Sdeslinprocfs_uninit(PFS_INIT_ARGS)
96985129Sdes{
97085129Sdes
97185129Sdes	/* nothing to do, pseudofs will GC */
97285129Sdes	return (0);
97385129Sdes}
97485129Sdes
97585129SdesPSEUDOFS(linprocfs, 1);
97678025SdesMODULE_DEPEND(linprocfs, linux, 1, 1, 1);
97778025SdesMODULE_DEPEND(linprocfs, procfs, 1, 1, 1);
978