xref: /freebsd/sys/compat/linprocfs/linprocfs.c (revision 4a84c26cfc241ffa113d2e815d61d4b406b937e9)
1 /*-
2  * SPDX-License-Identifier: BSD-4-Clause
3  *
4  * Copyright (c) 2000 Dag-Erling Coïdan 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  *	@(#)procfs_status.c	8.4 (Berkeley) 6/15/94
42  */
43 
44 #include <sys/cdefs.h>
45 __FBSDID("$FreeBSD$");
46 
47 #include <sys/param.h>
48 #include <sys/queue.h>
49 #include <sys/blist.h>
50 #include <sys/conf.h>
51 #include <sys/exec.h>
52 #include <sys/fcntl.h>
53 #include <sys/filedesc.h>
54 #include <sys/jail.h>
55 #include <sys/kernel.h>
56 #include <sys/limits.h>
57 #include <sys/linker.h>
58 #include <sys/lock.h>
59 #include <sys/malloc.h>
60 #include <sys/msg.h>
61 #include <sys/mutex.h>
62 #include <sys/namei.h>
63 #include <sys/proc.h>
64 #include <sys/ptrace.h>
65 #include <sys/resourcevar.h>
66 #include <sys/resource.h>
67 #include <sys/sbuf.h>
68 #include <sys/sem.h>
69 #include <sys/smp.h>
70 #include <sys/socket.h>
71 #include <sys/syscallsubr.h>
72 #include <sys/sysctl.h>
73 #include <sys/sysent.h>
74 #include <sys/systm.h>
75 #include <sys/time.h>
76 #include <sys/tty.h>
77 #include <sys/user.h>
78 #include <sys/uuid.h>
79 #include <sys/vmmeter.h>
80 #include <sys/vnode.h>
81 #include <sys/bus.h>
82 
83 #include <net/if.h>
84 #include <net/if_var.h>
85 #include <net/if_types.h>
86 
87 #include <vm/vm.h>
88 #include <vm/vm_extern.h>
89 #include <vm/pmap.h>
90 #include <vm/vm_map.h>
91 #include <vm/vm_param.h>
92 #include <vm/vm_object.h>
93 #include <vm/swap_pager.h>
94 
95 #include <machine/clock.h>
96 
97 #include <geom/geom.h>
98 #include <geom/geom_int.h>
99 
100 #if defined(__i386__) || defined(__amd64__)
101 #include <machine/cputypes.h>
102 #include <machine/md_var.h>
103 #endif /* __i386__ || __amd64__ */
104 
105 #include <compat/linux/linux.h>
106 #include <compat/linux/linux_mib.h>
107 #include <compat/linux/linux_misc.h>
108 #include <compat/linux/linux_util.h>
109 #include <fs/pseudofs/pseudofs.h>
110 #include <fs/procfs/procfs.h>
111 
112 /*
113  * Various conversion macros
114  */
115 #define T2J(x) ((long)(((x) * 100ULL) / (stathz ? stathz : hz)))	/* ticks to jiffies */
116 #define T2CS(x) ((unsigned long)(((x) * 100ULL) / (stathz ? stathz : hz)))	/* ticks to centiseconds */
117 #define T2S(x) ((x) / (stathz ? stathz : hz))		/* ticks to seconds */
118 #define B2K(x) ((x) >> 10)				/* bytes to kbytes */
119 #define B2P(x) ((x) >> PAGE_SHIFT)			/* bytes to pages */
120 #define P2B(x) ((x) << PAGE_SHIFT)			/* pages to bytes */
121 #define P2K(x) ((x) << (PAGE_SHIFT - 10))		/* pages to kbytes */
122 #define TV2J(x)	((x)->tv_sec * 100UL + (x)->tv_usec / 10000)
123 
124 /**
125  * @brief Mapping of ki_stat in struct kinfo_proc to the linux state
126  *
127  * The linux procfs state field displays one of the characters RSDZTW to
128  * denote running, sleeping in an interruptible wait, waiting in an
129  * uninterruptible disk sleep, a zombie process, process is being traced
130  * or stopped, or process is paging respectively.
131  *
132  * Our struct kinfo_proc contains the variable ki_stat which contains a
133  * value out of SIDL, SRUN, SSLEEP, SSTOP, SZOMB, SWAIT and SLOCK.
134  *
135  * This character array is used with ki_stati-1 as an index and tries to
136  * map our states to suitable linux states.
137  */
138 static char linux_state[] = "RRSTZDD";
139 
140 /*
141  * Filler function for proc/meminfo
142  */
143 static int
144 linprocfs_domeminfo(PFS_FILL_ARGS)
145 {
146 	unsigned long memtotal;		/* total memory in bytes */
147 	unsigned long memused;		/* used memory in bytes */
148 	unsigned long memfree;		/* free memory in bytes */
149 	unsigned long buffers, cached;	/* buffer / cache memory ??? */
150 	unsigned long long swaptotal;	/* total swap space in bytes */
151 	unsigned long long swapused;	/* used swap space in bytes */
152 	unsigned long long swapfree;	/* free swap space in bytes */
153 	int i, j;
154 
155 	memtotal = physmem * PAGE_SIZE;
156 	/*
157 	 * The correct thing here would be:
158 	 *
159 	memfree = vm_free_count() * PAGE_SIZE;
160 	memused = memtotal - memfree;
161 	 *
162 	 * but it might mislead linux binaries into thinking there
163 	 * is very little memory left, so we cheat and tell them that
164 	 * all memory that isn't wired down is free.
165 	 */
166 	memused = vm_wire_count() * PAGE_SIZE;
167 	memfree = memtotal - memused;
168 	swap_pager_status(&i, &j);
169 	swaptotal = (unsigned long long)i * PAGE_SIZE;
170 	swapused = (unsigned long long)j * PAGE_SIZE;
171 	swapfree = swaptotal - swapused;
172 	/*
173 	 * We'd love to be able to write:
174 	 *
175 	buffers = bufspace;
176 	 *
177 	 * but bufspace is internal to vfs_bio.c and we don't feel
178 	 * like unstaticizing it just for linprocfs's sake.
179 	 */
180 	buffers = 0;
181 	cached = vm_inactive_count() * PAGE_SIZE;
182 
183 	sbuf_printf(sb,
184 	    "MemTotal: %9lu kB\n"
185 	    "MemFree:  %9lu kB\n"
186 	    "Buffers:  %9lu kB\n"
187 	    "Cached:   %9lu kB\n"
188 	    "SwapTotal:%9llu kB\n"
189 	    "SwapFree: %9llu kB\n",
190 	    B2K(memtotal), B2K(memfree), B2K(buffers),
191 	    B2K(cached), B2K(swaptotal), B2K(swapfree));
192 
193 	return (0);
194 }
195 
196 #if defined(__i386__) || defined(__amd64__)
197 /*
198  * Filler function for proc/cpuinfo (i386 & amd64 version)
199  */
200 static int
201 linprocfs_docpuinfo(PFS_FILL_ARGS)
202 {
203 	int hw_model[2];
204 	char model[128];
205 	uint64_t freq;
206 	size_t size;
207 	u_int cache_size[4];
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 *flags[] = {
216 		"fpu",	    "vme",     "de",	   "pse",      "tsc",
217 		"msr",	    "pae",     "mce",	   "cx8",      "apic",
218 		"sep",	    "sep",     "mtrr",	   "pge",      "mca",
219 		"cmov",	    "pat",     "pse36",	   "pn",       "b19",
220 		"b20",	    "b21",     "mmxext",   "mmx",      "fxsr",
221 		"xmm",	    "sse2",    "b27",	   "b28",      "b29",
222 		"3dnowext", "3dnow"
223 	};
224 
225 	static char *power_flags[] = {
226 		"ts",           "fid",          "vid",
227 		"ttp",          "tm",           "stc",
228 		"100mhzsteps",  "hwpstate",     "",
229 		"cpb",          "eff_freq_ro",  "proc_feedback",
230 		"acc_power",
231 	};
232 
233 	hw_model[0] = CTL_HW;
234 	hw_model[1] = HW_MODEL;
235 	model[0] = '\0';
236 	size = sizeof(model);
237 	if (kernel_sysctl(td, hw_model, 2, &model, &size, 0, 0, 0, 0) != 0)
238 		strcpy(model, "unknown");
239 #ifdef __i386__
240 	switch (cpu_vendor_id) {
241 	case CPU_VENDOR_AMD:
242 		if (cpu_class < CPUCLASS_686)
243 			flags[16] = "fcmov";
244 		break;
245 	case CPU_VENDOR_CYRIX:
246 		flags[24] = "cxmmx";
247 		break;
248 	}
249 #endif
250 	if (cpu_exthigh >= 0x80000006)
251 		do_cpuid(0x80000006, cache_size);
252 	else
253 		memset(cache_size, 0, sizeof(cache_size));
254 	for (i = 0; i < mp_ncpus; ++i) {
255 		fqmhz = 0;
256 		fqkhz = 0;
257 		freq = atomic_load_acq_64(&tsc_freq);
258 		if (freq != 0) {
259 			fqmhz = (freq + 4999) / 1000000;
260 			fqkhz = ((freq + 4999) / 10000) % 100;
261 		}
262 		sbuf_printf(sb,
263 		    "processor\t: %d\n"
264 		    "vendor_id\t: %.20s\n"
265 		    "cpu family\t: %u\n"
266 		    "model\t\t: %u\n"
267 		    "model name\t: %s\n"
268 		    "stepping\t: %u\n"
269 		    "cpu MHz\t\t: %d.%02d\n"
270 		    "cache size\t: %d KB\n"
271 		    "physical id\t: %d\n"
272 		    "siblings\t: %d\n"
273 		    "core id\t\t: %d\n"
274 		    "cpu cores\t: %d\n"
275 		    "apicid\t\t: %d\n"
276 		    "initial apicid\t: %d\n"
277 		    "fpu\t\t: %s\n"
278 		    "fpu_exception\t: %s\n"
279 		    "cpuid level\t: %d\n"
280 		    "wp\t\t: %s\n",
281 		    i, cpu_vendor, CPUID_TO_FAMILY(cpu_id),
282 		    CPUID_TO_MODEL(cpu_id), model, cpu_id & CPUID_STEPPING,
283 		    fqmhz, fqkhz,
284 		    (cache_size[2] >> 16), 0, mp_ncpus, i, mp_ncpus,
285 		    i, i, /*cpu_id & CPUID_LOCAL_APIC_ID ??*/
286 		    (cpu_feature & CPUID_FPU) ? "yes" : "no", "yes",
287 		    CPUID_TO_FAMILY(cpu_id), "yes");
288 		sbuf_cat(sb, "flags\t\t:");
289 		for (j = 0; j < nitems(flags); j++)
290 			if (cpu_feature & (1 << j))
291 				sbuf_printf(sb, " %s", flags[j]);
292 		sbuf_cat(sb, "\n");
293 		sbuf_printf(sb,
294 		    "bugs\t\t: %s\n"
295 		    "bogomips\t: %d.%02d\n"
296 		    "clflush size\t: %d\n"
297 		    "cache_alignment\t: %d\n"
298 		    "address sizes\t: %d bits physical, %d bits virtual\n",
299 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
300 		    (has_f00f_bug) ? "Intel F00F" : "",
301 #else
302 		    "",
303 #endif
304 		    fqmhz, fqkhz,
305 		    cpu_clflush_line_size, cpu_clflush_line_size,
306 		    cpu_maxphyaddr,
307 		    (cpu_maxphyaddr > 32) ? 48 : 0);
308 		sbuf_cat(sb, "power management: ");
309 		for (j = 0; j < nitems(power_flags); j++)
310 			if (amd_pminfo & (1 << j))
311 				sbuf_printf(sb, " %s", power_flags[j]);
312 		sbuf_cat(sb, "\n\n");
313 
314 		/* XXX per-cpu vendor / class / model / id? */
315 	}
316 	sbuf_cat(sb, "\n");
317 
318 	return (0);
319 }
320 #endif /* __i386__ || __amd64__ */
321 
322 /*
323  * Filler function for proc/mtab
324  *
325  * This file doesn't exist in Linux' procfs, but is included here so
326  * users can symlink /compat/linux/etc/mtab to /proc/mtab
327  */
328 static int
329 linprocfs_domtab(PFS_FILL_ARGS)
330 {
331 	struct nameidata nd;
332 	const char *lep;
333 	char *dlep, *flep, *mntto, *mntfrom, *fstype;
334 	size_t lep_len;
335 	int error;
336 	struct statfs *buf, *sp;
337 	size_t count;
338 
339 	/* resolve symlinks etc. in the emulation tree prefix */
340 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, td);
341 	flep = NULL;
342 	error = namei(&nd);
343 	lep = linux_emul_path;
344 	if (error == 0) {
345 		if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0)
346 			lep = dlep;
347 		vrele(nd.ni_vp);
348 	}
349 	lep_len = strlen(lep);
350 
351 	buf = NULL;
352 	error = kern_getfsstat(td, &buf, SIZE_T_MAX, &count,
353 	    UIO_SYSSPACE, MNT_WAIT);
354 	if (error != 0) {
355 		free(buf, M_TEMP);
356 		free(flep, M_TEMP);
357 		return (error);
358 	}
359 
360 	for (sp = buf; count > 0; sp++, count--) {
361 		/* determine device name */
362 		mntfrom = sp->f_mntfromname;
363 
364 		/* determine mount point */
365 		mntto = sp->f_mntonname;
366 		if (strncmp(mntto, lep, lep_len) == 0 && mntto[lep_len] == '/')
367 			mntto += lep_len;
368 
369 		/* determine fs type */
370 		fstype = sp->f_fstypename;
371 		if (strcmp(fstype, pn->pn_info->pi_name) == 0)
372 			mntfrom = fstype = "proc";
373 		else if (strcmp(fstype, "procfs") == 0)
374 			continue;
375 
376 		if (strcmp(fstype, "linsysfs") == 0) {
377 			sbuf_printf(sb, "/sys %s sysfs %s", mntto,
378 			    sp->f_flags & MNT_RDONLY ? "ro" : "rw");
379 		} else {
380 			/* For Linux msdosfs is called vfat */
381 			if (strcmp(fstype, "msdosfs") == 0)
382 				fstype = "vfat";
383 			sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype,
384 			    sp->f_flags & MNT_RDONLY ? "ro" : "rw");
385 		}
386 #define ADD_OPTION(opt, name) \
387 	if (sp->f_flags & (opt)) sbuf_printf(sb, "," name);
388 		ADD_OPTION(MNT_SYNCHRONOUS,	"sync");
389 		ADD_OPTION(MNT_NOEXEC,		"noexec");
390 		ADD_OPTION(MNT_NOSUID,		"nosuid");
391 		ADD_OPTION(MNT_UNION,		"union");
392 		ADD_OPTION(MNT_ASYNC,		"async");
393 		ADD_OPTION(MNT_SUIDDIR,		"suiddir");
394 		ADD_OPTION(MNT_NOSYMFOLLOW,	"nosymfollow");
395 		ADD_OPTION(MNT_NOATIME,		"noatime");
396 #undef ADD_OPTION
397 		/* a real Linux mtab will also show NFS options */
398 		sbuf_printf(sb, " 0 0\n");
399 	}
400 
401 	free(buf, M_TEMP);
402 	free(flep, M_TEMP);
403 	return (error);
404 }
405 
406 /*
407  * Filler function for proc/partitions
408  */
409 static int
410 linprocfs_dopartitions(PFS_FILL_ARGS)
411 {
412 	struct g_class *cp;
413 	struct g_geom *gp;
414 	struct g_provider *pp;
415 	int major, minor;
416 
417 	g_topology_lock();
418 	sbuf_printf(sb, "major minor  #blocks  name rio rmerge rsect "
419 	    "ruse wio wmerge wsect wuse running use aveq\n");
420 
421 	LIST_FOREACH(cp, &g_classes, class) {
422 		if (strcmp(cp->name, "DISK") == 0 ||
423 		    strcmp(cp->name, "PART") == 0)
424 			LIST_FOREACH(gp, &cp->geom, geom) {
425 				LIST_FOREACH(pp, &gp->provider, provider) {
426 					if (linux_driver_get_major_minor(
427 					    pp->name, &major, &minor) != 0) {
428 						major = 0;
429 						minor = 0;
430 					}
431 					sbuf_printf(sb, "%d %d %lld %s "
432 					    "%d %d %d %d %d "
433 					     "%d %d %d %d %d %d\n",
434 					     major, minor,
435 					     (long long)pp->mediasize, pp->name,
436 					     0, 0, 0, 0, 0,
437 					     0, 0, 0, 0, 0, 0);
438 				}
439 			}
440 	}
441 	g_topology_unlock();
442 
443 	return (0);
444 }
445 
446 
447 /*
448  * Filler function for proc/stat
449  */
450 static int
451 linprocfs_dostat(PFS_FILL_ARGS)
452 {
453 	struct pcpu *pcpu;
454 	long cp_time[CPUSTATES];
455 	long *cp;
456 	struct timeval boottime;
457 	int i;
458 
459 	read_cpu_time(cp_time);
460 	getboottime(&boottime);
461 	sbuf_printf(sb, "cpu %ld %ld %ld %ld\n",
462 	    T2J(cp_time[CP_USER]),
463 	    T2J(cp_time[CP_NICE]),
464 	    T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/),
465 	    T2J(cp_time[CP_IDLE]));
466 	CPU_FOREACH(i) {
467 		pcpu = pcpu_find(i);
468 		cp = pcpu->pc_cp_time;
469 		sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i,
470 		    T2J(cp[CP_USER]),
471 		    T2J(cp[CP_NICE]),
472 		    T2J(cp[CP_SYS] /*+ cp[CP_INTR]*/),
473 		    T2J(cp[CP_IDLE]));
474 	}
475 	sbuf_printf(sb,
476 	    "disk 0 0 0 0\n"
477 	    "page %ju %ju\n"
478 	    "swap %ju %ju\n"
479 	    "intr %ju\n"
480 	    "ctxt %ju\n"
481 	    "btime %lld\n",
482 	    (uintmax_t)VM_CNT_FETCH(v_vnodepgsin),
483 	    (uintmax_t)VM_CNT_FETCH(v_vnodepgsout),
484 	    (uintmax_t)VM_CNT_FETCH(v_swappgsin),
485 	    (uintmax_t)VM_CNT_FETCH(v_swappgsout),
486 	    (uintmax_t)VM_CNT_FETCH(v_intr),
487 	    (uintmax_t)VM_CNT_FETCH(v_swtch),
488 	    (long long)boottime.tv_sec);
489 	return (0);
490 }
491 
492 static int
493 linprocfs_doswaps(PFS_FILL_ARGS)
494 {
495 	struct xswdev xsw;
496 	uintmax_t total, used;
497 	int n;
498 	char devname[SPECNAMELEN + 1];
499 
500 	sbuf_printf(sb, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n");
501 	for (n = 0; ; n++) {
502 		if (swap_dev_info(n, &xsw, devname, sizeof(devname)) != 0)
503 			break;
504 		total = (uintmax_t)xsw.xsw_nblks * PAGE_SIZE / 1024;
505 		used  = (uintmax_t)xsw.xsw_used * PAGE_SIZE / 1024;
506 
507 		/*
508 		 * The space and not tab after the device name is on
509 		 * purpose.  Linux does so.
510 		 */
511 		sbuf_printf(sb, "/dev/%-34s unknown\t\t%jd\t%jd\t-1\n",
512 		    devname, total, used);
513 	}
514 	return (0);
515 }
516 
517 /*
518  * Filler function for proc/uptime
519  */
520 static int
521 linprocfs_douptime(PFS_FILL_ARGS)
522 {
523 	long cp_time[CPUSTATES];
524 	struct timeval tv;
525 
526 	getmicrouptime(&tv);
527 	read_cpu_time(cp_time);
528 	sbuf_printf(sb, "%lld.%02ld %ld.%02lu\n",
529 	    (long long)tv.tv_sec, tv.tv_usec / 10000,
530 	    T2S(cp_time[CP_IDLE] / mp_ncpus),
531 	    T2CS(cp_time[CP_IDLE] / mp_ncpus) % 100);
532 	return (0);
533 }
534 
535 /*
536  * Get OS build date
537  */
538 static void
539 linprocfs_osbuild(struct thread *td, struct sbuf *sb)
540 {
541 #if 0
542 	char osbuild[256];
543 	char *cp1, *cp2;
544 
545 	strncpy(osbuild, version, 256);
546 	osbuild[255] = '\0';
547 	cp1 = strstr(osbuild, "\n");
548 	cp2 = strstr(osbuild, ":");
549 	if (cp1 && cp2) {
550 		*cp1 = *cp2 = '\0';
551 		cp1 = strstr(osbuild, "#");
552 	} else
553 		cp1 = NULL;
554 	if (cp1)
555 		sbuf_printf(sb, "%s%s", cp1, cp2 + 1);
556 	else
557 #endif
558 		sbuf_cat(sb, "#4 Sun Dec 18 04:30:00 CET 1977");
559 }
560 
561 /*
562  * Get OS builder
563  */
564 static void
565 linprocfs_osbuilder(struct thread *td, struct sbuf *sb)
566 {
567 #if 0
568 	char builder[256];
569 	char *cp;
570 
571 	cp = strstr(version, "\n    ");
572 	if (cp) {
573 		strncpy(builder, cp + 5, 256);
574 		builder[255] = '\0';
575 		cp = strstr(builder, ":");
576 		if (cp)
577 			*cp = '\0';
578 	}
579 	if (cp)
580 		sbuf_cat(sb, builder);
581 	else
582 #endif
583 		sbuf_cat(sb, "des@freebsd.org");
584 }
585 
586 /*
587  * Filler function for proc/version
588  */
589 static int
590 linprocfs_doversion(PFS_FILL_ARGS)
591 {
592 	char osname[LINUX_MAX_UTSNAME];
593 	char osrelease[LINUX_MAX_UTSNAME];
594 
595 	linux_get_osname(td, osname);
596 	linux_get_osrelease(td, osrelease);
597 	sbuf_printf(sb, "%s version %s (", osname, osrelease);
598 	linprocfs_osbuilder(td, sb);
599 	sbuf_cat(sb, ") (gcc version " __VERSION__ ") ");
600 	linprocfs_osbuild(td, sb);
601 	sbuf_cat(sb, "\n");
602 
603 	return (0);
604 }
605 
606 /*
607  * Filler function for proc/loadavg
608  */
609 static int
610 linprocfs_doloadavg(PFS_FILL_ARGS)
611 {
612 
613 	sbuf_printf(sb,
614 	    "%d.%02d %d.%02d %d.%02d %d/%d %d\n",
615 	    (int)(averunnable.ldavg[0] / averunnable.fscale),
616 	    (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100),
617 	    (int)(averunnable.ldavg[1] / averunnable.fscale),
618 	    (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100),
619 	    (int)(averunnable.ldavg[2] / averunnable.fscale),
620 	    (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100),
621 	    1,				/* number of running tasks */
622 	    nprocs,			/* number of tasks */
623 	    lastpid			/* the last pid */
624 	);
625 	return (0);
626 }
627 
628 /*
629  * Filler function for proc/pid/stat
630  */
631 static int
632 linprocfs_doprocstat(PFS_FILL_ARGS)
633 {
634 	struct kinfo_proc kp;
635 	struct timeval boottime;
636 	char state;
637 	static int ratelimit = 0;
638 	vm_offset_t startcode, startdata;
639 
640 	getboottime(&boottime);
641 	sx_slock(&proctree_lock);
642 	PROC_LOCK(p);
643 	fill_kinfo_proc(p, &kp);
644 	sx_sunlock(&proctree_lock);
645 	if (p->p_vmspace) {
646 	   startcode = (vm_offset_t)p->p_vmspace->vm_taddr;
647 	   startdata = (vm_offset_t)p->p_vmspace->vm_daddr;
648 	} else {
649 	   startcode = 0;
650 	   startdata = 0;
651 	}
652 	sbuf_printf(sb, "%d", p->p_pid);
653 #define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg)
654 	PS_ADD("comm",		"(%s)",	p->p_comm);
655 	if (kp.ki_stat > sizeof(linux_state)) {
656 		state = 'R';
657 
658 		if (ratelimit == 0) {
659 			printf("linprocfs: don't know how to handle unknown FreeBSD state %d/%zd, mapping to R\n",
660 			    kp.ki_stat, sizeof(linux_state));
661 			++ratelimit;
662 		}
663 	} else
664 		state = linux_state[kp.ki_stat - 1];
665 	PS_ADD("state",		"%c",	state);
666 	PS_ADD("ppid",		"%d",	p->p_pptr ? p->p_pptr->p_pid : 0);
667 	PS_ADD("pgrp",		"%d",	p->p_pgid);
668 	PS_ADD("session",	"%d",	p->p_session->s_sid);
669 	PROC_UNLOCK(p);
670 	PS_ADD("tty",		"%ju",	(uintmax_t)kp.ki_tdev);
671 	PS_ADD("tpgid",		"%d",	kp.ki_tpgid);
672 	PS_ADD("flags",		"%u",	0); /* XXX */
673 	PS_ADD("minflt",	"%lu",	kp.ki_rusage.ru_minflt);
674 	PS_ADD("cminflt",	"%lu",	kp.ki_rusage_ch.ru_minflt);
675 	PS_ADD("majflt",	"%lu",	kp.ki_rusage.ru_majflt);
676 	PS_ADD("cmajflt",	"%lu",	kp.ki_rusage_ch.ru_majflt);
677 	PS_ADD("utime",		"%ld",	TV2J(&kp.ki_rusage.ru_utime));
678 	PS_ADD("stime",		"%ld",	TV2J(&kp.ki_rusage.ru_stime));
679 	PS_ADD("cutime",	"%ld",	TV2J(&kp.ki_rusage_ch.ru_utime));
680 	PS_ADD("cstime",	"%ld",	TV2J(&kp.ki_rusage_ch.ru_stime));
681 	PS_ADD("priority",	"%d",	kp.ki_pri.pri_user);
682 	PS_ADD("nice",		"%d",	kp.ki_nice); /* 19 (nicest) to -19 */
683 	PS_ADD("0",		"%d",	0); /* removed field */
684 	PS_ADD("itrealvalue",	"%d",	0); /* XXX */
685 	PS_ADD("starttime",	"%lu",	TV2J(&kp.ki_start) - TV2J(&boottime));
686 	PS_ADD("vsize",		"%ju",	P2K((uintmax_t)kp.ki_size));
687 	PS_ADD("rss",		"%ju",	(uintmax_t)kp.ki_rssize);
688 	PS_ADD("rlim",		"%lu",	kp.ki_rusage.ru_maxrss);
689 	PS_ADD("startcode",	"%ju",	(uintmax_t)startcode);
690 	PS_ADD("endcode",	"%ju",	(uintmax_t)startdata);
691 	PS_ADD("startstack",	"%u",	0); /* XXX */
692 	PS_ADD("kstkesp",	"%u",	0); /* XXX */
693 	PS_ADD("kstkeip",	"%u",	0); /* XXX */
694 	PS_ADD("signal",	"%u",	0); /* XXX */
695 	PS_ADD("blocked",	"%u",	0); /* XXX */
696 	PS_ADD("sigignore",	"%u",	0); /* XXX */
697 	PS_ADD("sigcatch",	"%u",	0); /* XXX */
698 	PS_ADD("wchan",		"%u",	0); /* XXX */
699 	PS_ADD("nswap",		"%lu",	kp.ki_rusage.ru_nswap);
700 	PS_ADD("cnswap",	"%lu",	kp.ki_rusage_ch.ru_nswap);
701 	PS_ADD("exitsignal",	"%d",	0); /* XXX */
702 	PS_ADD("processor",	"%u",	kp.ki_lastcpu);
703 	PS_ADD("rt_priority",	"%u",	0); /* XXX */ /* >= 2.5.19 */
704 	PS_ADD("policy",	"%u",	kp.ki_pri.pri_class); /* >= 2.5.19 */
705 #undef PS_ADD
706 	sbuf_putc(sb, '\n');
707 
708 	return (0);
709 }
710 
711 /*
712  * Filler function for proc/pid/statm
713  */
714 static int
715 linprocfs_doprocstatm(PFS_FILL_ARGS)
716 {
717 	struct kinfo_proc kp;
718 	segsz_t lsize;
719 
720 	sx_slock(&proctree_lock);
721 	PROC_LOCK(p);
722 	fill_kinfo_proc(p, &kp);
723 	PROC_UNLOCK(p);
724 	sx_sunlock(&proctree_lock);
725 
726 	/*
727 	 * See comments in linprocfs_doprocstatus() regarding the
728 	 * computation of lsize.
729 	 */
730 	/* size resident share trs drs lrs dt */
731 	sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size));
732 	sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize);
733 	sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */
734 	sbuf_printf(sb, "%ju ",	(uintmax_t)kp.ki_tsize);
735 	sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize));
736 	lsize = B2P(kp.ki_size) - kp.ki_dsize -
737 	    kp.ki_ssize - kp.ki_tsize - 1;
738 	sbuf_printf(sb, "%ju ", (uintmax_t)lsize);
739 	sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */
740 
741 	return (0);
742 }
743 
744 /*
745  * Filler function for proc/pid/status
746  */
747 static int
748 linprocfs_doprocstatus(PFS_FILL_ARGS)
749 {
750 	struct kinfo_proc kp;
751 	char *state;
752 	segsz_t lsize;
753 	struct thread *td2;
754 	struct sigacts *ps;
755 	l_sigset_t siglist, sigignore, sigcatch;
756 	int i;
757 
758 	sx_slock(&proctree_lock);
759 	PROC_LOCK(p);
760 	td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */
761 
762 	if (P_SHOULDSTOP(p)) {
763 		state = "T (stopped)";
764 	} else {
765 		switch(p->p_state) {
766 		case PRS_NEW:
767 			state = "I (idle)";
768 			break;
769 		case PRS_NORMAL:
770 			if (p->p_flag & P_WEXIT) {
771 				state = "X (exiting)";
772 				break;
773 			}
774 			switch(td2->td_state) {
775 			case TDS_INHIBITED:
776 				state = "S (sleeping)";
777 				break;
778 			case TDS_RUNQ:
779 			case TDS_RUNNING:
780 				state = "R (running)";
781 				break;
782 			default:
783 				state = "? (unknown)";
784 				break;
785 			}
786 			break;
787 		case PRS_ZOMBIE:
788 			state = "Z (zombie)";
789 			break;
790 		default:
791 			state = "? (unknown)";
792 			break;
793 		}
794 	}
795 
796 	fill_kinfo_proc(p, &kp);
797 	sx_sunlock(&proctree_lock);
798 
799 	sbuf_printf(sb, "Name:\t%s\n",		p->p_comm); /* XXX escape */
800 	sbuf_printf(sb, "State:\t%s\n",		state);
801 
802 	/*
803 	 * Credentials
804 	 */
805 	sbuf_printf(sb, "Pid:\t%d\n",		p->p_pid);
806 	sbuf_printf(sb, "PPid:\t%d\n",		p->p_pptr ?
807 						p->p_pptr->p_pid : 0);
808 	sbuf_printf(sb, "Uid:\t%d %d %d %d\n",	p->p_ucred->cr_ruid,
809 						p->p_ucred->cr_uid,
810 						p->p_ucred->cr_svuid,
811 						/* FreeBSD doesn't have fsuid */
812 						p->p_ucred->cr_uid);
813 	sbuf_printf(sb, "Gid:\t%d %d %d %d\n",	p->p_ucred->cr_rgid,
814 						p->p_ucred->cr_gid,
815 						p->p_ucred->cr_svgid,
816 						/* FreeBSD doesn't have fsgid */
817 						p->p_ucred->cr_gid);
818 	sbuf_cat(sb, "Groups:\t");
819 	for (i = 0; i < p->p_ucred->cr_ngroups; i++)
820 		sbuf_printf(sb, "%d ",		p->p_ucred->cr_groups[i]);
821 	PROC_UNLOCK(p);
822 	sbuf_putc(sb, '\n');
823 
824 	/*
825 	 * Memory
826 	 *
827 	 * While our approximation of VmLib may not be accurate (I
828 	 * don't know of a simple way to verify it, and I'm not sure
829 	 * it has much meaning anyway), I believe it's good enough.
830 	 *
831 	 * The same code that could (I think) accurately compute VmLib
832 	 * could also compute VmLck, but I don't really care enough to
833 	 * implement it. Submissions are welcome.
834 	 */
835 	sbuf_printf(sb, "VmSize:\t%8ju kB\n",	B2K((uintmax_t)kp.ki_size));
836 	sbuf_printf(sb, "VmLck:\t%8u kB\n",	P2K(0)); /* XXX */
837 	sbuf_printf(sb, "VmRSS:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_rssize));
838 	sbuf_printf(sb, "VmData:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_dsize));
839 	sbuf_printf(sb, "VmStk:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_ssize));
840 	sbuf_printf(sb, "VmExe:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_tsize));
841 	lsize = B2P(kp.ki_size) - kp.ki_dsize -
842 	    kp.ki_ssize - kp.ki_tsize - 1;
843 	sbuf_printf(sb, "VmLib:\t%8ju kB\n",	P2K((uintmax_t)lsize));
844 
845 	/*
846 	 * Signal masks
847 	 */
848 	PROC_LOCK(p);
849 	bsd_to_linux_sigset(&p->p_siglist, &siglist);
850 	ps = p->p_sigacts;
851 	mtx_lock(&ps->ps_mtx);
852 	bsd_to_linux_sigset(&ps->ps_sigignore, &sigignore);
853 	bsd_to_linux_sigset(&ps->ps_sigcatch, &sigcatch);
854 	mtx_unlock(&ps->ps_mtx);
855 	PROC_UNLOCK(p);
856 
857 	sbuf_printf(sb, "SigPnd:\t%016jx\n",	siglist.__mask);
858 	/*
859 	 * XXX. SigBlk - target thread's signal mask, td_sigmask.
860 	 * To implement SigBlk pseudofs should support proc/tid dir entries.
861 	 */
862 	sbuf_printf(sb, "SigBlk:\t%016x\n",	0);
863 	sbuf_printf(sb, "SigIgn:\t%016jx\n",	sigignore.__mask);
864 	sbuf_printf(sb, "SigCgt:\t%016jx\n",	sigcatch.__mask);
865 
866 	/*
867 	 * Linux also prints the capability masks, but we don't have
868 	 * capabilities yet, and when we do get them they're likely to
869 	 * be meaningless to Linux programs, so we lie. XXX
870 	 */
871 	sbuf_printf(sb, "CapInh:\t%016x\n",	0);
872 	sbuf_printf(sb, "CapPrm:\t%016x\n",	0);
873 	sbuf_printf(sb, "CapEff:\t%016x\n",	0);
874 
875 	return (0);
876 }
877 
878 
879 /*
880  * Filler function for proc/pid/cwd
881  */
882 static int
883 linprocfs_doproccwd(PFS_FILL_ARGS)
884 {
885 	struct filedesc *fdp;
886 	struct vnode *vp;
887 	char *fullpath = "unknown";
888 	char *freepath = NULL;
889 
890 	fdp = p->p_fd;
891 	FILEDESC_SLOCK(fdp);
892 	vp = fdp->fd_cdir;
893 	if (vp != NULL)
894 		VREF(vp);
895 	FILEDESC_SUNLOCK(fdp);
896 	vn_fullpath(td, vp, &fullpath, &freepath);
897 	if (vp != NULL)
898 		vrele(vp);
899 	sbuf_printf(sb, "%s", fullpath);
900 	if (freepath)
901 		free(freepath, M_TEMP);
902 	return (0);
903 }
904 
905 /*
906  * Filler function for proc/pid/root
907  */
908 static int
909 linprocfs_doprocroot(PFS_FILL_ARGS)
910 {
911 	struct filedesc *fdp;
912 	struct vnode *vp;
913 	char *fullpath = "unknown";
914 	char *freepath = NULL;
915 
916 	fdp = p->p_fd;
917 	FILEDESC_SLOCK(fdp);
918 	vp = jailed(p->p_ucred) ? fdp->fd_jdir : fdp->fd_rdir;
919 	if (vp != NULL)
920 		VREF(vp);
921 	FILEDESC_SUNLOCK(fdp);
922 	vn_fullpath(td, vp, &fullpath, &freepath);
923 	if (vp != NULL)
924 		vrele(vp);
925 	sbuf_printf(sb, "%s", fullpath);
926 	if (freepath)
927 		free(freepath, M_TEMP);
928 	return (0);
929 }
930 
931 /*
932  * Filler function for proc/pid/cmdline
933  */
934 static int
935 linprocfs_doproccmdline(PFS_FILL_ARGS)
936 {
937 	int ret;
938 
939 	PROC_LOCK(p);
940 	if ((ret = p_cansee(td, p)) != 0) {
941 		PROC_UNLOCK(p);
942 		return (ret);
943 	}
944 
945 	/*
946 	 * Mimic linux behavior and pass only processes with usermode
947 	 * address space as valid.  Return zero silently otherwize.
948 	 */
949 	if (p->p_vmspace == &vmspace0) {
950 		PROC_UNLOCK(p);
951 		return (0);
952 	}
953 	if (p->p_args != NULL) {
954 		sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length);
955 		PROC_UNLOCK(p);
956 		return (0);
957 	}
958 
959 	if ((p->p_flag & P_SYSTEM) != 0) {
960 		PROC_UNLOCK(p);
961 		return (0);
962 	}
963 
964 	PROC_UNLOCK(p);
965 
966 	ret = proc_getargv(td, p, sb);
967 	return (ret);
968 }
969 
970 /*
971  * Filler function for proc/pid/environ
972  */
973 static int
974 linprocfs_doprocenviron(PFS_FILL_ARGS)
975 {
976 
977 	/*
978 	 * Mimic linux behavior and pass only processes with usermode
979 	 * address space as valid.  Return zero silently otherwize.
980 	 */
981 	if (p->p_vmspace == &vmspace0)
982 		return (0);
983 
984 	return (proc_getenvv(td, p, sb));
985 }
986 
987 static char l32_map_str[] = "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n";
988 static char l64_map_str[] = "%016lx-%016lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n";
989 static char vdso_str[] = "      [vdso]";
990 static char stack_str[] = "      [stack]";
991 
992 /*
993  * Filler function for proc/pid/maps
994  */
995 static int
996 linprocfs_doprocmaps(PFS_FILL_ARGS)
997 {
998 	struct vmspace *vm;
999 	vm_map_t map;
1000 	vm_map_entry_t entry, tmp_entry;
1001 	vm_object_t obj, tobj, lobj;
1002 	vm_offset_t e_start, e_end;
1003 	vm_ooffset_t off = 0;
1004 	vm_prot_t e_prot;
1005 	unsigned int last_timestamp;
1006 	char *name = "", *freename = NULL;
1007 	const char *l_map_str;
1008 	ino_t ino;
1009 	int ref_count, shadow_count, flags;
1010 	int error;
1011 	struct vnode *vp;
1012 	struct vattr vat;
1013 
1014 	PROC_LOCK(p);
1015 	error = p_candebug(td, p);
1016 	PROC_UNLOCK(p);
1017 	if (error)
1018 		return (error);
1019 
1020 	if (uio->uio_rw != UIO_READ)
1021 		return (EOPNOTSUPP);
1022 
1023 	error = 0;
1024 	vm = vmspace_acquire_ref(p);
1025 	if (vm == NULL)
1026 		return (ESRCH);
1027 
1028 	if (SV_CURPROC_FLAG(SV_LP64))
1029 		l_map_str = l64_map_str;
1030 	else
1031 		l_map_str = l32_map_str;
1032 	map = &vm->vm_map;
1033 	vm_map_lock_read(map);
1034 	for (entry = map->header.next; entry != &map->header;
1035 	    entry = entry->next) {
1036 		name = "";
1037 		freename = NULL;
1038 		if (entry->eflags & MAP_ENTRY_IS_SUB_MAP)
1039 			continue;
1040 		e_prot = entry->protection;
1041 		e_start = entry->start;
1042 		e_end = entry->end;
1043 		obj = entry->object.vm_object;
1044 		for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) {
1045 			VM_OBJECT_RLOCK(tobj);
1046 			if (lobj != obj)
1047 				VM_OBJECT_RUNLOCK(lobj);
1048 			lobj = tobj;
1049 		}
1050 		last_timestamp = map->timestamp;
1051 		vm_map_unlock_read(map);
1052 		ino = 0;
1053 		if (lobj) {
1054 			off = IDX_TO_OFF(lobj->size);
1055 			vp = vm_object_vnode(lobj);
1056 			if (vp != NULL)
1057 				vref(vp);
1058 			if (lobj != obj)
1059 				VM_OBJECT_RUNLOCK(lobj);
1060 			flags = obj->flags;
1061 			ref_count = obj->ref_count;
1062 			shadow_count = obj->shadow_count;
1063 			VM_OBJECT_RUNLOCK(obj);
1064 			if (vp != NULL) {
1065 				vn_fullpath(td, vp, &name, &freename);
1066 				vn_lock(vp, LK_SHARED | LK_RETRY);
1067 				VOP_GETATTR(vp, &vat, td->td_ucred);
1068 				ino = vat.va_fileid;
1069 				vput(vp);
1070 			} else if (SV_PROC_ABI(p) == SV_ABI_LINUX) {
1071 				if (e_start == p->p_sysent->sv_shared_page_base)
1072 					name = vdso_str;
1073 				if (e_end == p->p_sysent->sv_usrstack)
1074 					name = stack_str;
1075 			}
1076 		} else {
1077 			flags = 0;
1078 			ref_count = 0;
1079 			shadow_count = 0;
1080 		}
1081 
1082 		/*
1083 		 * format:
1084 		 *  start, end, access, offset, major, minor, inode, name.
1085 		 */
1086 		error = sbuf_printf(sb, l_map_str,
1087 		    (u_long)e_start, (u_long)e_end,
1088 		    (e_prot & VM_PROT_READ)?"r":"-",
1089 		    (e_prot & VM_PROT_WRITE)?"w":"-",
1090 		    (e_prot & VM_PROT_EXECUTE)?"x":"-",
1091 		    "p",
1092 		    (u_long)off,
1093 		    0,
1094 		    0,
1095 		    (u_long)ino,
1096 		    *name ? "     " : "",
1097 		    name
1098 		    );
1099 		if (freename)
1100 			free(freename, M_TEMP);
1101 		vm_map_lock_read(map);
1102 		if (error == -1) {
1103 			error = 0;
1104 			break;
1105 		}
1106 		if (last_timestamp != map->timestamp) {
1107 			/*
1108 			 * Look again for the entry because the map was
1109 			 * modified while it was unlocked.  Specifically,
1110 			 * the entry may have been clipped, merged, or deleted.
1111 			 */
1112 			vm_map_lookup_entry(map, e_end - 1, &tmp_entry);
1113 			entry = tmp_entry;
1114 		}
1115 	}
1116 	vm_map_unlock_read(map);
1117 	vmspace_free(vm);
1118 
1119 	return (error);
1120 }
1121 
1122 /*
1123  * Criteria for interface name translation
1124  */
1125 #define IFP_IS_ETH(ifp) (ifp->if_type == IFT_ETHER)
1126 
1127 static int
1128 linux_ifname(struct ifnet *ifp, char *buffer, size_t buflen)
1129 {
1130 	struct ifnet *ifscan;
1131 	int ethno;
1132 
1133 	IFNET_RLOCK_ASSERT();
1134 
1135 	/* Short-circuit non ethernet interfaces */
1136 	if (!IFP_IS_ETH(ifp))
1137 		return (strlcpy(buffer, ifp->if_xname, buflen));
1138 
1139 	/* Determine the (relative) unit number for ethernet interfaces */
1140 	ethno = 0;
1141 	TAILQ_FOREACH(ifscan, &V_ifnet, if_link) {
1142 		if (ifscan == ifp)
1143 			return (snprintf(buffer, buflen, "eth%d", ethno));
1144 		if (IFP_IS_ETH(ifscan))
1145 			ethno++;
1146 	}
1147 
1148 	return (0);
1149 }
1150 
1151 /*
1152  * Filler function for proc/net/dev
1153  */
1154 static int
1155 linprocfs_donetdev(PFS_FILL_ARGS)
1156 {
1157 	char ifname[16]; /* XXX LINUX_IFNAMSIZ */
1158 	struct ifnet *ifp;
1159 
1160 	sbuf_printf(sb, "%6s|%58s|%s\n"
1161 	    "%6s|%58s|%58s\n",
1162 	    "Inter-", "   Receive", "  Transmit",
1163 	    " face",
1164 	    "bytes    packets errs drop fifo frame compressed multicast",
1165 	    "bytes    packets errs drop fifo colls carrier compressed");
1166 
1167 	CURVNET_SET(TD_TO_VNET(curthread));
1168 	IFNET_RLOCK();
1169 	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
1170 		linux_ifname(ifp, ifname, sizeof ifname);
1171 		sbuf_printf(sb, "%6.6s: ", ifname);
1172 		sbuf_printf(sb, "%7ju %7ju %4ju %4ju %4lu %5lu %10lu %9ju ",
1173 		    (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IBYTES),
1174 		    (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IPACKETS),
1175 		    (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IERRORS),
1176 		    (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IQDROPS),
1177 							/* rx_missed_errors */
1178 		    0UL,				/* rx_fifo_errors */
1179 		    0UL,				/* rx_length_errors +
1180 							 * rx_over_errors +
1181 							 * rx_crc_errors +
1182 							 * rx_frame_errors */
1183 		    0UL,				/* rx_compressed */
1184 		    (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IMCASTS));
1185 							/* XXX-BZ rx only? */
1186 		sbuf_printf(sb, "%8ju %7ju %4ju %4ju %4lu %5ju %7lu %10lu\n",
1187 		    (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OBYTES),
1188 		    (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OPACKETS),
1189 		    (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OERRORS),
1190 		    (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OQDROPS),
1191 		    0UL,				/* tx_fifo_errors */
1192 		    (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_COLLISIONS),
1193 		    0UL,				/* tx_carrier_errors +
1194 							 * tx_aborted_errors +
1195 							 * tx_window_errors +
1196 							 * tx_heartbeat_errors*/
1197 		    0UL);				/* tx_compressed */
1198 	}
1199 	IFNET_RUNLOCK();
1200 	CURVNET_RESTORE();
1201 
1202 	return (0);
1203 }
1204 
1205 /*
1206  * Filler function for proc/sys/kernel/osrelease
1207  */
1208 static int
1209 linprocfs_doosrelease(PFS_FILL_ARGS)
1210 {
1211 	char osrelease[LINUX_MAX_UTSNAME];
1212 
1213 	linux_get_osrelease(td, osrelease);
1214 	sbuf_printf(sb, "%s\n", osrelease);
1215 
1216 	return (0);
1217 }
1218 
1219 /*
1220  * Filler function for proc/sys/kernel/ostype
1221  */
1222 static int
1223 linprocfs_doostype(PFS_FILL_ARGS)
1224 {
1225 	char osname[LINUX_MAX_UTSNAME];
1226 
1227 	linux_get_osname(td, osname);
1228 	sbuf_printf(sb, "%s\n", osname);
1229 
1230 	return (0);
1231 }
1232 
1233 /*
1234  * Filler function for proc/sys/kernel/version
1235  */
1236 static int
1237 linprocfs_doosbuild(PFS_FILL_ARGS)
1238 {
1239 
1240 	linprocfs_osbuild(td, sb);
1241 	sbuf_cat(sb, "\n");
1242 	return (0);
1243 }
1244 
1245 /*
1246  * Filler function for proc/sys/kernel/msgmni
1247  */
1248 static int
1249 linprocfs_domsgmni(PFS_FILL_ARGS)
1250 {
1251 
1252 	sbuf_printf(sb, "%d\n", msginfo.msgmni);
1253 	return (0);
1254 }
1255 
1256 /*
1257  * Filler function for proc/sys/kernel/pid_max
1258  */
1259 static int
1260 linprocfs_dopid_max(PFS_FILL_ARGS)
1261 {
1262 
1263 	sbuf_printf(sb, "%i\n", PID_MAX);
1264 	return (0);
1265 }
1266 
1267 /*
1268  * Filler function for proc/sys/kernel/sem
1269  */
1270 static int
1271 linprocfs_dosem(PFS_FILL_ARGS)
1272 {
1273 
1274 	sbuf_printf(sb, "%d %d %d %d\n", seminfo.semmsl, seminfo.semmns,
1275 	    seminfo.semopm, seminfo.semmni);
1276 	return (0);
1277 }
1278 
1279 /*
1280  * Filler function for proc/scsi/device_info
1281  */
1282 static int
1283 linprocfs_doscsidevinfo(PFS_FILL_ARGS)
1284 {
1285 
1286 	return (0);
1287 }
1288 
1289 /*
1290  * Filler function for proc/scsi/scsi
1291  */
1292 static int
1293 linprocfs_doscsiscsi(PFS_FILL_ARGS)
1294 {
1295 
1296 	return (0);
1297 }
1298 
1299 /*
1300  * Filler function for proc/devices
1301  */
1302 static int
1303 linprocfs_dodevices(PFS_FILL_ARGS)
1304 {
1305 	char *char_devices;
1306 	sbuf_printf(sb, "Character devices:\n");
1307 
1308 	char_devices = linux_get_char_devices();
1309 	sbuf_printf(sb, "%s", char_devices);
1310 	linux_free_get_char_devices(char_devices);
1311 
1312 	sbuf_printf(sb, "\nBlock devices:\n");
1313 
1314 	return (0);
1315 }
1316 
1317 /*
1318  * Filler function for proc/cmdline
1319  */
1320 static int
1321 linprocfs_docmdline(PFS_FILL_ARGS)
1322 {
1323 
1324 	sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname);
1325 	sbuf_printf(sb, " ro root=302\n");
1326 	return (0);
1327 }
1328 
1329 /*
1330  * Filler function for proc/filesystems
1331  */
1332 static int
1333 linprocfs_dofilesystems(PFS_FILL_ARGS)
1334 {
1335 	struct vfsconf *vfsp;
1336 
1337 	vfsconf_slock();
1338 	TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) {
1339 		if (vfsp->vfc_flags & VFCF_SYNTHETIC)
1340 			sbuf_printf(sb, "nodev");
1341 		sbuf_printf(sb, "\t%s\n", vfsp->vfc_name);
1342 	}
1343 	vfsconf_sunlock();
1344 	return(0);
1345 }
1346 
1347 #if 0
1348 /*
1349  * Filler function for proc/modules
1350  */
1351 static int
1352 linprocfs_domodules(PFS_FILL_ARGS)
1353 {
1354 	struct linker_file *lf;
1355 
1356 	TAILQ_FOREACH(lf, &linker_files, link) {
1357 		sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename,
1358 		    (unsigned long)lf->size, lf->refs);
1359 	}
1360 	return (0);
1361 }
1362 #endif
1363 
1364 /*
1365  * Filler function for proc/pid/fd
1366  */
1367 static int
1368 linprocfs_dofdescfs(PFS_FILL_ARGS)
1369 {
1370 
1371 	if (p == curproc)
1372 		sbuf_printf(sb, "/dev/fd");
1373 	else
1374 		sbuf_printf(sb, "unknown");
1375 	return (0);
1376 }
1377 
1378 /*
1379  * Filler function for proc/pid/limits
1380  */
1381 static const struct linux_rlimit_ident {
1382 	const char	*desc;
1383 	const char	*unit;
1384 	unsigned int	rlim_id;
1385 } linux_rlimits_ident[] = {
1386 	{ "Max cpu time",	"seconds",	RLIMIT_CPU },
1387 	{ "Max file size", 	"bytes",	RLIMIT_FSIZE },
1388 	{ "Max data size",	"bytes", 	RLIMIT_DATA },
1389 	{ "Max stack size",	"bytes", 	RLIMIT_STACK },
1390 	{ "Max core file size",  "bytes",	RLIMIT_CORE },
1391 	{ "Max resident set",	"bytes",	RLIMIT_RSS },
1392 	{ "Max processes",	"processes",	RLIMIT_NPROC },
1393 	{ "Max open files",	"files",	RLIMIT_NOFILE },
1394 	{ "Max locked memory",	"bytes",	RLIMIT_MEMLOCK },
1395 	{ "Max address space",	"bytes",	RLIMIT_AS },
1396 	{ "Max file locks",	"locks",	LINUX_RLIMIT_LOCKS },
1397 	{ "Max pending signals", "signals",	LINUX_RLIMIT_SIGPENDING },
1398 	{ "Max msgqueue size",	"bytes",	LINUX_RLIMIT_MSGQUEUE },
1399 	{ "Max nice priority", 		"",	LINUX_RLIMIT_NICE },
1400 	{ "Max realtime priority",	"",	LINUX_RLIMIT_RTPRIO },
1401 	{ "Max realtime timeout",	"us",	LINUX_RLIMIT_RTTIME },
1402 	{ 0, 0, 0 }
1403 };
1404 
1405 static int
1406 linprocfs_doproclimits(PFS_FILL_ARGS)
1407 {
1408 	const struct linux_rlimit_ident *li;
1409 	struct plimit *limp;
1410 	struct rlimit rl;
1411 	ssize_t size;
1412 	int res, error;
1413 
1414 	error = 0;
1415 
1416 	PROC_LOCK(p);
1417 	limp = lim_hold(p->p_limit);
1418 	PROC_UNLOCK(p);
1419 	size = sizeof(res);
1420 	sbuf_printf(sb, "%-26s%-21s%-21s%-21s\n", "Limit", "Soft Limit",
1421 			"Hard Limit", "Units");
1422 	for (li = linux_rlimits_ident; li->desc != NULL; ++li) {
1423 		switch (li->rlim_id)
1424 		{
1425 		case LINUX_RLIMIT_LOCKS:
1426 			/* FALLTHROUGH */
1427 		case LINUX_RLIMIT_RTTIME:
1428 			rl.rlim_cur = RLIM_INFINITY;
1429 			break;
1430 		case LINUX_RLIMIT_SIGPENDING:
1431 			error = kernel_sysctlbyname(td,
1432 			    "kern.sigqueue.max_pending_per_proc",
1433 			    &res, &size, 0, 0, 0, 0);
1434 			if (error != 0)
1435 				goto out;
1436 			rl.rlim_cur = res;
1437 			rl.rlim_max = res;
1438 			break;
1439 		case LINUX_RLIMIT_MSGQUEUE:
1440 			error = kernel_sysctlbyname(td,
1441 			    "kern.ipc.msgmnb", &res, &size, 0, 0, 0, 0);
1442 			if (error != 0)
1443 				goto out;
1444 			rl.rlim_cur = res;
1445 			rl.rlim_max = res;
1446 			break;
1447 		case LINUX_RLIMIT_NICE:
1448 			/* FALLTHROUGH */
1449 		case LINUX_RLIMIT_RTPRIO:
1450 			rl.rlim_cur = 0;
1451 			rl.rlim_max = 0;
1452 			break;
1453 		default:
1454 			rl = limp->pl_rlimit[li->rlim_id];
1455 			break;
1456 		}
1457 		if (rl.rlim_cur == RLIM_INFINITY)
1458 			sbuf_printf(sb, "%-26s%-21s%-21s%-10s\n",
1459 			    li->desc, "unlimited", "unlimited", li->unit);
1460 		else
1461 			sbuf_printf(sb, "%-26s%-21llu%-21llu%-10s\n",
1462 			    li->desc, (unsigned long long)rl.rlim_cur,
1463 			    (unsigned long long)rl.rlim_max, li->unit);
1464 	}
1465 out:
1466 	lim_free(limp);
1467 	return (error);
1468 }
1469 
1470 /*
1471  * Filler function for proc/sys/kernel/random/uuid
1472  */
1473 static int
1474 linprocfs_douuid(PFS_FILL_ARGS)
1475 {
1476 	struct uuid uuid;
1477 
1478 	kern_uuidgen(&uuid, 1);
1479 	sbuf_printf_uuid(sb, &uuid);
1480 	sbuf_printf(sb, "\n");
1481 	return(0);
1482 }
1483 
1484 /*
1485  * Filler function for proc/pid/auxv
1486  */
1487 static int
1488 linprocfs_doauxv(PFS_FILL_ARGS)
1489 {
1490 	struct sbuf *asb;
1491 	off_t buflen, resid;
1492 	int error;
1493 
1494 	/*
1495 	 * Mimic linux behavior and pass only processes with usermode
1496 	 * address space as valid. Return zero silently otherwise.
1497 	 */
1498 	if (p->p_vmspace == &vmspace0)
1499 		return (0);
1500 
1501 	if (uio->uio_resid == 0)
1502 		return (0);
1503 	if (uio->uio_offset < 0 || uio->uio_resid < 0)
1504 		return (EINVAL);
1505 
1506 	asb = sbuf_new_auto();
1507 	if (asb == NULL)
1508 		return (ENOMEM);
1509 	error = proc_getauxv(td, p, asb);
1510 	if (error == 0)
1511 		error = sbuf_finish(asb);
1512 
1513 	resid = sbuf_len(asb) - uio->uio_offset;
1514 	if (resid > uio->uio_resid)
1515 		buflen = uio->uio_resid;
1516 	else
1517 		buflen = resid;
1518 	if (buflen > IOSIZE_MAX)
1519 		return (EINVAL);
1520 	if (buflen > MAXPHYS)
1521 		buflen = MAXPHYS;
1522 	if (resid <= 0)
1523 		return (0);
1524 
1525 	if (error == 0)
1526 		error = uiomove(sbuf_data(asb) + uio->uio_offset, buflen, uio);
1527 	sbuf_delete(asb);
1528 	return (error);
1529 }
1530 
1531 /*
1532  * Constructor
1533  */
1534 static int
1535 linprocfs_init(PFS_INIT_ARGS)
1536 {
1537 	struct pfs_node *root;
1538 	struct pfs_node *dir;
1539 
1540 	root = pi->pi_root;
1541 
1542 	/* /proc/... */
1543 	pfs_create_file(root, "cmdline", &linprocfs_docmdline,
1544 	    NULL, NULL, NULL, PFS_RD);
1545 	pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo,
1546 	    NULL, NULL, NULL, PFS_RD);
1547 	pfs_create_file(root, "devices", &linprocfs_dodevices,
1548 	    NULL, NULL, NULL, PFS_RD);
1549 	pfs_create_file(root, "filesystems", &linprocfs_dofilesystems,
1550 	    NULL, NULL, NULL, PFS_RD);
1551 	pfs_create_file(root, "loadavg", &linprocfs_doloadavg,
1552 	    NULL, NULL, NULL, PFS_RD);
1553 	pfs_create_file(root, "meminfo", &linprocfs_domeminfo,
1554 	    NULL, NULL, NULL, PFS_RD);
1555 #if 0
1556 	pfs_create_file(root, "modules", &linprocfs_domodules,
1557 	    NULL, NULL, NULL, PFS_RD);
1558 #endif
1559 	pfs_create_file(root, "mounts", &linprocfs_domtab,
1560 	    NULL, NULL, NULL, PFS_RD);
1561 	pfs_create_file(root, "mtab", &linprocfs_domtab,
1562 	    NULL, NULL, NULL, PFS_RD);
1563 	pfs_create_file(root, "partitions", &linprocfs_dopartitions,
1564 	    NULL, NULL, NULL, PFS_RD);
1565 	pfs_create_link(root, "self", &procfs_docurproc,
1566 	    NULL, NULL, NULL, 0);
1567 	pfs_create_file(root, "stat", &linprocfs_dostat,
1568 	    NULL, NULL, NULL, PFS_RD);
1569 	pfs_create_file(root, "swaps", &linprocfs_doswaps,
1570 	    NULL, NULL, NULL, PFS_RD);
1571 	pfs_create_file(root, "uptime", &linprocfs_douptime,
1572 	    NULL, NULL, NULL, PFS_RD);
1573 	pfs_create_file(root, "version", &linprocfs_doversion,
1574 	    NULL, NULL, NULL, PFS_RD);
1575 
1576 	/* /proc/net/... */
1577 	dir = pfs_create_dir(root, "net", NULL, NULL, NULL, 0);
1578 	pfs_create_file(dir, "dev", &linprocfs_donetdev,
1579 	    NULL, NULL, NULL, PFS_RD);
1580 
1581 	/* /proc/<pid>/... */
1582 	dir = pfs_create_dir(root, "pid", NULL, NULL, NULL, PFS_PROCDEP);
1583 	pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline,
1584 	    NULL, NULL, NULL, PFS_RD);
1585 	pfs_create_link(dir, "cwd", &linprocfs_doproccwd,
1586 	    NULL, NULL, NULL, 0);
1587 	pfs_create_file(dir, "environ", &linprocfs_doprocenviron,
1588 	    NULL, &procfs_candebug, NULL, PFS_RD);
1589 	pfs_create_link(dir, "exe", &procfs_doprocfile,
1590 	    NULL, &procfs_notsystem, NULL, 0);
1591 	pfs_create_file(dir, "maps", &linprocfs_doprocmaps,
1592 	    NULL, NULL, NULL, PFS_RD);
1593 	pfs_create_file(dir, "mem", &procfs_doprocmem,
1594 	    procfs_attr_rw, &procfs_candebug, NULL, PFS_RDWR | PFS_RAW);
1595 	pfs_create_file(dir, "mounts", &linprocfs_domtab,
1596 	    NULL, NULL, NULL, PFS_RD);
1597 	pfs_create_link(dir, "root", &linprocfs_doprocroot,
1598 	    NULL, NULL, NULL, 0);
1599 	pfs_create_file(dir, "stat", &linprocfs_doprocstat,
1600 	    NULL, NULL, NULL, PFS_RD);
1601 	pfs_create_file(dir, "statm", &linprocfs_doprocstatm,
1602 	    NULL, NULL, NULL, PFS_RD);
1603 	pfs_create_file(dir, "status", &linprocfs_doprocstatus,
1604 	    NULL, NULL, NULL, PFS_RD);
1605 	pfs_create_link(dir, "fd", &linprocfs_dofdescfs,
1606 	    NULL, NULL, NULL, 0);
1607 	pfs_create_file(dir, "auxv", &linprocfs_doauxv,
1608 	    NULL, &procfs_candebug, NULL, PFS_RD|PFS_RAWRD);
1609 	pfs_create_file(dir, "limits", &linprocfs_doproclimits,
1610 	    NULL, NULL, NULL, PFS_RD);
1611 
1612 	/* /proc/scsi/... */
1613 	dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0);
1614 	pfs_create_file(dir, "device_info", &linprocfs_doscsidevinfo,
1615 	    NULL, NULL, NULL, PFS_RD);
1616 	pfs_create_file(dir, "scsi", &linprocfs_doscsiscsi,
1617 	    NULL, NULL, NULL, PFS_RD);
1618 
1619 	/* /proc/sys/... */
1620 	dir = pfs_create_dir(root, "sys", NULL, NULL, NULL, 0);
1621 	/* /proc/sys/kernel/... */
1622 	dir = pfs_create_dir(dir, "kernel", NULL, NULL, NULL, 0);
1623 	pfs_create_file(dir, "osrelease", &linprocfs_doosrelease,
1624 	    NULL, NULL, NULL, PFS_RD);
1625 	pfs_create_file(dir, "ostype", &linprocfs_doostype,
1626 	    NULL, NULL, NULL, PFS_RD);
1627 	pfs_create_file(dir, "version", &linprocfs_doosbuild,
1628 	    NULL, NULL, NULL, PFS_RD);
1629 	pfs_create_file(dir, "msgmni", &linprocfs_domsgmni,
1630 	    NULL, NULL, NULL, PFS_RD);
1631 	pfs_create_file(dir, "pid_max", &linprocfs_dopid_max,
1632 	    NULL, NULL, NULL, PFS_RD);
1633 	pfs_create_file(dir, "sem", &linprocfs_dosem,
1634 	    NULL, NULL, NULL, PFS_RD);
1635 
1636 	/* /proc/sys/kernel/random/... */
1637 	dir = pfs_create_dir(dir, "random", NULL, NULL, NULL, 0);
1638 	pfs_create_file(dir, "uuid", &linprocfs_douuid,
1639 	    NULL, NULL, NULL, PFS_RD);
1640 
1641 	return (0);
1642 }
1643 
1644 /*
1645  * Destructor
1646  */
1647 static int
1648 linprocfs_uninit(PFS_INIT_ARGS)
1649 {
1650 
1651 	/* nothing to do, pseudofs will GC */
1652 	return (0);
1653 }
1654 
1655 PSEUDOFS(linprocfs, 1, VFCF_JAIL);
1656 #if defined(__amd64__)
1657 MODULE_DEPEND(linprocfs, linux_common, 1, 1, 1);
1658 #else
1659 MODULE_DEPEND(linprocfs, linux, 1, 1, 1);
1660 #endif
1661 MODULE_DEPEND(linprocfs, procfs, 1, 1, 1);
1662 MODULE_DEPEND(linprocfs, sysvmsg, 1, 1, 1);
1663 MODULE_DEPEND(linprocfs, sysvsem, 1, 1, 1);
1664