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