]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/compat/linprocfs/linprocfs.c
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r306325, and update
[FreeBSD/FreeBSD.git] / sys / compat / linprocfs / linprocfs.c
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);