xref: /freebsd/sys/compat/linprocfs/linprocfs.c (revision 02f481a30b8269c7cad24ec2920ca09751708a1e)
1 /*-
2  * SPDX-License-Identifier: BSD-4-Clause
3  *
4  * Copyright (c) 2000 Dag-Erling Smørgrav
5  * Copyright (c) 1999 Pierre Beyssac
6  * Copyright (c) 1993 Jan-Simon Pendry
7  * Copyright (c) 1993
8  *	The Regents of the University of California.  All rights reserved.
9  *
10  * This code is derived from software contributed to Berkeley by
11  * Jan-Simon Pendry.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. All advertising materials mentioning features or use of this software
22  *    must display the following acknowledgement:
23  *	This product includes software developed by the University of
24  *	California, Berkeley and its contributors.
25  * 4. Neither the name of the University nor the names of its contributors
26  *    may be used to endorse or promote products derived from this software
27  *    without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39  * SUCH DAMAGE.
40  */
41 
42 #include "opt_inet.h"
43 
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/blist.h>
47 #include <sys/conf.h>
48 #include <sys/exec.h>
49 #include <sys/fcntl.h>
50 #include <sys/filedesc.h>
51 #include <sys/jail.h>
52 #include <sys/kernel.h>
53 #include <sys/limits.h>
54 #include <sys/linker.h>
55 #include <sys/lock.h>
56 #include <sys/malloc.h>
57 #include <sys/msg.h>
58 #include <sys/mutex.h>
59 #include <sys/namei.h>
60 #include <sys/proc.h>
61 #include <sys/ptrace.h>
62 #include <sys/queue.h>
63 #include <sys/resourcevar.h>
64 #include <sys/resource.h>
65 #include <sys/sbuf.h>
66 #include <sys/sem.h>
67 #include <sys/shm.h>
68 #include <sys/smp.h>
69 #include <sys/socket.h>
70 #include <sys/syscallsubr.h>
71 #include <sys/sysctl.h>
72 #include <sys/sysent.h>
73 #include <sys/time.h>
74 #include <sys/tty.h>
75 #include <sys/user.h>
76 #include <sys/uuid.h>
77 #include <sys/vmmeter.h>
78 #include <sys/vnode.h>
79 #include <sys/bus.h>
80 #include <sys/uio.h>
81 
82 #include <net/if.h>
83 #include <net/if_var.h>
84 #include <net/if_types.h>
85 
86 #include <net/route.h>
87 #include <net/route/nhop.h>
88 #include <net/route/route_ctl.h>
89 
90 #include <vm/vm.h>
91 #include <vm/vm_extern.h>
92 #include <vm/pmap.h>
93 #include <vm/vm_map.h>
94 #include <vm/vm_param.h>
95 #include <vm/vm_object.h>
96 #include <vm/swap_pager.h>
97 
98 #include <machine/clock.h>
99 
100 #include <geom/geom.h>
101 #include <geom/geom_int.h>
102 
103 #if defined(__i386__) || defined(__amd64__)
104 #include <machine/cputypes.h>
105 #include <machine/md_var.h>
106 #endif /* __i386__ || __amd64__ */
107 
108 #include <compat/linux/linux.h>
109 #include <compat/linux/linux_common.h>
110 #include <compat/linux/linux_emul.h>
111 #include <compat/linux/linux_mib.h>
112 #include <compat/linux/linux_misc.h>
113 #include <compat/linux/linux_util.h>
114 #include <fs/pseudofs/pseudofs.h>
115 #include <fs/procfs/procfs.h>
116 
117 /*
118  * Various conversion macros
119  */
120 #define T2J(x) ((long)(((x) * 100ULL) / (stathz ? stathz : hz)))	/* ticks to jiffies */
121 #define T2CS(x) ((unsigned long)(((x) * 100ULL) / (stathz ? stathz : hz)))	/* ticks to centiseconds */
122 #define T2S(x) ((x) / (stathz ? stathz : hz))		/* ticks to seconds */
123 #define B2K(x) ((x) >> 10)				/* bytes to kbytes */
124 #define B2P(x) ((x) >> PAGE_SHIFT)			/* bytes to pages */
125 #define P2B(x) ((x) << PAGE_SHIFT)			/* pages to bytes */
126 #define P2K(x) ((x) << (PAGE_SHIFT - 10))		/* pages to kbytes */
127 #define TV2J(x)	((x)->tv_sec * 100UL + (x)->tv_usec / 10000)
128 
129 /* Value defined in sys/kern/sysv_shm.c */
130 #define SHMSEG_ALLOCATED	0x0800
131 
132 /**
133  * @brief Mapping of ki_stat in struct kinfo_proc to the linux state
134  *
135  * The linux procfs state field displays one of the characters RSDZTW to
136  * denote running, sleeping in an interruptible wait, waiting in an
137  * uninterruptible disk sleep, a zombie process, process is being traced
138  * or stopped, or process is paging respectively.
139  *
140  * Our struct kinfo_proc contains the variable ki_stat which contains a
141  * value out of SIDL, SRUN, SSLEEP, SSTOP, SZOMB, SWAIT and SLOCK.
142  *
143  * This character array is used with ki_stati-1 as an index and tries to
144  * map our states to suitable linux states.
145  */
146 static char linux_state[] = "RRSTZDD";
147 
148 /*
149  * Filler function for proc/meminfo
150  */
151 static int
152 linprocfs_domeminfo(PFS_FILL_ARGS)
153 {
154 	unsigned long memtotal;		/* total memory in bytes */
155 	unsigned long memfree;		/* free memory in bytes */
156 	unsigned long cached;		/* page cache */
157 	unsigned long buffers;		/* buffer cache */
158 	unsigned long long swaptotal;	/* total swap space in bytes */
159 	unsigned long long swapused;	/* used swap space in bytes */
160 	unsigned long long swapfree;	/* free swap space in bytes */
161 	size_t sz;
162 	int error, i, j;
163 
164 	memtotal = physmem * PAGE_SIZE;
165 	memfree = (unsigned long)vm_free_count() * PAGE_SIZE;
166 	swap_pager_status(&i, &j);
167 	swaptotal = (unsigned long long)i * PAGE_SIZE;
168 	swapused = (unsigned long long)j * PAGE_SIZE;
169 	swapfree = swaptotal - swapused;
170 
171 	/*
172 	 * This value may exclude wired pages, but we have no good way of
173 	 * accounting for that.
174 	 */
175 	cached =
176 	    (vm_active_count() + vm_inactive_count() + vm_laundry_count()) *
177 	    PAGE_SIZE;
178 
179 	sz = sizeof(buffers);
180 	error = kernel_sysctlbyname(curthread, "vfs.bufspace", &buffers, &sz,
181 	    NULL, 0, 0, 0);
182 	if (error != 0)
183 		buffers = 0;
184 
185 	sbuf_printf(sb,
186 	    "MemTotal: %9lu kB\n"
187 	    "MemFree:  %9lu kB\n"
188 	    "Buffers:  %9lu kB\n"
189 	    "Cached:   %9lu kB\n"
190 	    "SwapTotal:%9llu kB\n"
191 	    "SwapFree: %9llu kB\n",
192 	    B2K(memtotal), B2K(memfree), B2K(buffers),
193 	    B2K(cached), B2K(swaptotal), B2K(swapfree));
194 
195 	return (0);
196 }
197 
198 #if defined(__i386__) || defined(__amd64__)
199 /*
200  * Filler function for proc/cpuinfo (i386 & amd64 version)
201  */
202 static int
203 linprocfs_docpuinfo(PFS_FILL_ARGS)
204 {
205 	uint64_t freq;
206 	u_int cache_size[4];
207 	u_int regs[4] = { 0 };
208 	int fqmhz, fqkhz;
209 	int i, j;
210 
211 	/*
212 	 * We default the flags to include all non-conflicting flags,
213 	 * and the Intel versions of conflicting flags.
214 	 */
215 	static char *cpu_feature_names[] = {
216 		/*  0 */ "fpu", "vme", "de", "pse",
217 		/*  4 */ "tsc", "msr", "pae", "mce",
218 		/*  8 */ "cx8", "apic", "", "sep",
219 		/* 12 */ "mtrr", "pge", "mca", "cmov",
220 		/* 16 */ "pat", "pse36", "pn", "clflush",
221 		/* 20 */ "", "dts", "acpi", "mmx",
222 		/* 24 */ "fxsr", "sse", "sse2", "ss",
223 		/* 28 */ "ht", "tm", "ia64", "pbe"
224 	};
225 
226 	static char *amd_feature_names[] = {
227 		/*  0 */ "", "", "", "",
228 		/*  4 */ "", "", "", "",
229 		/*  8 */ "", "", "", "syscall",
230 		/* 12 */ "", "", "", "",
231 		/* 16 */ "", "", "", "mp",
232 		/* 20 */ "nx", "", "mmxext", "",
233 		/* 24 */ "", "fxsr_opt", "pdpe1gb", "rdtscp",
234 		/* 28 */ "", "lm", "3dnowext", "3dnow"
235 	};
236 
237 	static char *cpu_feature2_names[] = {
238 		/*  0 */ "pni", "pclmulqdq", "dtes64", "monitor",
239 		/*  4 */ "ds_cpl", "vmx", "smx", "est",
240 		/*  8 */ "tm2", "ssse3", "cid", "sdbg",
241 		/* 12 */ "fma", "cx16", "xtpr", "pdcm",
242 		/* 16 */ "", "pcid", "dca", "sse4_1",
243 		/* 20 */ "sse4_2", "x2apic", "movbe", "popcnt",
244 		/* 24 */ "tsc_deadline_timer", "aes", "xsave", "",
245 		/* 28 */ "avx", "f16c", "rdrand", "hypervisor"
246 	};
247 
248 	static char *amd_feature2_names[] = {
249 		/*  0 */ "lahf_lm", "cmp_legacy", "svm", "extapic",
250 		/*  4 */ "cr8_legacy", "abm", "sse4a", "misalignsse",
251 		/*  8 */ "3dnowprefetch", "osvw", "ibs", "xop",
252 		/* 12 */ "skinit", "wdt", "", "lwp",
253 		/* 16 */ "fma4", "tce", "", "nodeid_msr",
254 		/* 20 */ "", "tbm", "topoext", "perfctr_core",
255 		/* 24 */ "perfctr_nb", "", "bpext", "ptsc",
256 		/* 28 */ "perfctr_llc", "mwaitx", "", ""
257 	};
258 
259 	static char *cpu_stdext_feature_names[] = {
260 		/*  0 */ "fsgsbase", "tsc_adjust", "sgx", "bmi1",
261 		/*  4 */ "hle", "avx2", "", "smep",
262 		/*  8 */ "bmi2", "erms", "invpcid", "rtm",
263 		/* 12 */ "cqm", "", "mpx", "rdt_a",
264 		/* 16 */ "avx512f", "avx512dq", "rdseed", "adx",
265 		/* 20 */ "smap", "avx512ifma", "", "clflushopt",
266 		/* 24 */ "clwb", "intel_pt", "avx512pf", "avx512er",
267 		/* 28 */ "avx512cd", "sha_ni", "avx512bw", "avx512vl"
268 	};
269 
270 	static char *cpu_stdext_feature2_names[] = {
271 		/*  0 */ "prefetchwt1", "avx512vbmi", "umip", "pku",
272 		/*  4 */ "ospke", "waitpkg", "avx512_vbmi2", "",
273 		/*  8 */ "gfni", "vaes", "vpclmulqdq", "avx512_vnni",
274 		/* 12 */ "avx512_bitalg", "", "avx512_vpopcntdq", "",
275 		/* 16 */ "", "", "", "",
276 		/* 20 */ "", "", "rdpid", "",
277 		/* 24 */ "", "cldemote", "", "movdiri",
278 		/* 28 */ "movdir64b", "enqcmd", "sgx_lc", ""
279 	};
280 
281 	static char *cpu_stdext_feature3_names[] = {
282 		/*  0 */ "", "", "avx512_4vnniw", "avx512_4fmaps",
283 		/*  4 */ "fsrm", "", "", "",
284 		/*  8 */ "avx512_vp2intersect", "", "md_clear", "",
285 		/* 12 */ "", "", "", "",
286 		/* 16 */ "", "", "pconfig", "",
287 		/* 20 */ "", "", "", "",
288 		/* 24 */ "", "", "ibrs", "stibp",
289 		/* 28 */ "flush_l1d", "arch_capabilities", "core_capabilities", "ssbd"
290 	};
291 
292 	static char *cpu_stdext_feature_l1_names[] = {
293 		/*  0 */ "xsaveopt", "xsavec", "xgetbv1", "xsaves",
294 		/*  4 */ "xfd"
295 	};
296 
297 	static char *power_flags[] = {
298 		"ts",           "fid",          "vid",
299 		"ttp",          "tm",           "stc",
300 		"100mhzsteps",  "hwpstate",     "",
301 		"cpb",          "eff_freq_ro",  "proc_feedback",
302 		"acc_power",
303 	};
304 
305 #ifdef __i386__
306 	switch (cpu_vendor_id) {
307 	case CPU_VENDOR_AMD:
308 		if (cpu_class < CPUCLASS_686)
309 			cpu_feature_names[16] = "fcmov";
310 		break;
311 	case CPU_VENDOR_CYRIX:
312 		cpu_feature_names[24] = "cxmmx";
313 		break;
314 	}
315 #endif
316 	if (cpu_exthigh >= 0x80000006)
317 		do_cpuid(0x80000006, cache_size);
318 	else
319 		memset(cache_size, 0, sizeof(cache_size));
320 	for (i = 0; i < mp_ncpus; ++i) {
321 		fqmhz = 0;
322 		fqkhz = 0;
323 		freq = atomic_load_acq_64(&tsc_freq);
324 		if (freq != 0) {
325 			fqmhz = (freq + 4999) / 1000000;
326 			fqkhz = ((freq + 4999) / 10000) % 100;
327 		}
328 		sbuf_printf(sb,
329 		    "processor\t: %d\n"
330 		    "vendor_id\t: %.20s\n"
331 		    "cpu family\t: %u\n"
332 		    "model\t\t: %u\n"
333 		    "model name\t: %s\n"
334 		    "stepping\t: %u\n"
335 		    "cpu MHz\t\t: %d.%02d\n"
336 		    "cache size\t: %d KB\n"
337 		    "physical id\t: %d\n"
338 		    "siblings\t: %d\n"
339 		    "core id\t\t: %d\n"
340 		    "cpu cores\t: %d\n"
341 		    "apicid\t\t: %d\n"
342 		    "initial apicid\t: %d\n"
343 		    "fpu\t\t: %s\n"
344 		    "fpu_exception\t: %s\n"
345 		    "cpuid level\t: %d\n"
346 		    "wp\t\t: %s\n",
347 		    i, cpu_vendor, CPUID_TO_FAMILY(cpu_id),
348 		    CPUID_TO_MODEL(cpu_id), cpu_model, cpu_id & CPUID_STEPPING,
349 		    fqmhz, fqkhz,
350 		    (cache_size[2] >> 16), 0, mp_ncpus, i, mp_ncpus,
351 		    i, i, /*cpu_id & CPUID_LOCAL_APIC_ID ??*/
352 		    (cpu_feature & CPUID_FPU) ? "yes" : "no", "yes",
353 		    CPUID_TO_FAMILY(cpu_id), "yes");
354 		sbuf_cat(sb, "flags\t\t:");
355 		for (j = 0; j < nitems(cpu_feature_names); j++)
356 			if (cpu_feature & (1 << j) &&
357 			    cpu_feature_names[j][0] != '\0')
358 				sbuf_printf(sb, " %s", cpu_feature_names[j]);
359 		for (j = 0; j < nitems(amd_feature_names); j++)
360 			if (amd_feature & (1 << j) &&
361 			    amd_feature_names[j][0] != '\0')
362 				sbuf_printf(sb, " %s", amd_feature_names[j]);
363 		for (j = 0; j < nitems(cpu_feature2_names); j++)
364 			if (cpu_feature2 & (1 << j) &&
365 			    cpu_feature2_names[j][0] != '\0')
366 				sbuf_printf(sb, " %s", cpu_feature2_names[j]);
367 		for (j = 0; j < nitems(amd_feature2_names); j++)
368 			if (amd_feature2 & (1 << j) &&
369 			    amd_feature2_names[j][0] != '\0')
370 				sbuf_printf(sb, " %s", amd_feature2_names[j]);
371 		for (j = 0; j < nitems(cpu_stdext_feature_names); j++)
372 			if (cpu_stdext_feature & (1 << j) &&
373 			    cpu_stdext_feature_names[j][0] != '\0')
374 				sbuf_printf(sb, " %s",
375 				    cpu_stdext_feature_names[j]);
376 		if (tsc_is_invariant)
377 			sbuf_cat(sb, " constant_tsc");
378 		for (j = 0; j < nitems(cpu_stdext_feature2_names); j++)
379 			if (cpu_stdext_feature2 & (1 << j) &&
380 			    cpu_stdext_feature2_names[j][0] != '\0')
381 				sbuf_printf(sb, " %s",
382 				    cpu_stdext_feature2_names[j]);
383 		for (j = 0; j < nitems(cpu_stdext_feature3_names); j++)
384 			if (cpu_stdext_feature3 & (1 << j) &&
385 			    cpu_stdext_feature3_names[j][0] != '\0')
386 				sbuf_printf(sb, " %s",
387 				    cpu_stdext_feature3_names[j]);
388 		if ((cpu_feature2 & CPUID2_XSAVE) != 0) {
389 			cpuid_count(0xd, 0x1, regs);
390 			for (j = 0; j < nitems(cpu_stdext_feature_l1_names); j++)
391 				if (regs[0] & (1 << j) &&
392 				    cpu_stdext_feature_l1_names[j][0] != '\0')
393 					sbuf_printf(sb, " %s",
394 					    cpu_stdext_feature_l1_names[j]);
395 		}
396 		sbuf_cat(sb, "\n");
397 		sbuf_printf(sb,
398 		    "bugs\t\t: %s\n"
399 		    "bogomips\t: %d.%02d\n"
400 		    "clflush size\t: %d\n"
401 		    "cache_alignment\t: %d\n"
402 		    "address sizes\t: %d bits physical, %d bits virtual\n",
403 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
404 		    (has_f00f_bug) ? "Intel F00F" : "",
405 #else
406 		    "",
407 #endif
408 		    fqmhz * 2, fqkhz,
409 		    cpu_clflush_line_size, cpu_clflush_line_size,
410 		    cpu_maxphyaddr,
411 		    (cpu_maxphyaddr > 32) ? 48 : 0);
412 		sbuf_cat(sb, "power management: ");
413 		for (j = 0; j < nitems(power_flags); j++)
414 			if (amd_pminfo & (1 << j))
415 				sbuf_printf(sb, " %s", power_flags[j]);
416 		sbuf_cat(sb, "\n\n");
417 
418 		/* XXX per-cpu vendor / class / model / id? */
419 	}
420 	sbuf_cat(sb, "\n");
421 
422 	return (0);
423 }
424 #else
425 /* ARM64TODO: implement non-stubbed linprocfs_docpuinfo */
426 static int
427 linprocfs_docpuinfo(PFS_FILL_ARGS)
428 {
429 	int i;
430 
431 	for (i = 0; i < mp_ncpus; ++i) {
432 		sbuf_printf(sb,
433 		    "processor\t: %d\n"
434 		    "BogoMIPS\t: %d.%02d\n",
435 		    i, 0, 0);
436 		sbuf_cat(sb, "Features\t: ");
437 		sbuf_cat(sb, "\n");
438 		sbuf_printf(sb,
439 		    "CPU implementer\t: \n"
440 		    "CPU architecture: \n"
441 		    "CPU variant\t: 0x%x\n"
442 		    "CPU part\t: 0x%x\n"
443 		    "CPU revision\t: %d\n",
444 		    0, 0, 0);
445 		sbuf_cat(sb, "\n");
446 	}
447 
448 	return (0);
449 }
450 #endif /* __i386__ || __amd64__ */
451 
452 static const char *path_slash_sys = "/sys";
453 static const char *fstype_sysfs = "sysfs";
454 
455 static int
456 _mtab_helper(const struct pfs_node *pn, const struct statfs *sp,
457     const char **mntfrom, const char **mntto, const char **fstype)
458 {
459 	/* determine device name */
460 	*mntfrom = sp->f_mntfromname;
461 
462 	/* determine mount point */
463 	*mntto = sp->f_mntonname;
464 
465 	/* determine fs type */
466 	*fstype = sp->f_fstypename;
467 	if (strcmp(*fstype, pn->pn_info->pi_name) == 0)
468 		*mntfrom = *fstype = "proc";
469 	else if (strcmp(*fstype, "procfs") == 0)
470 		return (ECANCELED);
471 
472 	if (strcmp(*fstype, "autofs") == 0) {
473 		/*
474 		 * FreeBSD uses eg "map -hosts", whereas Linux
475 		 * expects just "-hosts".
476 		 */
477 		if (strncmp(*mntfrom, "map ", 4) == 0)
478 			*mntfrom += 4;
479 	}
480 
481 	if (strcmp(*fstype, "linsysfs") == 0) {
482 		*mntfrom = path_slash_sys;
483 		*fstype = fstype_sysfs;
484 	} else {
485 		/* For Linux msdosfs is called vfat */
486 		if (strcmp(*fstype, "msdosfs") == 0)
487 			*fstype = "vfat";
488 	}
489 	return (0);
490 }
491 
492 static void
493 _sbuf_mntoptions_helper(struct sbuf *sb, uint64_t f_flags)
494 {
495 	sbuf_cat(sb, (f_flags & MNT_RDONLY) ? "ro" : "rw");
496 #define ADD_OPTION(opt, name) \
497 	if (f_flags & (opt)) sbuf_cat(sb, "," name);
498 	ADD_OPTION(MNT_SYNCHRONOUS,	"sync");
499 	ADD_OPTION(MNT_NOEXEC,		"noexec");
500 	ADD_OPTION(MNT_NOSUID,		"nosuid");
501 	ADD_OPTION(MNT_UNION,		"union");
502 	ADD_OPTION(MNT_ASYNC,		"async");
503 	ADD_OPTION(MNT_SUIDDIR,		"suiddir");
504 	ADD_OPTION(MNT_NOSYMFOLLOW,	"nosymfollow");
505 	ADD_OPTION(MNT_NOATIME,		"noatime");
506 #undef ADD_OPTION
507 }
508 
509 /*
510  * Filler function for proc/mtab and proc/<pid>/mounts.
511  *
512  * /proc/mtab doesn't exist in Linux' procfs, but is included here so
513  * users can symlink /compat/linux/etc/mtab to /proc/mtab
514  */
515 static int
516 linprocfs_domtab(PFS_FILL_ARGS)
517 {
518 	const char *mntto, *mntfrom, *fstype;
519 	char *dlep, *flep;
520 	struct vnode *vp;
521 	struct pwd *pwd;
522 	size_t lep_len;
523 	int error;
524 	struct statfs *buf, *sp;
525 	size_t count;
526 
527 	/*
528 	 * Resolve emulation tree prefix
529 	 */
530 	flep = NULL;
531 	pwd = pwd_hold(td);
532 	vp = pwd->pwd_adir;
533 	error = vn_fullpath_global(vp, &dlep, &flep);
534 	pwd_drop(pwd);
535 	if (error != 0)
536 		return (error);
537 	lep_len = strlen(dlep);
538 
539 	buf = NULL;
540 	error = kern_getfsstat(td, &buf, SIZE_T_MAX, &count,
541 	    UIO_SYSSPACE, MNT_WAIT);
542 	if (error != 0) {
543 		free(buf, M_TEMP);
544 		free(flep, M_TEMP);
545 		return (error);
546 	}
547 
548 	for (sp = buf; count > 0; sp++, count--) {
549 		error = _mtab_helper(pn, sp, &mntfrom, &mntto, &fstype);
550 		if (error != 0) {
551 			MPASS(error == ECANCELED);
552 			continue;
553 		}
554 
555 		/* determine mount point */
556 		if (strncmp(mntto, dlep, lep_len) == 0 && mntto[lep_len] == '/')
557 			mntto += lep_len;
558 
559 		sbuf_printf(sb, "%s %s %s ", mntfrom, mntto, fstype);
560 		_sbuf_mntoptions_helper(sb, sp->f_flags);
561 		/* a real Linux mtab will also show NFS options */
562 		sbuf_printf(sb, " 0 0\n");
563 	}
564 
565 	free(buf, M_TEMP);
566 	free(flep, M_TEMP);
567 	return (error);
568 }
569 
570 static int
571 linprocfs_doprocmountinfo(PFS_FILL_ARGS)
572 {
573 	const char *mntfrom, *mntto, *fstype;
574 	char *dlep, *flep;
575 	struct statfs *buf, *sp;
576 	size_t count, lep_len;
577 	struct vnode *vp;
578 	struct pwd *pwd;
579 	int error;
580 
581 	/*
582 	 * Resolve emulation tree prefix
583 	 */
584 	flep = NULL;
585 	pwd = pwd_hold(td);
586 	vp = pwd->pwd_adir;
587 	error = vn_fullpath_global(vp, &dlep, &flep);
588 	pwd_drop(pwd);
589 	if (error != 0)
590 		return (error);
591 	lep_len = strlen(dlep);
592 
593 	buf = NULL;
594 	error = kern_getfsstat(td, &buf, SIZE_T_MAX, &count,
595 	    UIO_SYSSPACE, MNT_WAIT);
596 	if (error != 0)
597 		goto out;
598 
599 	for (sp = buf; count > 0; sp++, count--) {
600 		error = _mtab_helper(pn, sp, &mntfrom, &mntto, &fstype);
601 		if (error != 0) {
602 			MPASS(error == ECANCELED);
603 			continue;
604 		}
605 
606 		if (strncmp(mntto, dlep, lep_len) == 0 && mntto[lep_len] == '/')
607 			mntto += lep_len;
608 #if 0
609 		/*
610 		 * If the prefix is a chroot, and this mountpoint is not under
611 		 * the prefix, we should skip it.  Leave it for now for
612 		 * consistency with procmtab above.
613 		 */
614 		else
615 			continue;
616 #endif
617 
618 		/*
619 		 * (1) mount id
620 		 *
621 		 * (2) parent mount id -- we don't have this cheaply, so
622 		 * provide a dummy value
623 		 *
624 		 * (3) major:minor -- ditto
625 		 *
626 		 * (4) root filesystem mount -- probably a namespaces thing
627 		 *
628 		 * (5) mountto path
629 		 */
630 		sbuf_printf(sb, "%u 0 0:0 / %s ",
631 		    sp->f_fsid.val[0] ^ sp->f_fsid.val[1], mntto);
632 		/* (6) mount options */
633 		_sbuf_mntoptions_helper(sb, sp->f_flags);
634 		/*
635 		 * (7) zero or more optional fields -- again, namespace related
636 		 *
637 		 * (8) End of variable length fields separator ("-")
638 		 *
639 		 * (9) fstype
640 		 *
641 		 * (10) mount from
642 		 *
643 		 * (11) "superblock" options -- like (6), but different
644 		 * semantics in Linux
645 		 */
646 		sbuf_printf(sb, " - %s %s %s\n", fstype, mntfrom,
647 		    (sp->f_flags & MNT_RDONLY) ? "ro" : "rw");
648 	}
649 
650 	error = 0;
651 out:
652 	free(buf, M_TEMP);
653 	free(flep, M_TEMP);
654 	return (error);
655 }
656 
657 /*
658  * Filler function for proc/partitions
659  */
660 static int
661 linprocfs_dopartitions(PFS_FILL_ARGS)
662 {
663 	struct g_class *cp;
664 	struct g_geom *gp;
665 	struct g_provider *pp;
666 	int major, minor;
667 
668 	g_topology_lock();
669 	sbuf_printf(sb, "major minor  #blocks  name rio rmerge rsect "
670 	    "ruse wio wmerge wsect wuse running use aveq\n");
671 
672 	LIST_FOREACH(cp, &g_classes, class) {
673 		if (strcmp(cp->name, "DISK") == 0 ||
674 		    strcmp(cp->name, "PART") == 0)
675 			LIST_FOREACH(gp, &cp->geom, geom) {
676 				LIST_FOREACH(pp, &gp->provider, provider) {
677 					if (linux_driver_get_major_minor(
678 					    pp->name, &major, &minor) != 0) {
679 						major = 0;
680 						minor = 0;
681 					}
682 					sbuf_printf(sb, "%d %d %lld %s "
683 					    "%d %d %d %d %d "
684 					     "%d %d %d %d %d %d\n",
685 					     major, minor,
686 					     (long long)pp->mediasize, pp->name,
687 					     0, 0, 0, 0, 0,
688 					     0, 0, 0, 0, 0, 0);
689 				}
690 			}
691 	}
692 	g_topology_unlock();
693 
694 	return (0);
695 }
696 
697 /*
698  * Filler function for proc/stat
699  *
700  * Output depends on kernel version:
701  *
702  * v2.5.40 <=
703  *   user nice system idle
704  * v2.5.41
705  *   user nice system idle iowait
706  * v2.6.11
707  *   user nice system idle iowait irq softirq steal
708  * v2.6.24
709  *   user nice system idle iowait irq softirq steal guest
710  * v2.6.33 >=
711  *   user nice system idle iowait irq softirq steal guest guest_nice
712  */
713 static int
714 linprocfs_dostat(PFS_FILL_ARGS)
715 {
716 	struct pcpu *pcpu;
717 	long cp_time[CPUSTATES];
718 	long *cp;
719 	struct timeval boottime;
720 	int i;
721 	char *zero_pad;
722 	bool has_intr = true;
723 
724 	if (linux_kernver(td) >= LINUX_KERNVER(2,6,33)) {
725 		zero_pad = " 0 0 0 0\n";
726 	} else if (linux_kernver(td) >= LINUX_KERNVER(2,6,24)) {
727 		zero_pad = " 0 0 0\n";
728 	} else if (linux_kernver(td) >= LINUX_KERNVER(2,6,11)) {
729 		zero_pad = " 0 0\n";
730 	} else if (linux_kernver(td) >= LINUX_KERNVER(2,5,41)) {
731 		has_intr = false;
732 		zero_pad = " 0\n";
733 	} else {
734 		has_intr = false;
735 		zero_pad = "\n";
736 	}
737 
738 	read_cpu_time(cp_time);
739 	getboottime(&boottime);
740 	/* Parameters common to all versions */
741 	sbuf_printf(sb, "cpu %lu %lu %lu %lu",
742 	    T2J(cp_time[CP_USER]),
743 	    T2J(cp_time[CP_NICE]),
744 	    T2J(cp_time[CP_SYS]),
745 	    T2J(cp_time[CP_IDLE]));
746 
747 	/* Print interrupt stats if available */
748 	if (has_intr) {
749 		sbuf_printf(sb, " 0 %lu", T2J(cp_time[CP_INTR]));
750 	}
751 
752 	/* Pad out remaining fields depending on version */
753 	sbuf_printf(sb, "%s", zero_pad);
754 
755 	CPU_FOREACH(i) {
756 		pcpu = pcpu_find(i);
757 		cp = pcpu->pc_cp_time;
758 		sbuf_printf(sb, "cpu%d %lu %lu %lu %lu", i,
759 		    T2J(cp[CP_USER]),
760 		    T2J(cp[CP_NICE]),
761 		    T2J(cp[CP_SYS]),
762 		    T2J(cp[CP_IDLE]));
763 
764 		if (has_intr) {
765 			sbuf_printf(sb, " 0 %lu", T2J(cp[CP_INTR]));
766 		}
767 
768 		sbuf_printf(sb, "%s", zero_pad);
769 	}
770 	sbuf_printf(sb,
771 	    "disk 0 0 0 0\n"
772 	    "page %ju %ju\n"
773 	    "swap %ju %ju\n"
774 	    "intr %ju\n"
775 	    "ctxt %ju\n"
776 	    "btime %lld\n",
777 	    (uintmax_t)VM_CNT_FETCH(v_vnodepgsin),
778 	    (uintmax_t)VM_CNT_FETCH(v_vnodepgsout),
779 	    (uintmax_t)VM_CNT_FETCH(v_swappgsin),
780 	    (uintmax_t)VM_CNT_FETCH(v_swappgsout),
781 	    (uintmax_t)VM_CNT_FETCH(v_intr),
782 	    (uintmax_t)VM_CNT_FETCH(v_swtch),
783 	    (long long)boottime.tv_sec);
784 	return (0);
785 }
786 
787 static int
788 linprocfs_doswaps(PFS_FILL_ARGS)
789 {
790 	struct xswdev xsw;
791 	uintmax_t total, used;
792 	int n;
793 	char devname[SPECNAMELEN + 1];
794 
795 	sbuf_printf(sb, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n");
796 	for (n = 0; ; n++) {
797 		if (swap_dev_info(n, &xsw, devname, sizeof(devname)) != 0)
798 			break;
799 		total = (uintmax_t)xsw.xsw_nblks * PAGE_SIZE / 1024;
800 		used  = (uintmax_t)xsw.xsw_used * PAGE_SIZE / 1024;
801 
802 		/*
803 		 * The space and not tab after the device name is on
804 		 * purpose.  Linux does so.
805 		 */
806 		sbuf_printf(sb, "/dev/%-34s unknown\t\t%jd\t%jd\t-1\n",
807 		    devname, total, used);
808 	}
809 	return (0);
810 }
811 
812 /*
813  * Filler function for proc/uptime
814  */
815 static int
816 linprocfs_douptime(PFS_FILL_ARGS)
817 {
818 	long cp_time[CPUSTATES];
819 	struct timeval tv;
820 
821 	getmicrouptime(&tv);
822 	read_cpu_time(cp_time);
823 	sbuf_printf(sb, "%lld.%02ld %ld.%02lu\n",
824 	    (long long)tv.tv_sec, tv.tv_usec / 10000,
825 	    T2S(cp_time[CP_IDLE] / mp_ncpus),
826 	    T2CS(cp_time[CP_IDLE] / mp_ncpus) % 100);
827 	return (0);
828 }
829 
830 /*
831  * Get OS build date
832  */
833 static void
834 linprocfs_osbuild(struct thread *td, struct sbuf *sb)
835 {
836 #if 0
837 	char osbuild[256];
838 	char *cp1, *cp2;
839 
840 	strncpy(osbuild, version, 256);
841 	osbuild[255] = '\0';
842 	cp1 = strstr(osbuild, "\n");
843 	cp2 = strstr(osbuild, ":");
844 	if (cp1 && cp2) {
845 		*cp1 = *cp2 = '\0';
846 		cp1 = strstr(osbuild, "#");
847 	} else
848 		cp1 = NULL;
849 	if (cp1)
850 		sbuf_printf(sb, "%s%s", cp1, cp2 + 1);
851 	else
852 #endif
853 		sbuf_cat(sb, "#4 Sun Dec 18 04:30:00 CET 1977");
854 }
855 
856 /*
857  * Get OS builder
858  */
859 static void
860 linprocfs_osbuilder(struct thread *td, struct sbuf *sb)
861 {
862 #if 0
863 	char builder[256];
864 	char *cp;
865 
866 	cp = strstr(version, "\n    ");
867 	if (cp) {
868 		strncpy(builder, cp + 5, 256);
869 		builder[255] = '\0';
870 		cp = strstr(builder, ":");
871 		if (cp)
872 			*cp = '\0';
873 	}
874 	if (cp)
875 		sbuf_cat(sb, builder);
876 	else
877 #endif
878 		sbuf_cat(sb, "des@freebsd.org");
879 }
880 
881 /*
882  * Filler function for proc/version
883  */
884 static int
885 linprocfs_doversion(PFS_FILL_ARGS)
886 {
887 	char osname[LINUX_MAX_UTSNAME];
888 	char osrelease[LINUX_MAX_UTSNAME];
889 
890 	linux_get_osname(td, osname);
891 	linux_get_osrelease(td, osrelease);
892 	sbuf_printf(sb, "%s version %s (", osname, osrelease);
893 	linprocfs_osbuilder(td, sb);
894 	sbuf_cat(sb, ") (gcc version " __VERSION__ ") ");
895 	linprocfs_osbuild(td, sb);
896 	sbuf_cat(sb, "\n");
897 
898 	return (0);
899 }
900 
901 /*
902  * Filler function for proc/loadavg
903  */
904 static int
905 linprocfs_doloadavg(PFS_FILL_ARGS)
906 {
907 
908 	sbuf_printf(sb,
909 	    "%d.%02d %d.%02d %d.%02d %d/%d %d\n",
910 	    (int)(averunnable.ldavg[0] / averunnable.fscale),
911 	    (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100),
912 	    (int)(averunnable.ldavg[1] / averunnable.fscale),
913 	    (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100),
914 	    (int)(averunnable.ldavg[2] / averunnable.fscale),
915 	    (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100),
916 	    1,				/* number of running tasks */
917 	    nprocs,			/* number of tasks */
918 	    lastpid			/* the last pid */
919 	);
920 	return (0);
921 }
922 
923 static int
924 linprocfs_get_tty_nr(struct proc *p)
925 {
926 	struct session *sp;
927 	const char *ttyname;
928 	int error, major, minor, nr;
929 
930 	PROC_LOCK_ASSERT(p, MA_OWNED);
931 	sx_assert(&proctree_lock, SX_LOCKED);
932 
933 	if ((p->p_flag & P_CONTROLT) == 0)
934 		return (-1);
935 
936 	sp = p->p_pgrp->pg_session;
937 	if (sp == NULL)
938 		return (-1);
939 
940 	ttyname = devtoname(sp->s_ttyp->t_dev);
941 	error = linux_driver_get_major_minor(ttyname, &major, &minor);
942 	if (error != 0)
943 		return (-1);
944 
945 	nr = makedev(major, minor);
946 	return (nr);
947 }
948 
949 /*
950  * Filler function for proc/pid/stat
951  */
952 static int
953 linprocfs_doprocstat(PFS_FILL_ARGS)
954 {
955 	struct kinfo_proc kp;
956 	struct timeval boottime;
957 	char state;
958 	static int ratelimit = 0;
959 	int tty_nr;
960 	vm_offset_t startcode, startdata;
961 
962 	getboottime(&boottime);
963 	sx_slock(&proctree_lock);
964 	PROC_LOCK(p);
965 	fill_kinfo_proc(p, &kp);
966 	tty_nr = linprocfs_get_tty_nr(p);
967 	sx_sunlock(&proctree_lock);
968 	if (p->p_vmspace) {
969 	   startcode = (vm_offset_t)p->p_vmspace->vm_taddr;
970 	   startdata = (vm_offset_t)p->p_vmspace->vm_daddr;
971 	} else {
972 	   startcode = 0;
973 	   startdata = 0;
974 	}
975 	sbuf_printf(sb, "%d", p->p_pid);
976 #define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg)
977 	PS_ADD("comm",		"(%s)",	p->p_comm);
978 	if (kp.ki_stat > sizeof(linux_state)) {
979 		state = 'R';
980 
981 		if (ratelimit == 0) {
982 			printf("linprocfs: don't know how to handle unknown FreeBSD state %d/%zd, mapping to R\n",
983 			    kp.ki_stat, sizeof(linux_state));
984 			++ratelimit;
985 		}
986 	} else
987 		state = linux_state[kp.ki_stat - 1];
988 	PS_ADD("state",		"%c",	state);
989 	PS_ADD("ppid",		"%d",	p->p_pptr ? p->p_pptr->p_pid : 0);
990 	PS_ADD("pgrp",		"%d",	p->p_pgid);
991 	PS_ADD("session",	"%d",	p->p_session->s_sid);
992 	PROC_UNLOCK(p);
993 	PS_ADD("tty",		"%d",	tty_nr);
994 	PS_ADD("tpgid",		"%d",	kp.ki_tpgid);
995 	PS_ADD("flags",		"%u",	0); /* XXX */
996 	PS_ADD("minflt",	"%lu",	kp.ki_rusage.ru_minflt);
997 	PS_ADD("cminflt",	"%lu",	kp.ki_rusage_ch.ru_minflt);
998 	PS_ADD("majflt",	"%lu",	kp.ki_rusage.ru_majflt);
999 	PS_ADD("cmajflt",	"%lu",	kp.ki_rusage_ch.ru_majflt);
1000 	PS_ADD("utime",		"%ld",	TV2J(&kp.ki_rusage.ru_utime));
1001 	PS_ADD("stime",		"%ld",	TV2J(&kp.ki_rusage.ru_stime));
1002 	PS_ADD("cutime",	"%ld",	TV2J(&kp.ki_rusage_ch.ru_utime));
1003 	PS_ADD("cstime",	"%ld",	TV2J(&kp.ki_rusage_ch.ru_stime));
1004 	PS_ADD("priority",	"%d",	kp.ki_pri.pri_user);
1005 	PS_ADD("nice",		"%d",	kp.ki_nice); /* 19 (nicest) to -19 */
1006 	PS_ADD("0",		"%d",	0); /* removed field */
1007 	PS_ADD("itrealvalue",	"%d",	0); /* XXX */
1008 	PS_ADD("starttime",	"%lu",	TV2J(&kp.ki_start) - TV2J(&boottime));
1009 	PS_ADD("vsize",		"%ju",	(uintmax_t)kp.ki_size);
1010 	PS_ADD("rss",		"%ju",	(uintmax_t)kp.ki_rssize);
1011 	PS_ADD("rlim",		"%lu",	kp.ki_rusage.ru_maxrss);
1012 	PS_ADD("startcode",	"%ju",	(uintmax_t)startcode);
1013 	PS_ADD("endcode",	"%ju",	(uintmax_t)startdata);
1014 	PS_ADD("startstack",	"%u",	0); /* XXX */
1015 	PS_ADD("kstkesp",	"%u",	0); /* XXX */
1016 	PS_ADD("kstkeip",	"%u",	0); /* XXX */
1017 	PS_ADD("signal",	"%u",	0); /* XXX */
1018 	PS_ADD("blocked",	"%u",	0); /* XXX */
1019 	PS_ADD("sigignore",	"%u",	0); /* XXX */
1020 	PS_ADD("sigcatch",	"%u",	0); /* XXX */
1021 	PS_ADD("wchan",		"%u",	0); /* XXX */
1022 	PS_ADD("nswap",		"%lu",	kp.ki_rusage.ru_nswap);
1023 	PS_ADD("cnswap",	"%lu",	kp.ki_rusage_ch.ru_nswap);
1024 	PS_ADD("exitsignal",	"%d",	0); /* XXX */
1025 	PS_ADD("processor",	"%u",	kp.ki_lastcpu);
1026 	PS_ADD("rt_priority",	"%u",	0); /* XXX */ /* >= 2.5.19 */
1027 	PS_ADD("policy",	"%u",	kp.ki_pri.pri_class); /* >= 2.5.19 */
1028 #undef PS_ADD
1029 	sbuf_putc(sb, '\n');
1030 
1031 	return (0);
1032 }
1033 
1034 /*
1035  * Filler function for proc/pid/statm
1036  */
1037 static int
1038 linprocfs_doprocstatm(PFS_FILL_ARGS)
1039 {
1040 	struct kinfo_proc kp;
1041 	segsz_t lsize;
1042 
1043 	sx_slock(&proctree_lock);
1044 	PROC_LOCK(p);
1045 	fill_kinfo_proc(p, &kp);
1046 	PROC_UNLOCK(p);
1047 	sx_sunlock(&proctree_lock);
1048 
1049 	/*
1050 	 * See comments in linprocfs_doprocstatus() regarding the
1051 	 * computation of lsize.
1052 	 */
1053 	/* size resident share trs drs lrs dt */
1054 	sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size));
1055 	sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize);
1056 	sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */
1057 	sbuf_printf(sb, "%ju ",	(uintmax_t)kp.ki_tsize);
1058 	sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize));
1059 	lsize = B2P(kp.ki_size) - kp.ki_dsize -
1060 	    kp.ki_ssize - kp.ki_tsize - 1;
1061 	sbuf_printf(sb, "%ju ", (uintmax_t)lsize);
1062 	sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */
1063 
1064 	return (0);
1065 }
1066 
1067 /*
1068  * Filler function for proc/pid/status
1069  */
1070 static int
1071 linprocfs_doprocstatus(PFS_FILL_ARGS)
1072 {
1073 	struct kinfo_proc kp;
1074 	char *state;
1075 	segsz_t lsize;
1076 	struct thread *td2;
1077 	struct sigacts *ps;
1078 	l_sigset_t siglist, sigignore, sigcatch;
1079 	int i;
1080 
1081 	sx_slock(&proctree_lock);
1082 	PROC_LOCK(p);
1083 	td2 = FIRST_THREAD_IN_PROC(p);
1084 
1085 	if (P_SHOULDSTOP(p)) {
1086 		state = "T (stopped)";
1087 	} else {
1088 		switch(p->p_state) {
1089 		case PRS_NEW:
1090 			state = "I (idle)";
1091 			break;
1092 		case PRS_NORMAL:
1093 			if (p->p_flag & P_WEXIT) {
1094 				state = "X (exiting)";
1095 				break;
1096 			}
1097 			switch(TD_GET_STATE(td2)) {
1098 			case TDS_INHIBITED:
1099 				state = "S (sleeping)";
1100 				break;
1101 			case TDS_RUNQ:
1102 			case TDS_RUNNING:
1103 				state = "R (running)";
1104 				break;
1105 			default:
1106 				state = "? (unknown)";
1107 				break;
1108 			}
1109 			break;
1110 		case PRS_ZOMBIE:
1111 			state = "Z (zombie)";
1112 			break;
1113 		default:
1114 			state = "? (unknown)";
1115 			break;
1116 		}
1117 	}
1118 
1119 	fill_kinfo_proc(p, &kp);
1120 	sx_sunlock(&proctree_lock);
1121 
1122 	sbuf_printf(sb, "Name:\t%s\n",		p->p_comm); /* XXX escape */
1123 	sbuf_printf(sb, "State:\t%s\n",		state);
1124 
1125 	/*
1126 	 * Credentials
1127 	 */
1128 	sbuf_printf(sb, "Tgid:\t%d\n",		p->p_pid);
1129 	sbuf_printf(sb, "Pid:\t%d\n",		p->p_pid);
1130 	sbuf_printf(sb, "PPid:\t%d\n",		kp.ki_ppid );
1131 	sbuf_printf(sb, "TracerPid:\t%d\n",	kp.ki_tracer );
1132 	sbuf_printf(sb, "Uid:\t%d\t%d\t%d\t%d\n", p->p_ucred->cr_ruid,
1133 						p->p_ucred->cr_uid,
1134 						p->p_ucred->cr_svuid,
1135 						/* FreeBSD doesn't have fsuid */
1136 						p->p_ucred->cr_uid);
1137 	sbuf_printf(sb, "Gid:\t%d\t%d\t%d\t%d\n", p->p_ucred->cr_rgid,
1138 						p->p_ucred->cr_gid,
1139 						p->p_ucred->cr_svgid,
1140 						/* FreeBSD doesn't have fsgid */
1141 						p->p_ucred->cr_gid);
1142 	sbuf_cat(sb, "Groups:\t");
1143 	for (i = 0; i < p->p_ucred->cr_ngroups; i++)
1144 		sbuf_printf(sb, "%d ",		p->p_ucred->cr_groups[i]);
1145 	PROC_UNLOCK(p);
1146 	sbuf_putc(sb, '\n');
1147 
1148 	/*
1149 	 * Memory
1150 	 *
1151 	 * While our approximation of VmLib may not be accurate (I
1152 	 * don't know of a simple way to verify it, and I'm not sure
1153 	 * it has much meaning anyway), I believe it's good enough.
1154 	 *
1155 	 * The same code that could (I think) accurately compute VmLib
1156 	 * could also compute VmLck, but I don't really care enough to
1157 	 * implement it. Submissions are welcome.
1158 	 */
1159 	sbuf_printf(sb, "VmSize:\t%8ju kB\n",	B2K((uintmax_t)kp.ki_size));
1160 	sbuf_printf(sb, "VmLck:\t%8u kB\n",	P2K(0)); /* XXX */
1161 	sbuf_printf(sb, "VmRSS:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_rssize));
1162 	sbuf_printf(sb, "VmData:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_dsize));
1163 	sbuf_printf(sb, "VmStk:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_ssize));
1164 	sbuf_printf(sb, "VmExe:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_tsize));
1165 	lsize = B2P(kp.ki_size) - kp.ki_dsize -
1166 	    kp.ki_ssize - kp.ki_tsize - 1;
1167 	sbuf_printf(sb, "VmLib:\t%8ju kB\n",	P2K((uintmax_t)lsize));
1168 
1169 	/*
1170 	 * Signal masks
1171 	 */
1172 	PROC_LOCK(p);
1173 	bsd_to_linux_sigset(&p->p_siglist, &siglist);
1174 	ps = p->p_sigacts;
1175 	mtx_lock(&ps->ps_mtx);
1176 	bsd_to_linux_sigset(&ps->ps_sigignore, &sigignore);
1177 	bsd_to_linux_sigset(&ps->ps_sigcatch, &sigcatch);
1178 	mtx_unlock(&ps->ps_mtx);
1179 	PROC_UNLOCK(p);
1180 
1181 	sbuf_printf(sb, "SigPnd:\t%016jx\n",	siglist.__mask);
1182 	/*
1183 	 * XXX. SigBlk - target thread's signal mask, td_sigmask.
1184 	 * To implement SigBlk pseudofs should support proc/tid dir entries.
1185 	 */
1186 	sbuf_printf(sb, "SigBlk:\t%016x\n",	0);
1187 	sbuf_printf(sb, "SigIgn:\t%016jx\n",	sigignore.__mask);
1188 	sbuf_printf(sb, "SigCgt:\t%016jx\n",	sigcatch.__mask);
1189 
1190 	/*
1191 	 * Linux also prints the capability masks, but we don't have
1192 	 * capabilities yet, and when we do get them they're likely to
1193 	 * be meaningless to Linux programs, so we lie. XXX
1194 	 */
1195 	sbuf_printf(sb, "CapInh:\t%016x\n",	0);
1196 	sbuf_printf(sb, "CapPrm:\t%016x\n",	0);
1197 	sbuf_printf(sb, "CapEff:\t%016x\n",	0);
1198 
1199 	return (0);
1200 }
1201 
1202 /*
1203  * Filler function for proc/pid/cwd
1204  */
1205 static int
1206 linprocfs_doproccwd(PFS_FILL_ARGS)
1207 {
1208 	struct pwd *pwd;
1209 	char *fullpath = "unknown";
1210 	char *freepath = NULL;
1211 
1212 	pwd = pwd_hold_proc(p);
1213 	vn_fullpath(pwd->pwd_cdir, &fullpath, &freepath);
1214 	sbuf_printf(sb, "%s", fullpath);
1215 	if (freepath)
1216 		free(freepath, M_TEMP);
1217 	pwd_drop(pwd);
1218 	return (0);
1219 }
1220 
1221 /*
1222  * Filler function for proc/pid/root
1223  */
1224 static int
1225 linprocfs_doprocroot(PFS_FILL_ARGS)
1226 {
1227 	struct pwd *pwd;
1228 	struct vnode *vp;
1229 	char *fullpath = "unknown";
1230 	char *freepath = NULL;
1231 
1232 	pwd = pwd_hold_proc(p);
1233 	vp = jailed(p->p_ucred) ? pwd->pwd_jdir : pwd->pwd_rdir;
1234 	vn_fullpath(vp, &fullpath, &freepath);
1235 	sbuf_printf(sb, "%s", fullpath);
1236 	if (freepath)
1237 		free(freepath, M_TEMP);
1238 	pwd_drop(pwd);
1239 	return (0);
1240 }
1241 
1242 /*
1243  * Filler function for proc/pid/cmdline
1244  */
1245 static int
1246 linprocfs_doproccmdline(PFS_FILL_ARGS)
1247 {
1248 	int ret;
1249 
1250 	PROC_LOCK(p);
1251 	if ((ret = p_cansee(td, p)) != 0) {
1252 		PROC_UNLOCK(p);
1253 		return (ret);
1254 	}
1255 
1256 	/*
1257 	 * Mimic linux behavior and pass only processes with usermode
1258 	 * address space as valid.  Return zero silently otherwize.
1259 	 */
1260 	if (p->p_vmspace == &vmspace0) {
1261 		PROC_UNLOCK(p);
1262 		return (0);
1263 	}
1264 	if (p->p_args != NULL) {
1265 		sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length);
1266 		PROC_UNLOCK(p);
1267 		return (0);
1268 	}
1269 
1270 	if ((p->p_flag & P_SYSTEM) != 0) {
1271 		PROC_UNLOCK(p);
1272 		return (0);
1273 	}
1274 
1275 	PROC_UNLOCK(p);
1276 
1277 	ret = proc_getargv(td, p, sb);
1278 	return (ret);
1279 }
1280 
1281 /*
1282  * Filler function for proc/pid/environ
1283  */
1284 static int
1285 linprocfs_doprocenviron(PFS_FILL_ARGS)
1286 {
1287 
1288 	/*
1289 	 * Mimic linux behavior and pass only processes with usermode
1290 	 * address space as valid.  Return zero silently otherwize.
1291 	 */
1292 	if (p->p_vmspace == &vmspace0)
1293 		return (0);
1294 
1295 	return (proc_getenvv(td, p, sb));
1296 }
1297 
1298 static char l32_map_str[] = "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n";
1299 static char l64_map_str[] = "%016lx-%016lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n";
1300 static char vdso_str[] = "      [vdso]";
1301 static char stack_str[] = "      [stack]";
1302 
1303 /*
1304  * Filler function for proc/pid/maps
1305  */
1306 static int
1307 linprocfs_doprocmaps(PFS_FILL_ARGS)
1308 {
1309 	struct vmspace *vm;
1310 	vm_map_t map;
1311 	vm_map_entry_t entry, tmp_entry;
1312 	vm_object_t obj, tobj, lobj;
1313 	vm_offset_t e_start, e_end;
1314 	vm_ooffset_t off;
1315 	vm_prot_t e_prot;
1316 	unsigned int last_timestamp;
1317 	char *name = "", *freename = NULL;
1318 	const char *l_map_str;
1319 	ino_t ino;
1320 	int error;
1321 	struct vnode *vp;
1322 	struct vattr vat;
1323 	bool private;
1324 
1325 	PROC_LOCK(p);
1326 	error = p_candebug(td, p);
1327 	PROC_UNLOCK(p);
1328 	if (error)
1329 		return (error);
1330 
1331 	if (uio->uio_rw != UIO_READ)
1332 		return (EOPNOTSUPP);
1333 
1334 	error = 0;
1335 	vm = vmspace_acquire_ref(p);
1336 	if (vm == NULL)
1337 		return (ESRCH);
1338 
1339 	if (SV_CURPROC_FLAG(SV_LP64))
1340 		l_map_str = l64_map_str;
1341 	else
1342 		l_map_str = l32_map_str;
1343 	map = &vm->vm_map;
1344 	vm_map_lock_read(map);
1345 	VM_MAP_ENTRY_FOREACH(entry, map) {
1346 		name = "";
1347 		freename = NULL;
1348 		/*
1349 		 * Skip printing of the guard page of the stack region, as
1350 		 * it confuses glibc pthread_getattr_np() method, where both
1351 		 * the base address and size of the stack of the initial thread
1352 		 * are calculated.
1353 		 */
1354 		if ((entry->eflags & (MAP_ENTRY_IS_SUB_MAP | MAP_ENTRY_GUARD)) != 0)
1355 			continue;
1356 		e_prot = entry->protection;
1357 		e_start = entry->start;
1358 		e_end = entry->end;
1359 		obj = entry->object.vm_object;
1360 		off = entry->offset;
1361 		for (lobj = tobj = obj; tobj != NULL;
1362 		    lobj = tobj, tobj = tobj->backing_object) {
1363 			VM_OBJECT_RLOCK(tobj);
1364 			off += lobj->backing_object_offset;
1365 			if (lobj != obj)
1366 				VM_OBJECT_RUNLOCK(lobj);
1367 		}
1368 		private = (entry->eflags & MAP_ENTRY_COW) != 0 || obj == NULL ||
1369 		    (obj->flags & OBJ_ANON) != 0;
1370 		last_timestamp = map->timestamp;
1371 		vm_map_unlock_read(map);
1372 		ino = 0;
1373 		if (lobj) {
1374 			vp = vm_object_vnode(lobj);
1375 			if (vp != NULL)
1376 				vref(vp);
1377 			if (lobj != obj)
1378 				VM_OBJECT_RUNLOCK(lobj);
1379 			VM_OBJECT_RUNLOCK(obj);
1380 			if (vp != NULL) {
1381 				vn_fullpath(vp, &name, &freename);
1382 				vn_lock(vp, LK_SHARED | LK_RETRY);
1383 				VOP_GETATTR(vp, &vat, td->td_ucred);
1384 				ino = vat.va_fileid;
1385 				vput(vp);
1386 			} else if (SV_PROC_ABI(p) == SV_ABI_LINUX) {
1387 				/*
1388 				 * sv_shared_page_base pointed out to the
1389 				 * FreeBSD sharedpage, PAGE_SIZE is a size
1390 				 * of it. The vDSO page is above.
1391 				 */
1392 				if (e_start == p->p_sysent->sv_shared_page_base +
1393 				    PAGE_SIZE)
1394 					name = vdso_str;
1395 				if (e_end == p->p_sysent->sv_usrstack)
1396 					name = stack_str;
1397 			}
1398 		}
1399 
1400 		/*
1401 		 * format:
1402 		 *  start, end, access, offset, major, minor, inode, name.
1403 		 */
1404 		error = sbuf_printf(sb, l_map_str,
1405 		    (u_long)e_start, (u_long)e_end,
1406 		    (e_prot & VM_PROT_READ)?"r":"-",
1407 		    (e_prot & VM_PROT_WRITE)?"w":"-",
1408 		    (e_prot & VM_PROT_EXECUTE)?"x":"-",
1409 		    private ? "p" : "s",
1410 		    (u_long)off,
1411 		    0,
1412 		    0,
1413 		    (u_long)ino,
1414 		    *name ? "     " : " ",
1415 		    name
1416 		    );
1417 		if (freename)
1418 			free(freename, M_TEMP);
1419 		vm_map_lock_read(map);
1420 		if (error == -1) {
1421 			error = 0;
1422 			break;
1423 		}
1424 		if (last_timestamp != map->timestamp) {
1425 			/*
1426 			 * Look again for the entry because the map was
1427 			 * modified while it was unlocked.  Specifically,
1428 			 * the entry may have been clipped, merged, or deleted.
1429 			 */
1430 			vm_map_lookup_entry(map, e_end - 1, &tmp_entry);
1431 			entry = tmp_entry;
1432 		}
1433 	}
1434 	vm_map_unlock_read(map);
1435 	vmspace_free(vm);
1436 
1437 	return (error);
1438 }
1439 
1440 /*
1441  * Filler function for proc/pid/mem
1442  */
1443 static int
1444 linprocfs_doprocmem(PFS_FILL_ARGS)
1445 {
1446 	ssize_t resid;
1447 	int error;
1448 
1449 	resid = uio->uio_resid;
1450 	error = procfs_doprocmem(PFS_FILL_ARGNAMES);
1451 
1452 	if (uio->uio_rw == UIO_READ && resid != uio->uio_resid)
1453 		return (0);
1454 
1455 	if (error == EFAULT)
1456 		error = EIO;
1457 
1458 	return (error);
1459 }
1460 
1461 /*
1462  * Filler function for proc/net/dev
1463  */
1464 static int
1465 linprocfs_donetdev_cb(if_t ifp, void *arg)
1466 {
1467 	char ifname[LINUX_IFNAMSIZ];
1468 	struct sbuf *sb = arg;
1469 
1470 	if (ifname_bsd_to_linux_ifp(ifp, ifname, sizeof(ifname)) <= 0)
1471 		return (ENODEV);
1472 
1473 	sbuf_printf(sb, "%6.6s: ", ifname);
1474 	sbuf_printf(sb, "%7ju %7ju %4ju %4ju %4lu %5lu %10lu %9ju ",
1475 	    (uintmax_t)if_getcounter(ifp, IFCOUNTER_IBYTES),
1476 	    (uintmax_t)if_getcounter(ifp, IFCOUNTER_IPACKETS),
1477 	    (uintmax_t)if_getcounter(ifp, IFCOUNTER_IERRORS),
1478 	    (uintmax_t)if_getcounter(ifp, IFCOUNTER_IQDROPS),
1479 						/* rx_missed_errors */
1480 	    0UL,				/* rx_fifo_errors */
1481 	    0UL,				/* rx_length_errors +
1482 						 * rx_over_errors +
1483 						 * rx_crc_errors +
1484 						 * rx_frame_errors */
1485 	    0UL,				/* rx_compressed */
1486 	    (uintmax_t)if_getcounter(ifp, IFCOUNTER_IMCASTS));
1487 						/* XXX-BZ rx only? */
1488 	sbuf_printf(sb, "%8ju %7ju %4ju %4ju %4lu %5ju %7lu %10lu\n",
1489 	    (uintmax_t)if_getcounter(ifp, IFCOUNTER_OBYTES),
1490 	    (uintmax_t)if_getcounter(ifp, IFCOUNTER_OPACKETS),
1491 	    (uintmax_t)if_getcounter(ifp, IFCOUNTER_OERRORS),
1492 	    (uintmax_t)if_getcounter(ifp, IFCOUNTER_OQDROPS),
1493 	    0UL,				/* tx_fifo_errors */
1494 	    (uintmax_t)if_getcounter(ifp, IFCOUNTER_COLLISIONS),
1495 	    0UL,				/* tx_carrier_errors +
1496 						 * tx_aborted_errors +
1497 						 * tx_window_errors +
1498 						 * tx_heartbeat_errors*/
1499 	    0UL);				/* tx_compressed */
1500 	return (0);
1501 }
1502 
1503 static int
1504 linprocfs_donetdev(PFS_FILL_ARGS)
1505 {
1506 	struct epoch_tracker et;
1507 
1508 	sbuf_printf(sb, "%6s|%58s|%s\n"
1509 	    "%6s|%58s|%58s\n",
1510 	    "Inter-", "   Receive", "  Transmit",
1511 	    " face",
1512 	    "bytes    packets errs drop fifo frame compressed multicast",
1513 	    "bytes    packets errs drop fifo colls carrier compressed");
1514 
1515 	CURVNET_SET(TD_TO_VNET(curthread));
1516 	NET_EPOCH_ENTER(et);
1517 	if_foreach(linprocfs_donetdev_cb, sb);
1518 	NET_EPOCH_EXIT(et);
1519 	CURVNET_RESTORE();
1520 
1521 	return (0);
1522 }
1523 
1524 struct walkarg {
1525 	struct sbuf *sb;
1526 };
1527 
1528 static int
1529 linux_route_print(struct rtentry *rt, void *vw)
1530 {
1531 #ifdef INET
1532 	struct walkarg *w = vw;
1533 	struct route_nhop_data rnd;
1534 	struct in_addr dst, mask;
1535 	struct nhop_object *nh;
1536 	char ifname[16];
1537 	uint32_t scopeid = 0;
1538 	uint32_t gw = 0;
1539 	uint32_t linux_flags = 0;
1540 
1541 	rt_get_inet_prefix_pmask(rt, &dst, &mask, &scopeid);
1542 
1543 	rt_get_rnd(rt, &rnd);
1544 
1545 	/* select only first route in case of multipath */
1546 	nh = nhop_select_func(rnd.rnd_nhop, 0);
1547 
1548 	if (ifname_bsd_to_linux_ifp(nh->nh_ifp, ifname, sizeof(ifname)) <= 0)
1549 		return (ENODEV);
1550 
1551 	gw = (nh->nh_flags & NHF_GATEWAY)
1552 		? nh->gw4_sa.sin_addr.s_addr : 0;
1553 
1554 	linux_flags = RTF_UP |
1555 		(nhop_get_rtflags(nh) & (RTF_GATEWAY | RTF_HOST));
1556 
1557 	sbuf_printf(w->sb,
1558 		"%s\t"
1559 		"%08X\t%08X\t%04X\t"
1560 		"%d\t%u\t%d\t"
1561 		"%08X\t%d\t%u\t%u",
1562 		ifname,
1563 		dst.s_addr, gw, linux_flags,
1564 		0, 0, rnd.rnd_weight,
1565 		mask.s_addr, nh->nh_mtu, 0, 0);
1566 
1567 	sbuf_printf(w->sb, "\n\n");
1568 #endif
1569 	return (0);
1570 }
1571 
1572 /*
1573  * Filler function for proc/net/route
1574  */
1575 static int
1576 linprocfs_donetroute(PFS_FILL_ARGS)
1577 {
1578 	struct epoch_tracker et;
1579 	struct walkarg w = {
1580 		.sb = sb
1581 	};
1582 	uint32_t fibnum = curthread->td_proc->p_fibnum;
1583 
1584 	sbuf_printf(w.sb, "%-127s\n", "Iface\tDestination\tGateway "
1585                "\tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU"
1586                "\tWindow\tIRTT");
1587 
1588 	CURVNET_SET(TD_TO_VNET(curthread));
1589 	NET_EPOCH_ENTER(et);
1590 	rib_walk(fibnum, AF_INET, false, linux_route_print, &w);
1591 	NET_EPOCH_EXIT(et);
1592 	CURVNET_RESTORE();
1593 
1594 	return (0);
1595 }
1596 
1597 /*
1598  * Filler function for proc/sys/kernel/osrelease
1599  */
1600 static int
1601 linprocfs_doosrelease(PFS_FILL_ARGS)
1602 {
1603 	char osrelease[LINUX_MAX_UTSNAME];
1604 
1605 	linux_get_osrelease(td, osrelease);
1606 	sbuf_printf(sb, "%s\n", osrelease);
1607 
1608 	return (0);
1609 }
1610 
1611 /*
1612  * Filler function for proc/sys/kernel/ostype
1613  */
1614 static int
1615 linprocfs_doostype(PFS_FILL_ARGS)
1616 {
1617 	char osname[LINUX_MAX_UTSNAME];
1618 
1619 	linux_get_osname(td, osname);
1620 	sbuf_printf(sb, "%s\n", osname);
1621 
1622 	return (0);
1623 }
1624 
1625 /*
1626  * Filler function for proc/sys/kernel/version
1627  */
1628 static int
1629 linprocfs_doosbuild(PFS_FILL_ARGS)
1630 {
1631 
1632 	linprocfs_osbuild(td, sb);
1633 	sbuf_cat(sb, "\n");
1634 	return (0);
1635 }
1636 
1637 /*
1638  * Filler function for proc/sys/kernel/msgmax
1639  */
1640 static int
1641 linprocfs_domsgmax(PFS_FILL_ARGS)
1642 {
1643 
1644 	sbuf_printf(sb, "%d\n", msginfo.msgmax);
1645 	return (0);
1646 }
1647 
1648 /*
1649  * Filler function for proc/sys/kernel/msgmni
1650  */
1651 static int
1652 linprocfs_domsgmni(PFS_FILL_ARGS)
1653 {
1654 
1655 	sbuf_printf(sb, "%d\n", msginfo.msgmni);
1656 	return (0);
1657 }
1658 
1659 /*
1660  * Filler function for proc/sys/kernel/msgmnb
1661  */
1662 static int
1663 linprocfs_domsgmnb(PFS_FILL_ARGS)
1664 {
1665 
1666 	sbuf_printf(sb, "%d\n", msginfo.msgmnb);
1667 	return (0);
1668 }
1669 
1670 /*
1671  * Filler function for proc/sys/kernel/ngroups_max
1672  *
1673  * Note that in Linux it defaults to 65536, not 1023.
1674  */
1675 static int
1676 linprocfs_dongroups_max(PFS_FILL_ARGS)
1677 {
1678 
1679 	sbuf_printf(sb, "%d\n", ngroups_max);
1680 	return (0);
1681 }
1682 
1683 /*
1684  * Filler function for proc/sys/kernel/pid_max
1685  */
1686 static int
1687 linprocfs_dopid_max(PFS_FILL_ARGS)
1688 {
1689 
1690 	sbuf_printf(sb, "%i\n", PID_MAX);
1691 	return (0);
1692 }
1693 
1694 /*
1695  * Filler function for proc/sys/kernel/sem
1696  */
1697 static int
1698 linprocfs_dosem(PFS_FILL_ARGS)
1699 {
1700 
1701 	sbuf_printf(sb, "%d %d %d %d\n", seminfo.semmsl, seminfo.semmns,
1702 	    seminfo.semopm, seminfo.semmni);
1703 	return (0);
1704 }
1705 
1706 /*
1707  * Filler function for proc/sys/kernel/shmall
1708  */
1709 static int
1710 linprocfs_doshmall(PFS_FILL_ARGS)
1711 {
1712 
1713 	sbuf_printf(sb, "%lu\n", shminfo.shmall);
1714 	return (0);
1715 }
1716 
1717 /*
1718  * Filler function for proc/sys/kernel/shmmax
1719  */
1720 static int
1721 linprocfs_doshmmax(PFS_FILL_ARGS)
1722 {
1723 
1724 	sbuf_printf(sb, "%lu\n", shminfo.shmmax);
1725 	return (0);
1726 }
1727 
1728 /*
1729  * Filler function for proc/sys/kernel/shmmni
1730  */
1731 static int
1732 linprocfs_doshmmni(PFS_FILL_ARGS)
1733 {
1734 
1735 	sbuf_printf(sb, "%lu\n", shminfo.shmmni);
1736 	return (0);
1737 }
1738 
1739 /*
1740  * Filler function for proc/sys/kernel/tainted
1741  */
1742 static int
1743 linprocfs_dotainted(PFS_FILL_ARGS)
1744 {
1745 
1746 	sbuf_printf(sb, "0\n");
1747 	return (0);
1748 }
1749 
1750 /*
1751  * Filler function for proc/sys/vm/min_free_kbytes
1752  *
1753  * This mirrors the approach in illumos to return zero for reads. Effectively,
1754  * it says, no memory is kept in reserve for "atomic allocations". This class
1755  * of allocation can be used at times when a thread cannot be suspended.
1756  */
1757 static int
1758 linprocfs_dominfree(PFS_FILL_ARGS)
1759 {
1760 
1761 	sbuf_printf(sb, "%d\n", 0);
1762 	return (0);
1763 }
1764 
1765 /*
1766  * Filler function for proc/scsi/device_info
1767  */
1768 static int
1769 linprocfs_doscsidevinfo(PFS_FILL_ARGS)
1770 {
1771 
1772 	return (0);
1773 }
1774 
1775 /*
1776  * Filler function for proc/scsi/scsi
1777  */
1778 static int
1779 linprocfs_doscsiscsi(PFS_FILL_ARGS)
1780 {
1781 
1782 	return (0);
1783 }
1784 
1785 /*
1786  * Filler function for proc/devices
1787  */
1788 static int
1789 linprocfs_dodevices(PFS_FILL_ARGS)
1790 {
1791 	char *char_devices;
1792 	sbuf_printf(sb, "Character devices:\n");
1793 
1794 	char_devices = linux_get_char_devices();
1795 	sbuf_printf(sb, "%s", char_devices);
1796 	linux_free_get_char_devices(char_devices);
1797 
1798 	sbuf_printf(sb, "\nBlock devices:\n");
1799 
1800 	return (0);
1801 }
1802 
1803 /*
1804  * Filler function for proc/cmdline
1805  */
1806 static int
1807 linprocfs_docmdline(PFS_FILL_ARGS)
1808 {
1809 
1810 	sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname);
1811 	sbuf_printf(sb, " ro root=302\n");
1812 	return (0);
1813 }
1814 
1815 /*
1816  * Filler function for proc/filesystems
1817  */
1818 static int
1819 linprocfs_dofilesystems(PFS_FILL_ARGS)
1820 {
1821 	struct vfsconf *vfsp;
1822 
1823 	vfsconf_slock();
1824 	TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) {
1825 		if (vfsp->vfc_flags & VFCF_SYNTHETIC)
1826 			sbuf_printf(sb, "nodev");
1827 		sbuf_printf(sb, "\t%s\n", vfsp->vfc_name);
1828 	}
1829 	vfsconf_sunlock();
1830 	return(0);
1831 }
1832 
1833 /*
1834  * Filler function for proc/modules
1835  */
1836 static int
1837 linprocfs_domodules(PFS_FILL_ARGS)
1838 {
1839 #if 0
1840 	struct linker_file *lf;
1841 
1842 	TAILQ_FOREACH(lf, &linker_files, link) {
1843 		sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename,
1844 		    (unsigned long)lf->size, lf->refs);
1845 	}
1846 #endif
1847 	return (0);
1848 }
1849 
1850 /*
1851  * Filler function for proc/pid/fd
1852  */
1853 static int
1854 linprocfs_dofdescfs(PFS_FILL_ARGS)
1855 {
1856 
1857 	if (p == curproc)
1858 		sbuf_printf(sb, "/dev/fd");
1859 	else
1860 		sbuf_printf(sb, "unknown");
1861 	return (0);
1862 }
1863 
1864 /*
1865  * Filler function for proc/pid/limits
1866  */
1867 static const struct linux_rlimit_ident {
1868 	const char	*desc;
1869 	const char	*unit;
1870 	unsigned int	rlim_id;
1871 } linux_rlimits_ident[] = {
1872 	{ "Max cpu time",	"seconds",	RLIMIT_CPU },
1873 	{ "Max file size", 	"bytes",	RLIMIT_FSIZE },
1874 	{ "Max data size",	"bytes", 	RLIMIT_DATA },
1875 	{ "Max stack size",	"bytes", 	RLIMIT_STACK },
1876 	{ "Max core file size",  "bytes",	RLIMIT_CORE },
1877 	{ "Max resident set",	"bytes",	RLIMIT_RSS },
1878 	{ "Max processes",	"processes",	RLIMIT_NPROC },
1879 	{ "Max open files",	"files",	RLIMIT_NOFILE },
1880 	{ "Max locked memory",	"bytes",	RLIMIT_MEMLOCK },
1881 	{ "Max address space",	"bytes",	RLIMIT_AS },
1882 	{ "Max file locks",	"locks",	LINUX_RLIMIT_LOCKS },
1883 	{ "Max pending signals", "signals",	LINUX_RLIMIT_SIGPENDING },
1884 	{ "Max msgqueue size",	"bytes",	LINUX_RLIMIT_MSGQUEUE },
1885 	{ "Max nice priority", 		"",	LINUX_RLIMIT_NICE },
1886 	{ "Max realtime priority",	"",	LINUX_RLIMIT_RTPRIO },
1887 	{ "Max realtime timeout",	"us",	LINUX_RLIMIT_RTTIME },
1888 	{ 0, 0, 0 }
1889 };
1890 
1891 static int
1892 linprocfs_doproclimits(PFS_FILL_ARGS)
1893 {
1894 	const struct linux_rlimit_ident *li;
1895 	struct plimit *limp;
1896 	struct rlimit rl;
1897 	ssize_t size;
1898 	int res, error;
1899 
1900 	error = 0;
1901 
1902 	PROC_LOCK(p);
1903 	limp = lim_hold(p->p_limit);
1904 	PROC_UNLOCK(p);
1905 	size = sizeof(res);
1906 	sbuf_printf(sb, "%-26s%-21s%-21s%-21s\n", "Limit", "Soft Limit",
1907 			"Hard Limit", "Units");
1908 	for (li = linux_rlimits_ident; li->desc != NULL; ++li) {
1909 		switch (li->rlim_id)
1910 		{
1911 		case LINUX_RLIMIT_LOCKS:
1912 			/* FALLTHROUGH */
1913 		case LINUX_RLIMIT_RTTIME:
1914 			rl.rlim_cur = RLIM_INFINITY;
1915 			break;
1916 		case LINUX_RLIMIT_SIGPENDING:
1917 			error = kernel_sysctlbyname(td,
1918 			    "kern.sigqueue.max_pending_per_proc",
1919 			    &res, &size, 0, 0, 0, 0);
1920 			if (error != 0)
1921 				goto out;
1922 			rl.rlim_cur = res;
1923 			rl.rlim_max = res;
1924 			break;
1925 		case LINUX_RLIMIT_MSGQUEUE:
1926 			error = kernel_sysctlbyname(td,
1927 			    "kern.ipc.msgmnb", &res, &size, 0, 0, 0, 0);
1928 			if (error != 0)
1929 				goto out;
1930 			rl.rlim_cur = res;
1931 			rl.rlim_max = res;
1932 			break;
1933 		case LINUX_RLIMIT_NICE:
1934 			/* FALLTHROUGH */
1935 		case LINUX_RLIMIT_RTPRIO:
1936 			rl.rlim_cur = 0;
1937 			rl.rlim_max = 0;
1938 			break;
1939 		default:
1940 			rl = limp->pl_rlimit[li->rlim_id];
1941 			break;
1942 		}
1943 		if (rl.rlim_cur == RLIM_INFINITY)
1944 			sbuf_printf(sb, "%-26s%-21s%-21s%-10s\n",
1945 			    li->desc, "unlimited", "unlimited", li->unit);
1946 		else
1947 			sbuf_printf(sb, "%-26s%-21llu%-21llu%-10s\n",
1948 			    li->desc, (unsigned long long)rl.rlim_cur,
1949 			    (unsigned long long)rl.rlim_max, li->unit);
1950 	}
1951 out:
1952 	lim_free(limp);
1953 	return (error);
1954 }
1955 
1956 /*
1957  * The point of the following two functions is to work around
1958  * an assertion in Chromium; see kern/240991 for details.
1959  */
1960 static int
1961 linprocfs_dotaskattr(PFS_ATTR_ARGS)
1962 {
1963 
1964 	vap->va_nlink = 3;
1965 	return (0);
1966 }
1967 
1968 /*
1969  * Filler function for proc/<pid>/task/.dummy
1970  */
1971 static int
1972 linprocfs_dotaskdummy(PFS_FILL_ARGS)
1973 {
1974 
1975 	return (0);
1976 }
1977 
1978 /*
1979  * Filler function for proc/sys/kernel/random/uuid
1980  */
1981 static int
1982 linprocfs_douuid(PFS_FILL_ARGS)
1983 {
1984 	struct uuid uuid;
1985 
1986 	kern_uuidgen(&uuid, 1);
1987 	sbuf_printf_uuid(sb, &uuid);
1988 	sbuf_printf(sb, "\n");
1989 	return(0);
1990 }
1991 
1992 /*
1993  * Filler function for proc/sys/kernel/random/boot_id
1994  */
1995 static int
1996 linprocfs_doboot_id(PFS_FILL_ARGS)
1997 {
1998        static bool firstboot = 1;
1999        static struct uuid uuid;
2000 
2001        if (firstboot) {
2002                kern_uuidgen(&uuid, 1);
2003                firstboot = 0;
2004        }
2005        sbuf_printf_uuid(sb, &uuid);
2006        sbuf_printf(sb, "\n");
2007        return(0);
2008 }
2009 
2010 /*
2011  * Filler function for proc/pid/auxv
2012  */
2013 static int
2014 linprocfs_doauxv(PFS_FILL_ARGS)
2015 {
2016 	struct sbuf *asb;
2017 	off_t buflen, resid;
2018 	int error;
2019 
2020 	/*
2021 	 * Mimic linux behavior and pass only processes with usermode
2022 	 * address space as valid. Return zero silently otherwise.
2023 	 */
2024 	if (p->p_vmspace == &vmspace0)
2025 		return (0);
2026 
2027 	if (uio->uio_resid == 0)
2028 		return (0);
2029 	if (uio->uio_offset < 0 || uio->uio_resid < 0)
2030 		return (EINVAL);
2031 
2032 	asb = sbuf_new_auto();
2033 	if (asb == NULL)
2034 		return (ENOMEM);
2035 	error = proc_getauxv(td, p, asb);
2036 	if (error == 0)
2037 		error = sbuf_finish(asb);
2038 
2039 	resid = sbuf_len(asb) - uio->uio_offset;
2040 	if (resid > uio->uio_resid)
2041 		buflen = uio->uio_resid;
2042 	else
2043 		buflen = resid;
2044 	if (buflen > IOSIZE_MAX)
2045 		return (EINVAL);
2046 	if (buflen > maxphys)
2047 		buflen = maxphys;
2048 	if (resid <= 0)
2049 		return (0);
2050 
2051 	if (error == 0)
2052 		error = uiomove(sbuf_data(asb) + uio->uio_offset, buflen, uio);
2053 	sbuf_delete(asb);
2054 	return (error);
2055 }
2056 
2057 /*
2058  * Filler function for proc/self/oom_score_adj
2059  */
2060 static int
2061 linprocfs_do_oom_score_adj(PFS_FILL_ARGS)
2062 {
2063 	struct linux_pemuldata *pem;
2064 	long oom;
2065 
2066 	pem = pem_find(p);
2067 	if (pem == NULL || uio == NULL)
2068 		return (EOPNOTSUPP);
2069 	if (uio->uio_rw == UIO_READ) {
2070 		sbuf_printf(sb, "%d\n", pem->oom_score_adj);
2071 	} else {
2072 		sbuf_trim(sb);
2073 		sbuf_finish(sb);
2074 		oom = strtol(sbuf_data(sb), NULL, 10);
2075 		if (oom < LINUX_OOM_SCORE_ADJ_MIN ||
2076 		    oom > LINUX_OOM_SCORE_ADJ_MAX)
2077 			return (EINVAL);
2078 		pem->oom_score_adj = oom;
2079 	}
2080 	return (0);
2081 }
2082 
2083 /*
2084  * Filler function for proc/sys/vm/max_map_count
2085  *
2086  * Maximum number of active map areas, on Linux this limits the number
2087  * of vmaps per mm struct. We don't limit mappings, return a suitable
2088  * large value.
2089  */
2090 static int
2091 linprocfs_domax_map_cnt(PFS_FILL_ARGS)
2092 {
2093 
2094 	sbuf_printf(sb, "%d\n", INT32_MAX);
2095 	return (0);
2096 }
2097 
2098 /*
2099  * Filler function for proc/sysvipc/msg
2100  */
2101 static int
2102 linprocfs_dosysvipc_msg(PFS_FILL_ARGS)
2103 {
2104 	struct msqid_kernel *msqids;
2105 	u_long id, msgmni;
2106 	size_t sz;
2107 	int error;
2108 
2109 	sbuf_printf(sb,
2110 	    "%10s %10s %4s  %10s %10s %5s %5s %5s %5s %5s %5s %10s %10s %10s\n",
2111 	    "key", "msqid", "perms", "cbytes", "qnum", "lspid", "lrpid",
2112 	    "uid", "gid", "cuid", "cgid", "stime", "rtime", "ctime");
2113 
2114 again:
2115 	msgmni = msginfo.msgmni;
2116 	sz = sizeof(struct msqid_kernel) * msgmni;
2117 	msqids = malloc(sz, M_TEMP, M_NOWAIT);
2118 	if (msqids == NULL)
2119 		return (ENOMEM);
2120 	if (msgmni != msginfo.msgmni) {
2121 		free(msqids, M_TEMP);
2122 		goto again;
2123 	}
2124 
2125 	error = kernel_sysctlbyname(curthread, "kern.ipc.msqids", msqids, &sz,
2126 	    NULL, 0, 0, 0);
2127 	if (error != 0) {
2128 		free(msqids, M_TEMP);
2129 		return (error);
2130 	}
2131 	msgmni = sz / sizeof(struct msqid_kernel);
2132 
2133 	for (id = 0; id < msgmni; id++)
2134 		if (msqids[id].u.msg_qbytes != 0)
2135 			sbuf_printf(sb,
2136 			    "%10d %10lu  %4o  %10lu %10lu %5u %5u %5u %5u %5u %5u %10ld %10ld %10ld\n",
2137 			    (int) msqids[id].u.msg_perm.key,
2138 			    IXSEQ_TO_IPCID(id, msqids[id].u.msg_perm),
2139 			    msqids[id].u.msg_perm.mode,
2140 			    msqids[id].u.msg_cbytes,
2141 			    msqids[id].u.msg_qnum,
2142 			    msqids[id].u.msg_lspid,
2143 			    msqids[id].u.msg_lrpid,
2144 			    msqids[id].u.msg_perm.uid,
2145 			    msqids[id].u.msg_perm.gid,
2146 			    msqids[id].u.msg_perm.cuid,
2147 			    msqids[id].u.msg_perm.cgid,
2148 			    (long)msqids[id].u.msg_stime,
2149 			    (long)msqids[id].u.msg_rtime,
2150 			    (long)msqids[id].u.msg_ctime);
2151 
2152 	free(msqids, M_TEMP);
2153 	return (0);
2154 }
2155 
2156 /*
2157  * Filler function for proc/sysvipc/sem
2158  */
2159 static int
2160 linprocfs_dosysvipc_sem(PFS_FILL_ARGS)
2161 {
2162 	struct semid_kernel *semids;
2163 	u_long id, semmni;
2164 	size_t sz;
2165 	int error;
2166 
2167 	sbuf_printf(sb, "%10s %10s %4s %10s %5s %5s %5s %5s %10s %10s\n",
2168 	    "key", "semid", "perms", "nsems", "uid", "gid", "cuid", "cgid",
2169 	    "otime", "ctime");
2170 
2171 again:
2172 	semmni = seminfo.semmni;
2173 	sz = sizeof(struct semid_kernel) * semmni;
2174 	semids = malloc(sz, M_TEMP, M_NOWAIT);
2175 	if (semids == NULL)
2176 		return (ENOMEM);
2177 	if (semmni != seminfo.semmni) {
2178 		free(semids, M_TEMP);
2179 		goto again;
2180 	}
2181 
2182 	error = kernel_sysctlbyname(curthread, "kern.ipc.sema", semids, &sz,
2183 	    NULL, 0, 0, 0);
2184 	if (error != 0) {
2185 		free(semids, M_TEMP);
2186 		return (error);
2187 	}
2188 	semmni = sz / sizeof(struct semid_kernel);
2189 
2190 	for (id = 0; id < semmni; id++)
2191 		if ((semids[id].u.sem_perm.mode & SEM_ALLOC) != 0)
2192 			sbuf_printf(sb,
2193 			    "%10d %10lu  %4o %10u %5u %5u %5u %5u %10ld %10ld\n",
2194 			    (int) semids[id].u.sem_perm.key,
2195 			    IXSEQ_TO_IPCID(id, semids[id].u.sem_perm),
2196 			    semids[id].u.sem_perm.mode,
2197 			    semids[id].u.sem_nsems,
2198 			    semids[id].u.sem_perm.uid,
2199 			    semids[id].u.sem_perm.gid,
2200 			    semids[id].u.sem_perm.cuid,
2201 			    semids[id].u.sem_perm.cgid,
2202 			    (long)semids[id].u.sem_otime,
2203 			    (long)semids[id].u.sem_ctime);
2204 
2205 	free(semids, M_TEMP);
2206 	return (0);
2207 }
2208 
2209 /*
2210  * Filler function for proc/sysvipc/shm
2211  */
2212 static int
2213 linprocfs_dosysvipc_shm(PFS_FILL_ARGS)
2214 {
2215 	struct shmid_kernel *shmids;
2216 	u_long id, shmmni;
2217 	size_t sz;
2218 	int error;
2219 
2220 	sbuf_printf(sb,
2221 	    "%10s %10s %s %21s %5s %5s %5s %5s %5s %5s %5s %10s %10s %10s %21s %21s\n",
2222 	    "key", "shmid", "perms", "size", "cpid", "lpid", "nattch", "uid",
2223 	    "gid", "cuid", "cgid", "atime", "dtime", "ctime", "rss", "swap");
2224 
2225 again:
2226 	shmmni = shminfo.shmmni;
2227 	sz = sizeof(struct shmid_kernel) * shmmni;
2228 	shmids = malloc(sz, M_TEMP, M_NOWAIT);
2229 	if (shmids == NULL)
2230 		return (ENOMEM);
2231 	if (shmmni != shminfo.shmmni) {
2232 		free(shmids, M_TEMP);
2233 		goto again;
2234 	}
2235 
2236 	error = kernel_sysctlbyname(curthread, "kern.ipc.shmsegs", shmids, &sz,
2237 	    NULL, 0, 0, 0);
2238 	if (error != 0) {
2239 		free(shmids, M_TEMP);
2240 		return (error);
2241 	}
2242 	shmmni = sz / sizeof(struct shmid_kernel);
2243 
2244 	for (id = 0; id < shmmni; id++)
2245 		if ((shmids[id].u.shm_perm.mode & SHMSEG_ALLOCATED) != 0)
2246 			sbuf_printf(sb,
2247 			    "%10d %10lu  %4o %21lu %5u %5u  %5u %5u %5u %5u %5u %10ld %10ld %10ld %21d %21d\n",
2248 			    (int) shmids[id].u.shm_perm.key,
2249 			    IXSEQ_TO_IPCID(id, shmids[id].u.shm_perm),
2250 			    shmids[id].u.shm_perm.mode,
2251 			    shmids[id].u.shm_segsz,
2252 			    shmids[id].u.shm_cpid,
2253 			    shmids[id].u.shm_lpid,
2254 			    shmids[id].u.shm_nattch,
2255 			    shmids[id].u.shm_perm.uid,
2256 			    shmids[id].u.shm_perm.gid,
2257 			    shmids[id].u.shm_perm.cuid,
2258 			    shmids[id].u.shm_perm.cgid,
2259 			    (long)shmids[id].u.shm_atime,
2260 			    (long)shmids[id].u.shm_dtime,
2261 			    (long)shmids[id].u.shm_ctime,
2262 			    0, 0);	/* XXX rss & swp are not supported */
2263 
2264 	free(shmids, M_TEMP);
2265 	return (0);
2266 }
2267 
2268 /*
2269  * Constructor
2270  */
2271 static int
2272 linprocfs_init(PFS_INIT_ARGS)
2273 {
2274 	struct pfs_node *root;
2275 	struct pfs_node *dir;
2276 	struct pfs_node *sys;
2277 
2278 	root = pi->pi_root;
2279 
2280 	/* /proc/... */
2281 	pfs_create_file(root, "cmdline", &linprocfs_docmdline,
2282 	    NULL, NULL, NULL, PFS_RD);
2283 	pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo,
2284 	    NULL, NULL, NULL, PFS_RD);
2285 	pfs_create_file(root, "devices", &linprocfs_dodevices,
2286 	    NULL, NULL, NULL, PFS_RD);
2287 	pfs_create_file(root, "filesystems", &linprocfs_dofilesystems,
2288 	    NULL, NULL, NULL, PFS_RD);
2289 	pfs_create_file(root, "loadavg", &linprocfs_doloadavg,
2290 	    NULL, NULL, NULL, PFS_RD);
2291 	pfs_create_file(root, "meminfo", &linprocfs_domeminfo,
2292 	    NULL, NULL, NULL, PFS_RD);
2293 	pfs_create_file(root, "modules", &linprocfs_domodules,
2294 	    NULL, NULL, NULL, PFS_RD);
2295 	pfs_create_file(root, "mounts", &linprocfs_domtab,
2296 	    NULL, NULL, NULL, PFS_RD);
2297 	pfs_create_file(root, "mtab", &linprocfs_domtab,
2298 	    NULL, NULL, NULL, PFS_RD);
2299 	pfs_create_file(root, "partitions", &linprocfs_dopartitions,
2300 	    NULL, NULL, NULL, PFS_RD);
2301 	pfs_create_link(root, "self", &procfs_docurproc,
2302 	    NULL, NULL, NULL, 0);
2303 	pfs_create_file(root, "stat", &linprocfs_dostat,
2304 	    NULL, NULL, NULL, PFS_RD);
2305 	pfs_create_file(root, "swaps", &linprocfs_doswaps,
2306 	    NULL, NULL, NULL, PFS_RD);
2307 	pfs_create_file(root, "uptime", &linprocfs_douptime,
2308 	    NULL, NULL, NULL, PFS_RD);
2309 	pfs_create_file(root, "version", &linprocfs_doversion,
2310 	    NULL, NULL, NULL, PFS_RD);
2311 
2312 	/* /proc/bus/... */
2313 	dir = pfs_create_dir(root, "bus", NULL, NULL, NULL, 0);
2314 	dir = pfs_create_dir(dir, "pci", NULL, NULL, NULL, 0);
2315 	dir = pfs_create_dir(dir, "devices", NULL, NULL, NULL, 0);
2316 
2317 	/* /proc/net/... */
2318 	dir = pfs_create_dir(root, "net", NULL, NULL, NULL, 0);
2319 	pfs_create_file(dir, "dev", &linprocfs_donetdev,
2320 	    NULL, NULL, NULL, PFS_RD);
2321 	pfs_create_file(dir, "route", &linprocfs_donetroute,
2322 	    NULL, NULL, NULL, PFS_RD);
2323 
2324 	/* /proc/<pid>/... */
2325 	dir = pfs_create_dir(root, "pid", NULL, NULL, NULL, PFS_PROCDEP);
2326 	pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline,
2327 	    NULL, NULL, NULL, PFS_RD);
2328 	pfs_create_link(dir, "cwd", &linprocfs_doproccwd,
2329 	    NULL, NULL, NULL, 0);
2330 	pfs_create_file(dir, "environ", &linprocfs_doprocenviron,
2331 	    NULL, &procfs_candebug, NULL, PFS_RD);
2332 	pfs_create_link(dir, "exe", &procfs_doprocfile,
2333 	    NULL, &procfs_notsystem, NULL, 0);
2334 	pfs_create_file(dir, "maps", &linprocfs_doprocmaps,
2335 	    NULL, NULL, NULL, PFS_RD | PFS_AUTODRAIN);
2336 	pfs_create_file(dir, "mem", &linprocfs_doprocmem,
2337 	    procfs_attr_rw, &procfs_candebug, NULL, PFS_RDWR | PFS_RAW);
2338 	pfs_create_file(dir, "mountinfo", &linprocfs_doprocmountinfo,
2339 	    NULL, NULL, NULL, PFS_RD);
2340 	pfs_create_file(dir, "mounts", &linprocfs_domtab,
2341 	    NULL, NULL, NULL, PFS_RD);
2342 	pfs_create_link(dir, "root", &linprocfs_doprocroot,
2343 	    NULL, NULL, NULL, 0);
2344 	pfs_create_file(dir, "stat", &linprocfs_doprocstat,
2345 	    NULL, NULL, NULL, PFS_RD);
2346 	pfs_create_file(dir, "statm", &linprocfs_doprocstatm,
2347 	    NULL, NULL, NULL, PFS_RD);
2348 	pfs_create_file(dir, "status", &linprocfs_doprocstatus,
2349 	    NULL, NULL, NULL, PFS_RD);
2350 	pfs_create_link(dir, "fd", &linprocfs_dofdescfs,
2351 	    NULL, NULL, NULL, 0);
2352 	pfs_create_file(dir, "auxv", &linprocfs_doauxv,
2353 	    NULL, &procfs_candebug, NULL, PFS_RD|PFS_RAWRD);
2354 	pfs_create_file(dir, "limits", &linprocfs_doproclimits,
2355 	    NULL, NULL, NULL, PFS_RD);
2356 	pfs_create_file(dir, "oom_score_adj", &linprocfs_do_oom_score_adj,
2357 	    procfs_attr_rw, &procfs_candebug, NULL, PFS_RDWR);
2358 
2359 	/* /proc/<pid>/task/... */
2360 	dir = pfs_create_dir(dir, "task", linprocfs_dotaskattr, NULL, NULL, 0);
2361 	pfs_create_file(dir, ".dummy", &linprocfs_dotaskdummy,
2362 	    NULL, NULL, NULL, PFS_RD);
2363 
2364 	/* /proc/scsi/... */
2365 	dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0);
2366 	pfs_create_file(dir, "device_info", &linprocfs_doscsidevinfo,
2367 	    NULL, NULL, NULL, PFS_RD);
2368 	pfs_create_file(dir, "scsi", &linprocfs_doscsiscsi,
2369 	    NULL, NULL, NULL, PFS_RD);
2370 
2371 	/* /proc/sys/... */
2372 	sys = pfs_create_dir(root, "sys", NULL, NULL, NULL, 0);
2373 
2374 	/* /proc/sys/kernel/... */
2375 	dir = pfs_create_dir(sys, "kernel", NULL, NULL, NULL, 0);
2376 	pfs_create_file(dir, "osrelease", &linprocfs_doosrelease,
2377 	    NULL, NULL, NULL, PFS_RD);
2378 	pfs_create_file(dir, "ostype", &linprocfs_doostype,
2379 	    NULL, NULL, NULL, PFS_RD);
2380 	pfs_create_file(dir, "version", &linprocfs_doosbuild,
2381 	    NULL, NULL, NULL, PFS_RD);
2382 	pfs_create_file(dir, "msgmax", &linprocfs_domsgmax,
2383 	    NULL, NULL, NULL, PFS_RD);
2384 	pfs_create_file(dir, "msgmni", &linprocfs_domsgmni,
2385 	    NULL, NULL, NULL, PFS_RD);
2386 	pfs_create_file(dir, "msgmnb", &linprocfs_domsgmnb,
2387 	    NULL, NULL, NULL, PFS_RD);
2388 	pfs_create_file(dir, "ngroups_max", &linprocfs_dongroups_max,
2389 	    NULL, NULL, NULL, PFS_RD);
2390 	pfs_create_file(dir, "pid_max", &linprocfs_dopid_max,
2391 	    NULL, NULL, NULL, PFS_RD);
2392 	pfs_create_file(dir, "sem", &linprocfs_dosem,
2393 	    NULL, NULL, NULL, PFS_RD);
2394 	pfs_create_file(dir, "shmall", &linprocfs_doshmall,
2395 	    NULL, NULL, NULL, PFS_RD);
2396 	pfs_create_file(dir, "shmmax", &linprocfs_doshmmax,
2397 	    NULL, NULL, NULL, PFS_RD);
2398 	pfs_create_file(dir, "shmmni", &linprocfs_doshmmni,
2399 	    NULL, NULL, NULL, PFS_RD);
2400 	pfs_create_file(dir, "tainted", &linprocfs_dotainted,
2401 	    NULL, NULL, NULL, PFS_RD);
2402 
2403 	/* /proc/sys/kernel/random/... */
2404 	dir = pfs_create_dir(dir, "random", NULL, NULL, NULL, 0);
2405 	pfs_create_file(dir, "uuid", &linprocfs_douuid,
2406 	    NULL, NULL, NULL, PFS_RD);
2407 	pfs_create_file(dir, "boot_id", &linprocfs_doboot_id,
2408 	    NULL, NULL, NULL, PFS_RD);
2409 
2410 	/* /proc/sys/vm/.... */
2411 	dir = pfs_create_dir(sys, "vm", NULL, NULL, NULL, 0);
2412 	pfs_create_file(dir, "min_free_kbytes", &linprocfs_dominfree,
2413 	    NULL, NULL, NULL, PFS_RD);
2414 	pfs_create_file(dir, "max_map_count", &linprocfs_domax_map_cnt,
2415 	    NULL, NULL, NULL, PFS_RD);
2416 
2417 	/* /proc/sysvipc/... */
2418 	dir = pfs_create_dir(root, "sysvipc", NULL, NULL, NULL, 0);
2419 	pfs_create_file(dir, "msg", &linprocfs_dosysvipc_msg,
2420 	    NULL, NULL, NULL, PFS_RD);
2421 	pfs_create_file(dir, "sem", &linprocfs_dosysvipc_sem,
2422 	    NULL, NULL, NULL, PFS_RD);
2423 	pfs_create_file(dir, "shm", &linprocfs_dosysvipc_shm,
2424 	    NULL, NULL, NULL, PFS_RD);
2425 
2426 	return (0);
2427 }
2428 
2429 /*
2430  * Destructor
2431  */
2432 static int
2433 linprocfs_uninit(PFS_INIT_ARGS)
2434 {
2435 
2436 	/* nothing to do, pseudofs will GC */
2437 	return (0);
2438 }
2439 
2440 PSEUDOFS(linprocfs, 1, VFCF_JAIL);
2441 #if defined(__aarch64__) || defined(__amd64__)
2442 MODULE_DEPEND(linprocfs, linux_common, 1, 1, 1);
2443 #else
2444 MODULE_DEPEND(linprocfs, linux, 1, 1, 1);
2445 #endif
2446 MODULE_DEPEND(linprocfs, procfs, 1, 1, 1);
2447 MODULE_DEPEND(linprocfs, sysvmsg, 1, 1, 1);
2448 MODULE_DEPEND(linprocfs, sysvsem, 1, 1, 1);
2449 MODULE_DEPEND(linprocfs, sysvshm, 1, 1, 1);
2450