Fix caveat in new implementation of linprocfs_docpuinfo():
[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         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);