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