AMD64 - Refactor uio_resid and size_t assumptions.
[dragonfly.git] / sys / emulation / linux / i386 / linprocfs / linprocfs_misc.c
CommitLineData
984263bc
MD
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: src/sys/i386/linux/linprocfs/linprocfs_misc.c,v 1.3.2.8 2001/06/25 19:46:47 pirzyk Exp $
870b0161 42 * $DragonFly: src/sys/emulation/linux/i386/linprocfs/linprocfs_misc.c,v 1.19 2008/05/10 17:24:05 dillon Exp $
984263bc
MD
43 */
44
45#include <sys/param.h>
46#include <sys/blist.h>
984263bc 47#include <sys/kernel.h>
9eea7f0c 48#include <sys/kinfo.h>
984263bc 49#include <sys/proc.h>
b91ea118 50#include <sys/jail.h>
984263bc
MD
51#include <sys/resourcevar.h>
52#include <sys/systm.h>
53#include <sys/tty.h>
54#include <sys/vnode.h>
55#include <sys/lock.h>
56
57#include <vm/vm.h>
58#include <vm/pmap.h>
59#include <vm/vm_map.h>
60#include <vm/vm_param.h>
61#include <vm/vm_object.h>
62#include <vm/swap_pager.h>
63#include <sys/vmmeter.h>
64#include <sys/exec.h>
65
66#include <machine/clock.h>
67#include <machine/cputypes.h>
b91ea118 68#include <machine/inttypes.h>
984263bc
MD
69#include <machine/md_var.h>
70
1f2de5d4 71#include "linprocfs.h"
984263bc
MD
72
73/*
74 * Various conversion macros
75 */
e5a22113 76#define T2J(x) (((x) * 100) / (stathz ? stathz : hz)) /* ticks to jiffies */
984263bc 77#define T2S(x) ((x) / (stathz ? stathz : hz)) /* ticks to seconds */
09b0da94 78#define B2K(x) ((unsigned long)((x) >> 10)) /* bytes to kbytes */
984263bc
MD
79#define P2B(x) ((x) << PAGE_SHIFT) /* pages to bytes */
80#define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */
81
82int
2da2a8af
SW
83linprocfs_domeminfo(struct proc *curp, struct proc *p, struct pfsnode *pfs,
84 struct uio *uio)
984263bc
MD
85{
86 char *ps;
984263bc
MD
87 char psbuf[512]; /* XXX - conservative */
88 unsigned long memtotal; /* total memory in bytes */
89 unsigned long memused; /* used memory in bytes */
90 unsigned long memfree; /* free memory in bytes */
91 unsigned long memshared; /* shared memory ??? */
92 unsigned long buffers, cached; /* buffer / cache memory ??? */
09b0da94
MD
93 unsigned long long swaptotal; /* total swap space in bytes */
94 unsigned long long swapused; /* used swap space in bytes */
95 unsigned long long swapfree; /* free swap space in bytes */
984263bc
MD
96 vm_object_t object;
97
98 if (uio->uio_rw != UIO_READ)
99 return (EOPNOTSUPP);
100
31c33cf2 101 memtotal = Maxmem * PAGE_SIZE;
984263bc
MD
102 /*
103 * The correct thing here would be:
104 *
12e4aaff 105 memfree = vmstats.v_free_count * PAGE_SIZE;
984263bc
MD
106 memused = memtotal - memfree;
107 *
108 * but it might mislead linux binaries into thinking there
109 * is very little memory left, so we cheat and tell them that
110 * all memory that isn't wired down is free.
111 */
12e4aaff 112 memused = vmstats.v_wire_count * PAGE_SIZE;
984263bc
MD
113 memfree = memtotal - memused;
114 if (swapblist == NULL) {
115 swaptotal = 0;
116 swapfree = 0;
117 } else {
09b0da94
MD
118 swaptotal = swapblist->bl_blocks * 1024LL; /* XXX why 1024? */
119 swapfree = (unsigned long long)swapblist->bl_root->u.bmu_avail * PAGE_SIZE;
984263bc
MD
120 }
121 swapused = swaptotal - swapfree;
122 memshared = 0;
123 for (object = TAILQ_FIRST(&vm_object_list); object != NULL;
124 object = TAILQ_NEXT(object, object_list))
125 if (object->shadow_count > 1)
126 memshared += object->resident_page_count;
127 memshared *= PAGE_SIZE;
128 /*
129 * We'd love to be able to write:
130 *
131 buffers = bufspace;
132 *
133 * but bufspace is internal to vfs_bio.c and we don't feel
134 * like unstaticizing it just for linprocfs's sake.
135 */
136 buffers = 0;
12e4aaff 137 cached = vmstats.v_cache_count * PAGE_SIZE;
984263bc
MD
138
139 ps = psbuf;
f8c7a42d 140 ps += ksprintf(ps,
984263bc
MD
141 " total: used: free: shared: buffers: cached:\n"
142 "Mem: %lu %lu %lu %lu %lu %lu\n"
143 "Swap: %llu %llu %llu\n"
144 "MemTotal: %9lu kB\n"
145 "MemFree: %9lu kB\n"
146 "MemShared:%9lu kB\n"
147 "Buffers: %9lu kB\n"
148 "Cached: %9lu kB\n"
e5a22113
DR
149 "SwapTotal:%9lu kB\n"
150 "SwapFree: %9lu kB\n",
984263bc
MD
151 memtotal, memused, memfree, memshared, buffers, cached,
152 swaptotal, swapused, swapfree,
153 B2K(memtotal), B2K(memfree),
154 B2K(memshared), B2K(buffers), B2K(cached),
155 B2K(swaptotal), B2K(swapfree));
156
e5a22113 157 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
984263bc
MD
158}
159
160int
2da2a8af
SW
161linprocfs_docpuinfo(struct proc *curp, struct proc *p, struct pfsnode *pfs,
162 struct uio *uio)
984263bc
MD
163{
164 char *ps;
984263bc
MD
165 char psbuf[512]; /* XXX - conservative */
166 int class;
167 int i;
168#if 0
169 extern char *cpu_model; /* Yuck */
170#endif
171 /* We default the flags to include all non-conflicting flags,
172 and the Intel versions of conflicting flags. Note the space
173 before each name; that is significant, and should be
174 preserved. */
175
176 static char *flags[] = {
177 "fpu", "vme", "de", "pse", "tsc",
178 "msr", "pae", "mce", "cx8", "apic",
179 "sep", "sep", "mtrr", "pge", "mca",
180 "cmov", "pat", "pse36", "pn", "b19",
181 "b20", "b21", "mmxext", "mmx", "fxsr",
182 "xmm", "b26", "b27", "b28", "b29",
183 "3dnowext", "3dnow"
184 };
185
186 if (uio->uio_rw != UIO_READ)
187 return (EOPNOTSUPP);
188
189 switch (cpu_class) {
190 case CPUCLASS_286:
191 class = 2;
192 break;
193 case CPUCLASS_386:
194 class = 3;
195 break;
196 case CPUCLASS_486:
197 class = 4;
198 break;
199 case CPUCLASS_586:
200 class = 5;
201 break;
202 case CPUCLASS_686:
203 class = 6;
204 break;
205 default:
206 class = 0;
207 break;
208 }
209
210 ps = psbuf;
f8c7a42d 211 ps += ksprintf(ps,
984263bc
MD
212 "processor\t: %d\n"
213 "vendor_id\t: %.20s\n"
214 "cpu family\t: %d\n"
215 "model\t\t: %d\n"
216 "stepping\t: %d\n",
217 0, cpu_vendor, class, cpu, cpu_id & 0xf);
218
f8c7a42d 219 ps += ksprintf(ps,
984263bc
MD
220 "flags\t\t:");
221
222 if (!strcmp(cpu_vendor, "AuthenticAMD") && (class < 6)) {
223 flags[16] = "fcmov";
224 } else if (!strcmp(cpu_vendor, "CyrixInstead")) {
225 flags[24] = "cxmmx";
226 }
227
228 for (i = 0; i < 32; i++)
229 if (cpu_feature & (1 << i))
f8c7a42d
MD
230 ps += ksprintf(ps, " %s", flags[i]);
231 ps += ksprintf(ps, "\n");
984263bc 232 if (class >= 5) {
f8c7a42d 233 ps += ksprintf(ps,
984263bc
MD
234 "cpu MHz\t\t: %d.%02d\n"
235 "bogomips\t: %d.%02d\n",
870b0161
MD
236 (int)((tsc_frequency + 4999) / 1000000),
237 (int)((tsc_frequency + 4999) / 10000) % 100,
238 (int)((tsc_frequency + 4999) / 1000000),
239 (int)((tsc_frequency + 4999) / 10000) % 100);
984263bc
MD
240 }
241
e5a22113 242 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
984263bc
MD
243}
244
12e4aaff
MD
245static unsigned int
246cpucnt(int offset)
247{
248 int i;
249 int count = 0;
250
251 for (i = 0; i < ncpus; ++i) {
252 struct globaldata *gd = globaldata_find(i);
253 count += *(unsigned int *)((char *)&gd->gd_cnt + offset);
254 }
255 return(count);
256}
257
984263bc 258int
2da2a8af
SW
259linprocfs_dostat(struct proc *curp, struct proc *p, struct pfsnode *pfs,
260 struct uio *uio)
984263bc
MD
261{
262 char *ps;
263 char psbuf[512];
984263bc
MD
264
265 ps = psbuf;
f8c7a42d 266 ps += ksprintf(ps,
b91ea118 267 "cpu %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64"\n"
984263bc
MD
268 "disk 0 0 0 0\n"
269 "page %u %u\n"
270 "swap %u %u\n"
271 "intr %u\n"
272 "ctxt %u\n"
273 "btime %ld\n",
9eea7f0c
HP
274 T2J(cpu_time.cp_user),
275 T2J(cpu_time.cp_nice),
276 T2J(cpu_time.cp_sys /*+ cpu_time[CP_INTR]*/),
277 T2J(cpu_time.cp_idle),
12e4aaff
MD
278 cpucnt(offsetof(struct vmmeter, v_vnodepgsin)),
279 cpucnt(offsetof(struct vmmeter, v_vnodepgsout)),
280 cpucnt(offsetof(struct vmmeter, v_swappgsin)),
281 cpucnt(offsetof(struct vmmeter, v_swappgsout)),
282 cpucnt(offsetof(struct vmmeter, v_intr)),
283 cpucnt(offsetof(struct vmmeter, v_swtch)),
984263bc 284 boottime.tv_sec);
e5a22113 285 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
984263bc
MD
286}
287
288int
2da2a8af
SW
289linprocfs_douptime(struct proc *curp, struct proc *p, struct pfsnode *pfs,
290 struct uio *uio)
984263bc
MD
291{
292 char *ps;
984263bc
MD
293 char psbuf[64];
294 struct timeval tv;
295
296 getmicrouptime(&tv);
297 ps = psbuf;
f8c7a42d 298 ps += ksprintf(ps, "%ld.%02ld %"PRIu64".%02"PRIu64"\n",
984263bc 299 tv.tv_sec, tv.tv_usec / 10000,
9eea7f0c 300 T2S(cpu_time.cp_idle), T2J(cpu_time.cp_idle) % 100);
e5a22113 301 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
984263bc
MD
302}
303
304int
2da2a8af
SW
305linprocfs_doversion(struct proc *curp, struct proc *p, struct pfsnode *pfs,
306 struct uio *uio)
984263bc
MD
307{
308 char *ps;
e54488bb 309 size_t xlen;
984263bc
MD
310
311 ps = version; /* XXX not entirely correct */
312 for (xlen = 0; ps[xlen] != '\n'; ++xlen)
313 /* nothing */ ;
314 ++xlen;
e5a22113 315 return (uiomove_frombuf(ps, xlen, uio));
984263bc
MD
316}
317
318int
2da2a8af
SW
319linprocfs_doprocstat(struct proc *curp, struct proc *p, struct pfsnode *pfs,
320 struct uio *uio)
984263bc
MD
321{
322 char *ps, psbuf[1024];
984263bc
MD
323
324 ps = psbuf;
f8c7a42d
MD
325 ps += ksprintf(ps, "%d", p->p_pid);
326#define PS_ADD(name, fmt, arg) ps += ksprintf(ps, " " fmt, arg)
984263bc
MD
327 PS_ADD("comm", "(%s)", p->p_comm);
328 PS_ADD("statr", "%c", '0'); /* XXX */
329 PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0);
330 PS_ADD("pgrp", "%d", p->p_pgid);
331 PS_ADD("session", "%d", p->p_session->s_sid);
332 PS_ADD("tty", "%d", 0); /* XXX */
333 PS_ADD("tpgid", "%d", 0); /* XXX */
334 PS_ADD("flags", "%u", 0); /* XXX */
335 PS_ADD("minflt", "%u", 0); /* XXX */
336 PS_ADD("cminflt", "%u", 0); /* XXX */
337 PS_ADD("majflt", "%u", 0); /* XXX */
338 PS_ADD("cminflt", "%u", 0); /* XXX */
339 PS_ADD("utime", "%d", 0); /* XXX */
340 PS_ADD("stime", "%d", 0); /* XXX */
341 PS_ADD("cutime", "%d", 0); /* XXX */
342 PS_ADD("cstime", "%d", 0); /* XXX */
343 PS_ADD("counter", "%d", 0); /* XXX */
344 PS_ADD("priority", "%d", 0); /* XXX */
345 PS_ADD("timeout", "%u", 0); /* XXX */
346 PS_ADD("itrealvalue", "%u", 0); /* XXX */
347 PS_ADD("starttime", "%d", 0); /* XXX */
348 PS_ADD("vsize", "%u", 0); /* XXX */
349 PS_ADD("rss", "%u", 0); /* XXX */
350 PS_ADD("rlim", "%u", 0); /* XXX */
351 PS_ADD("startcode", "%u", 0); /* XXX */
352 PS_ADD("endcode", "%u", 0); /* XXX */
353 PS_ADD("startstack", "%u", 0); /* XXX */
354 PS_ADD("kstkesp", "%u", 0); /* XXX */
355 PS_ADD("kstkeip", "%u", 0); /* XXX */
356 PS_ADD("signal", "%d", 0); /* XXX */
357 PS_ADD("blocked", "%d", 0); /* XXX */
358 PS_ADD("sigignore", "%d", 0); /* XXX */
359 PS_ADD("sigcatch", "%d", 0); /* XXX */
360 PS_ADD("wchan", "%u", 0); /* XXX */
361#undef PS_ADD
f8c7a42d 362 ps += ksprintf(ps, "\n");
984263bc 363
e5a22113 364 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
984263bc
MD
365}
366
367/*
368 * Map process state to descriptive letter. Note that this does not
369 * quite correspond to what Linux outputs, but it's close enough.
370 */
371static char *state_str[] = {
372 "? (unknown)",
373 "I (idle)",
374 "R (running)",
984263bc
MD
375 "T (stopped)",
376 "Z (zombie)",
164b8401 377 "S (sleeping)",
984263bc
MD
378 "W (waiting)",
379 "M (mutex)"
380};
381
382int
2da2a8af
SW
383linprocfs_doprocstatus(struct proc *curp, struct proc *p, struct pfsnode *pfs,
384 struct uio *uio)
984263bc
MD
385{
386 char *ps, psbuf[1024];
387 char *state;
e5a22113 388 int i;
984263bc
MD
389
390 ps = psbuf;
391
392 if (p->p_stat > sizeof state_str / sizeof *state_str)
393 state = state_str[0];
394 else
395 state = state_str[(int)p->p_stat];
396
f8c7a42d 397#define PS_ADD ps += ksprintf
984263bc
MD
398 PS_ADD(ps, "Name:\t%s\n", p->p_comm); /* XXX escape */
399 PS_ADD(ps, "State:\t%s\n", state);
400
401 /*
402 * Credentials
403 */
404 PS_ADD(ps, "Pid:\t%d\n", p->p_pid);
405 PS_ADD(ps, "PPid:\t%d\n", p->p_pptr ? p->p_pptr->p_pid : 0);
41c20dac 406 PS_ADD(ps, "Uid:\t%d %d %d %d\n", p->p_ucred->cr_ruid,
984263bc 407 p->p_ucred->cr_uid,
41c20dac 408 p->p_ucred->cr_svuid,
984263bc
MD
409 /* FreeBSD doesn't have fsuid */
410 p->p_ucred->cr_uid);
41c20dac 411 PS_ADD(ps, "Gid:\t%d %d %d %d\n", p->p_ucred->cr_rgid,
984263bc 412 p->p_ucred->cr_gid,
41c20dac 413 p->p_ucred->cr_svgid,
984263bc
MD
414 /* FreeBSD doesn't have fsgid */
415 p->p_ucred->cr_gid);
416 PS_ADD(ps, "Groups:\t");
417 for (i = 0; i < p->p_ucred->cr_ngroups; i++)
418 PS_ADD(ps, "%d ", p->p_ucred->cr_groups[i]);
419 PS_ADD(ps, "\n");
420
421 /*
422 * Memory
423 */
09b0da94 424 PS_ADD(ps, "VmSize:\t%8lu kB\n", B2K(p->p_vmspace->vm_map.size));
984263bc
MD
425 PS_ADD(ps, "VmLck:\t%8u kB\n", P2K(0)); /* XXX */
426 /* XXX vm_rssize seems to always be zero, how can this be? */
427 PS_ADD(ps, "VmRss:\t%8u kB\n", P2K(p->p_vmspace->vm_rssize));
428 PS_ADD(ps, "VmData:\t%8u kB\n", P2K(p->p_vmspace->vm_dsize));
429 PS_ADD(ps, "VmStk:\t%8u kB\n", P2K(p->p_vmspace->vm_ssize));
430 PS_ADD(ps, "VmExe:\t%8u kB\n", P2K(p->p_vmspace->vm_tsize));
431 PS_ADD(ps, "VmLib:\t%8u kB\n", P2K(0)); /* XXX */
432
433 /*
434 * Signal masks
435 *
436 * We support up to 128 signals, while Linux supports 32,
437 * but we only define 32 (the same 32 as Linux, to boot), so
438 * just show the lower 32 bits of each mask. XXX hack.
439 *
440 * NB: on certain platforms (Sparc at least) Linux actually
441 * supports 64 signals, but this code is a long way from
442 * running on anything but i386, so ignore that for now.
443 */
444 PS_ADD(ps, "SigPnd:\t%08x\n", p->p_siglist.__bits[0]);
445 PS_ADD(ps, "SigBlk:\t%08x\n", 0); /* XXX */
446 PS_ADD(ps, "SigIgn:\t%08x\n", p->p_sigignore.__bits[0]);
447 PS_ADD(ps, "SigCgt:\t%08x\n", p->p_sigcatch.__bits[0]);
448
449 /*
450 * Linux also prints the capability masks, but we don't have
451 * capabilities yet, and when we do get them they're likely to
452 * be meaningless to Linux programs, so we lie. XXX
453 */
454 PS_ADD(ps, "CapInh:\t%016x\n", 0);
455 PS_ADD(ps, "CapPrm:\t%016x\n", 0);
456 PS_ADD(ps, "CapEff:\t%016x\n", 0);
457#undef PS_ADD
458
e5a22113 459 return (uiomove_frombuf(psbuf, ps - psbuf, uio));
984263bc
MD
460}
461
09b0da94
MD
462int
463linprocfs_doloadavg(struct proc *curp, struct proc *p,
464 struct pfsnode *pfs, struct uio *uio)
465{
466 char *ps, psbuf[512];
09b0da94
MD
467
468 ps = psbuf;
f8c7a42d 469 ps += ksprintf(ps, "%d.%02d %d.%02d %d.%02d %d/%d %d\n",
09b0da94
MD
470 (int)(averunnable.ldavg[0] / averunnable.fscale),
471 (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100),
472 (int)(averunnable.ldavg[1] / averunnable.fscale),
473 (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100),
474 (int)(averunnable.ldavg[2] / averunnable.fscale),
475 (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100),
476 1, /* number of running tasks */
477 -1, /* number of tasks */
67d32fb2 478 1 /* The last pid, just kidding */
09b0da94 479 );
9bbc4e5c 480 return(uiomove_frombuf(psbuf, ps - psbuf, uio));
09b0da94
MD
481}
482