xref: /freebsd/sys/compat/linprocfs/linprocfs.c (revision ec447af1917a32900f152ade656ef886ce895d3f)
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  * $FreeBSD$
42  */
43 
44 #include <sys/param.h>
45 #include <sys/blist.h>
46 #include <sys/dkstat.h>
47 #include <sys/jail.h>
48 #include <sys/kernel.h>
49 #include <sys/proc.h>
50 #include <sys/resourcevar.h>
51 #include <sys/sbuf.h>
52 #include <sys/systm.h>
53 #include <sys/tty.h>
54 #include <sys/vnode.h>
55 
56 #include <vm/vm.h>
57 #include <vm/pmap.h>
58 #include <vm/vm_map.h>
59 #include <vm/vm_param.h>
60 #include <vm/vm_object.h>
61 #include <vm/vm_zone.h>
62 #include <vm/swap_pager.h>
63 
64 #include <sys/exec.h>
65 #include <sys/user.h>
66 #include <sys/vmmeter.h>
67 
68 #include <machine/clock.h>
69 #include <machine/cputypes.h>
70 #include <machine/md_var.h>
71 
72 #include <compat/linux/linux_mib.h>
73 #include <compat/linprocfs/linprocfs.h>
74 
75 /*
76  * Various conversion macros
77  */
78 #define T2J(x) (((x) * 100) / (stathz ? stathz : hz))	/* ticks to jiffies */
79 #define T2S(x) ((x) / (stathz ? stathz : hz))		/* ticks to seconds */
80 #define B2K(x) ((x) >> 10)				/* bytes to kbytes */
81 #define B2P(x) ((x) >> PAGE_SHIFT)			/* bytes to pages */
82 #define P2B(x) ((x) << PAGE_SHIFT)			/* pages to bytes */
83 #define P2K(x) ((x) << (PAGE_SHIFT - 10))		/* pages to kbytes */
84 
85 int
86 linprocfs_domeminfo(curp, p, pfs, uio)
87 	struct proc *curp;
88 	struct proc *p;
89 	struct pfsnode *pfs;
90 	struct uio *uio;
91 {
92 	struct sbuf sb;
93 	char *ps;
94 	int r, xlen;
95 	unsigned long memtotal;		/* total memory in bytes */
96 	unsigned long memused;		/* used memory in bytes */
97 	unsigned long memfree;		/* free memory in bytes */
98 	unsigned long memshared;	/* shared memory ??? */
99 	unsigned long buffers, cached;	/* buffer / cache memory ??? */
100 	unsigned long swaptotal;	/* total swap space in bytes */
101 	unsigned long swapused;		/* used swap space in bytes */
102 	unsigned long swapfree;		/* free swap space in bytes */
103 	vm_object_t object;
104 
105 	if (uio->uio_rw != UIO_READ)
106 		return (EOPNOTSUPP);
107 
108 	memtotal = physmem * PAGE_SIZE;
109 	/*
110 	 * The correct thing here would be:
111 	 *
112 	memfree = cnt.v_free_count * PAGE_SIZE;
113 	memused = memtotal - memfree;
114 	 *
115 	 * but it might mislead linux binaries into thinking there
116 	 * is very little memory left, so we cheat and tell them that
117 	 * all memory that isn't wired down is free.
118 	 */
119 	memused = cnt.v_wire_count * PAGE_SIZE;
120 	memfree = memtotal - memused;
121 	if (swapblist == NULL) {
122 		swaptotal = 0;
123 		swapfree = 0;
124 	} else {
125 		swaptotal = swapblist->bl_blocks * 1024; /* XXX why 1024? */
126 		swapfree = swapblist->bl_root->u.bmu_avail * PAGE_SIZE;
127 	}
128 	swapused = swaptotal - swapfree;
129 	memshared = 0;
130 	TAILQ_FOREACH(object, &vm_object_list, object_list)
131 		if (object->shadow_count > 1)
132 			memshared += object->resident_page_count;
133 	memshared *= PAGE_SIZE;
134 	/*
135 	 * We'd love to be able to write:
136 	 *
137 	buffers = bufspace;
138 	 *
139 	 * but bufspace is internal to vfs_bio.c and we don't feel
140 	 * like unstaticizing it just for linprocfs's sake.
141 	 */
142 	buffers = 0;
143 	cached = cnt.v_cache_count * PAGE_SIZE;
144 
145 	sbuf_new(&sb, NULL, 512, 0);
146 	sbuf_printf(&sb,
147 	    "        total:    used:    free:  shared: buffers:  cached:\n"
148 	    "Mem:  %lu %lu %lu %lu %lu %lu\n"
149 	    "Swap: %lu %lu %lu\n"
150 	    "MemTotal: %9lu kB\n"
151 	    "MemFree:  %9lu kB\n"
152 	    "MemShared:%9lu kB\n"
153 	    "Buffers:  %9lu kB\n"
154 	    "Cached:   %9lu kB\n"
155 	    "SwapTotal:%9lu kB\n"
156 	    "SwapFree: %9lu kB\n",
157 	    memtotal, memused, memfree, memshared, buffers, cached,
158 	    swaptotal, swapused, swapfree,
159 	    B2K(memtotal), B2K(memfree),
160 	    B2K(memshared), B2K(buffers), B2K(cached),
161 	    B2K(swaptotal), B2K(swapfree));
162 
163 	sbuf_finish(&sb);
164 	ps = sbuf_data(&sb) + uio->uio_offset;
165 	xlen = sbuf_len(&sb) -  uio->uio_offset;
166 	xlen = imin(xlen, uio->uio_resid);
167 	r = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
168 	sbuf_delete(&sb);
169 	return r;
170 }
171 
172 int
173 linprocfs_docpuinfo(curp, p, pfs, uio)
174 	struct proc *curp;
175 	struct proc *p;
176 	struct pfsnode *pfs;
177 	struct uio *uio;
178 {
179 	struct sbuf sb;
180 	char *ps;
181 	int r, xlen;
182 	int class, i, fqmhz, fqkhz;
183 
184 	/*
185          * We default the flags to include all non-conflicting flags,
186          * and the Intel versions of conflicting flags.
187 	 */
188         static char *flags[] = {
189 		"fpu",      "vme",     "de",       "pse",      "tsc",
190 		"msr",      "pae",     "mce",      "cx8",      "apic",
191 		"sep",      "sep",     "mtrr",     "pge",      "mca",
192 		"cmov",     "pat",     "pse36",    "pn",       "b19",
193 		"b20",      "b21",     "mmxext",   "mmx",      "fxsr",
194 		"xmm",      "b26",     "b27",      "b28",      "b29",
195 		"3dnowext", "3dnow"
196 	};
197 
198 	if (uio->uio_rw != UIO_READ)
199 		return (EOPNOTSUPP);
200 
201 	switch (cpu_class) {
202 	case CPUCLASS_286:
203 		class = 2;
204 		break;
205 	case CPUCLASS_386:
206 		class = 3;
207 		break;
208 	case CPUCLASS_486:
209 		class = 4;
210 		break;
211 	case CPUCLASS_586:
212 		class = 5;
213 		break;
214 	case CPUCLASS_686:
215 		class = 6;
216 		break;
217 	default:
218                 class = 0;
219 		break;
220 	}
221 
222 	sbuf_new(&sb, NULL, 512, 0);
223 	sbuf_printf(&sb,
224             "processor\t: %d\n"
225 	    "vendor_id\t: %.20s\n"
226 	    "cpu family\t: %d\n"
227 	    "model\t\t: %d\n"
228 	    "stepping\t: %d\n",
229 	    0, cpu_vendor, class, cpu, cpu_id & 0xf);
230 
231         sbuf_cat(&sb,
232             "flags\t\t:");
233 
234         if (!strcmp(cpu_vendor, "AuthenticAMD") && (class < 6)) {
235 		flags[16] = "fcmov";
236         } else if (!strcmp(cpu_vendor, "CyrixInstead")) {
237 		flags[24] = "cxmmx";
238         }
239 
240         for (i = 0; i < 32; i++)
241 		if (cpu_feature & (1 << i))
242 			sbuf_printf(&sb, " %s", flags[i]);
243 	sbuf_cat(&sb, "\n");
244         if (class >= 5) {
245 		fqmhz = (tsc_freq + 4999) / 1000000;
246 		fqkhz = ((tsc_freq + 4999) / 10000) % 100;
247 		sbuf_printf(&sb,
248 		    "cpu MHz\t\t: %d.%02d\n"
249 		    "bogomips\t: %d.%02d\n",
250 		    fqmhz, fqkhz, fqmhz, fqkhz);
251         }
252 
253 	sbuf_finish(&sb);
254 	ps = sbuf_data(&sb) + uio->uio_offset;
255 	xlen = sbuf_len(&sb) - uio->uio_offset;
256 	xlen = imin(xlen, uio->uio_resid);
257 	r = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
258 	sbuf_delete(&sb);
259 	return r;
260 }
261 
262 int
263 linprocfs_dostat(curp, p, pfs, uio)
264 	struct proc *curp;
265 	struct proc *p;
266 	struct pfsnode *pfs;
267 	struct uio *uio;
268 {
269 	struct sbuf sb;
270         char *ps;
271 	int r, xlen;
272 
273 	sbuf_new(&sb, NULL, 512, 0);
274 	sbuf_printf(&sb,
275 	    "cpu %ld %ld %ld %ld\n"
276 	    "disk 0 0 0 0\n"
277 	    "page %u %u\n"
278 	    "swap %u %u\n"
279 	    "intr %u\n"
280 	    "ctxt %u\n"
281 	    "btime %ld\n",
282 	    T2J(cp_time[CP_USER]),
283 	    T2J(cp_time[CP_NICE]),
284 	    T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/),
285 	    T2J(cp_time[CP_IDLE]),
286 	    cnt.v_vnodepgsin,
287 	    cnt.v_vnodepgsout,
288 	    cnt.v_swappgsin,
289 	    cnt.v_swappgsout,
290 	    cnt.v_intr,
291 	    cnt.v_swtch,
292 	    boottime.tv_sec);
293 
294 	sbuf_finish(&sb);
295 	ps = sbuf_data(&sb) + uio->uio_offset;
296 	xlen = sbuf_len(&sb) -  uio->uio_offset;
297 	xlen = imin(xlen, uio->uio_resid);
298 	r = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
299 	sbuf_delete(&sb);
300 	return r;
301 }
302 
303 int
304 linprocfs_douptime(curp, p, pfs, uio)
305 	struct proc *curp;
306 	struct proc *p;
307 	struct pfsnode *pfs;
308 	struct uio *uio;
309 {
310 	struct sbuf sb;
311 	char *ps;
312 	int r, xlen;
313 	struct timeval tv;
314 
315 	getmicrouptime(&tv);
316 	sbuf_new(&sb, NULL, 64, 0);
317 	sbuf_printf(&sb, "%ld.%02ld %ld.%02ld\n",
318 	    tv.tv_sec, tv.tv_usec / 10000,
319 	    T2S(cp_time[CP_IDLE]), T2J(cp_time[CP_IDLE]) % 100);
320 	sbuf_finish(&sb);
321 	ps = sbuf_data(&sb) + uio->uio_offset;
322 	xlen = sbuf_len(&sb) -  uio->uio_offset;
323 	xlen = imin(xlen, uio->uio_resid);
324 	r = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
325 	sbuf_delete(&sb);
326 	return r;
327 }
328 
329 int
330 linprocfs_doversion(curp, p, pfs, uio)
331 	struct proc *curp;
332 	struct proc *p;
333 	struct pfsnode *pfs;
334 	struct uio *uio;
335 {
336 	struct sbuf sb;
337         char *ps;
338 	int r, xlen;
339 
340 	sbuf_new(&sb, NULL, 128, 0);
341 	sbuf_printf(&sb,
342 	    "%s version %s (des@freebsd.org) (gcc version " __VERSION__ ")"
343 	    " #4 Sun Dec 18 04:30:00 CET 1977\n",
344 	    linux_get_osname(curp),
345 	    linux_get_osrelease(curp));
346 	sbuf_finish(&sb);
347 	ps = sbuf_data(&sb) + uio->uio_offset;
348 	xlen = sbuf_len(&sb) -  uio->uio_offset;
349 	xlen = imin(xlen, uio->uio_resid);
350 	r = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
351 	sbuf_delete(&sb);
352 	return r;
353 }
354 
355 int
356 linprocfs_doprocstat(curp, p, pfs, uio)
357     	struct proc *curp;
358 	struct proc *p;
359 	struct pfsnode *pfs;
360 	struct uio *uio;
361 {
362 	struct kinfo_proc kp;
363 	struct sbuf sb;
364 	char *ps;
365 	int r, xlen;
366 	pid_t ppid;
367 
368 	PROCTREE_LOCK(PT_SHARED);
369 	ppid = p->p_pptr ? p->p_pptr->p_pid : 0;
370 	PROCTREE_LOCK(PT_RELEASE);
371 	fill_kinfo_proc(p, &kp);
372 	sbuf_new(&sb, NULL, 1024, 0);
373 	sbuf_printf(&sb, "%d", p->p_pid);
374 #define PS_ADD(name, fmt, arg) sbuf_printf(&sb, " " fmt, arg)
375 	PS_ADD("comm",		"(%s)",	p->p_comm);
376 	PS_ADD("statr",		"%c",	'0'); /* XXX */
377 	PS_ADD("ppid",		"%d",	ppid);
378 	PS_ADD("pgrp",		"%d",	p->p_pgid);
379 	PS_ADD("session",	"%d",	p->p_session->s_sid);
380 	PS_ADD("tty",		"%d",	0); /* XXX */
381 	PS_ADD("tpgid",		"%d",	0); /* XXX */
382 	PS_ADD("flags",		"%u",	0); /* XXX */
383 	PS_ADD("minflt",	"%u",	0); /* XXX */
384 	PS_ADD("cminflt",	"%u",	0); /* XXX */
385 	PS_ADD("majflt",	"%u",	0); /* XXX */
386 	PS_ADD("cminflt",	"%u",	0); /* XXX */
387 	PS_ADD("utime",		"%d",	0); /* XXX */
388 	PS_ADD("stime",		"%d",	0); /* XXX */
389 	PS_ADD("cutime",	"%d",	0); /* XXX */
390 	PS_ADD("cstime",	"%d",	0); /* XXX */
391 	PS_ADD("counter",	"%d",	0); /* XXX */
392 	PS_ADD("priority",	"%d",	0); /* XXX */
393 	PS_ADD("timeout",	"%u",	0); /* XXX */
394 	PS_ADD("itrealvalue",	"%u",	0); /* XXX */
395 	PS_ADD("starttime",	"%d",	0); /* XXX */
396 	PS_ADD("vsize",		"%u",	kp.ki_size);
397 	PS_ADD("rss",		"%u",	P2K(kp.ki_rssize));
398 	PS_ADD("rlim",		"%u",	0); /* XXX */
399 	PS_ADD("startcode",	"%u",	(unsigned)0);
400 	PS_ADD("endcode",	"%u",	0); /* XXX */
401 	PS_ADD("startstack",	"%u",	0); /* XXX */
402 	PS_ADD("esp",		"%u",	0); /* XXX */
403 	PS_ADD("eip",		"%u",	0); /* XXX */
404 	PS_ADD("signal",	"%d",	0); /* XXX */
405 	PS_ADD("blocked",	"%d",	0); /* XXX */
406 	PS_ADD("sigignore",	"%d",	0); /* XXX */
407 	PS_ADD("sigcatch",	"%d",	0); /* XXX */
408 	PS_ADD("wchan",		"%u",	0); /* XXX */
409 	PS_ADD("nswap",		"%lu",	(long unsigned)0); /* XXX */
410 	PS_ADD("cnswap",	"%lu",	(long unsigned)0); /* XXX */
411 	PS_ADD("exitsignal",	"%d",	0); /* XXX */
412 	PS_ADD("processor",	"%d",	0); /* XXX */
413 #undef PS_ADD
414 	sbuf_putc(&sb, '\n');
415 
416 	sbuf_finish(&sb);
417 	ps = sbuf_data(&sb) + uio->uio_offset;
418 	xlen = sbuf_len(&sb) -  uio->uio_offset;
419 	xlen = imin(xlen, uio->uio_resid);
420 	r = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
421 	sbuf_delete(&sb);
422 	return r;
423 }
424 
425 /*
426  * Map process state to descriptive letter. Note that this does not
427  * quite correspond to what Linux outputs, but it's close enough.
428  */
429 static char *state_str[] = {
430 	"? (unknown)",
431 	"I (idle)",
432 	"R (running)",
433 	"S (sleeping)",
434 	"T (stopped)",
435 	"Z (zombie)",
436 	"W (waiting)",
437 	"M (mutex)"
438 };
439 
440 int
441 linprocfs_doprocstatus(curp, p, pfs, uio)
442     	struct proc *curp;
443 	struct proc *p;
444 	struct pfsnode *pfs;
445 	struct uio *uio;
446 {
447 	struct kinfo_proc kp;
448 	struct sbuf sb;
449 	char *ps;
450 	char *state;
451 	int i, r, xlen;
452 	segsz_t lsize;
453 	pid_t ppid;
454 
455 	sbuf_new(&sb, NULL, 1024, 0);
456 
457 	mtx_enter(&sched_lock, MTX_SPIN);
458 	if (p->p_stat > sizeof state_str / sizeof *state_str)
459 		state = state_str[0];
460 	else
461 		state = state_str[(int)p->p_stat];
462 	mtx_exit(&sched_lock, MTX_SPIN);
463 
464 	PROCTREE_LOCK(PT_SHARED);
465 	ppid = p->p_pptr ? p->p_pptr->p_pid : 0;
466 	PROCTREE_LOCK(PT_RELEASE);
467 	fill_kinfo_proc(p, &kp);
468 	sbuf_printf(&sb, "Name:\t%s\n",		p->p_comm); /* XXX escape */
469 	sbuf_printf(&sb, "State:\t%s\n",	state);
470 
471 	/*
472 	 * Credentials
473 	 */
474 	sbuf_printf(&sb, "Pid:\t%d\n",		p->p_pid);
475 	sbuf_printf(&sb, "PPid:\t%d\n",		ppid);
476 	PROC_LOCK(p);
477 	sbuf_printf(&sb, "Uid:\t%d %d %d %d\n", p->p_cred->p_ruid,
478 			                        p->p_ucred->cr_uid,
479 			                        p->p_cred->p_svuid,
480 			                        /* FreeBSD doesn't have fsuid */
481 				                p->p_ucred->cr_uid);
482 	sbuf_printf(&sb, "Gid:\t%d %d %d %d\n", p->p_cred->p_rgid,
483 			                        p->p_ucred->cr_gid,
484 			                        p->p_cred->p_svgid,
485 			                        /* FreeBSD doesn't have fsgid */
486 				                p->p_ucred->cr_gid);
487 	sbuf_cat(&sb, "Groups:\t");
488 	for (i = 0; i < p->p_ucred->cr_ngroups; i++)
489 		sbuf_printf(&sb, "%d ", p->p_ucred->cr_groups[i]);
490 	PROC_UNLOCK(p);
491 	sbuf_putc(&sb, '\n');
492 
493 	/*
494 	 * Memory
495 	 *
496 	 * While our approximation of VmLib may not be accurate (I
497 	 * don't know of a simple way to verify it, and I'm not sure
498 	 * it has much meaning anyway), I believe it's good enough.
499 	 *
500 	 * The same code that could (I think) accurately compute VmLib
501 	 * could also compute VmLck, but I don't really care enough to
502 	 * implement it. Submissions are welcome.
503 	 */
504 	sbuf_printf(&sb, "VmSize:\t%8u kB\n",	B2K(kp.ki_size));
505 	sbuf_printf(&sb, "VmLck:\t%8u kB\n",	P2K(0)); /* XXX */
506 	sbuf_printf(&sb, "VmRss:\t%8u kB\n",	P2K(kp.ki_rssize));
507 	sbuf_printf(&sb, "VmData:\t%8u kB\n",	P2K(kp.ki_dsize));
508 	sbuf_printf(&sb, "VmStk:\t%8u kB\n",	P2K(kp.ki_ssize));
509 	sbuf_printf(&sb, "VmExe:\t%8u kB\n",	P2K(kp.ki_tsize));
510 	lsize = B2P(kp.ki_size) - kp.ki_dsize -
511 	    kp.ki_ssize - kp.ki_tsize - 1;
512 	sbuf_printf(&sb, "VmLib:\t%8u kB\n",	P2K(lsize));
513 
514 	/*
515 	 * Signal masks
516 	 *
517 	 * We support up to 128 signals, while Linux supports 32,
518 	 * but we only define 32 (the same 32 as Linux, to boot), so
519 	 * just show the lower 32 bits of each mask. XXX hack.
520 	 *
521 	 * NB: on certain platforms (Sparc at least) Linux actually
522 	 * supports 64 signals, but this code is a long way from
523 	 * running on anything but i386, so ignore that for now.
524 	 */
525 	PROC_LOCK(p);
526 	sbuf_printf(&sb, "SigPnd:\t%08x\n",	p->p_siglist.__bits[0]);
527 	/*
528 	 * I can't seem to find out where the signal mask is in
529 	 * relation to struct proc, so SigBlk is left unimplemented.
530 	 */
531 	sbuf_printf(&sb, "SigBlk:\t%08x\n",	0); /* XXX */
532 	sbuf_printf(&sb, "SigIgn:\t%08x\n",	p->p_sigignore.__bits[0]);
533 	sbuf_printf(&sb, "SigCgt:\t%08x\n",	p->p_sigcatch.__bits[0]);
534 	PROC_UNLOCK(p);
535 
536 	/*
537 	 * Linux also prints the capability masks, but we don't have
538 	 * capabilities yet, and when we do get them they're likely to
539 	 * be meaningless to Linux programs, so we lie. XXX
540 	 */
541 	sbuf_printf(&sb, "CapInh:\t%016x\n",	0);
542 	sbuf_printf(&sb, "CapPrm:\t%016x\n",	0);
543 	sbuf_printf(&sb, "CapEff:\t%016x\n",	0);
544 
545 	sbuf_finish(&sb);
546 	ps = sbuf_data(&sb) + uio->uio_offset;
547 	xlen = sbuf_len(&sb) -  uio->uio_offset;
548 	xlen = imin(xlen, uio->uio_resid);
549 	r = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
550 	sbuf_delete(&sb);
551 	return r;
552 }
553