xref: /freebsd/sys/compat/linprocfs/linprocfs.c (revision ddc0b9925df4b1063012d55019c7f5e18219a8dc)
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/systm.h>
52 #include <sys/tty.h>
53 #include <sys/vnode.h>
54 
55 #include <vm/vm.h>
56 #include <vm/pmap.h>
57 #include <vm/vm_param.h>
58 #include <vm/vm_object.h>
59 #include <vm/swap_pager.h>
60 #include <sys/vmmeter.h>
61 #include <sys/exec.h>
62 
63 #include <machine/md_var.h>
64 #include <machine/cputypes.h>
65 
66 #include <i386/linux/linprocfs/linprocfs.h>
67 
68 #define T2J(x) (((x) * 100) / stathz)
69 #define T2S(x) ((x) / stathz)
70 
71 int
72 linprocfs_domeminfo(curp, p, pfs, uio)
73 	struct proc *curp;
74 	struct proc *p;
75 	struct pfsnode *pfs;
76 	struct uio *uio;
77 {
78 	char *ps;
79 	int xlen;
80 	char psbuf[512];		/* XXX - conservative */
81 	unsigned long memtotal;		/* total memory in bytes */
82 	unsigned long memused;		/* used memory in bytes */
83 	unsigned long memfree;		/* free memory in bytes */
84 	unsigned long memshared;	/* shared memory ??? */
85 	unsigned long buffers, cached;	/* buffer / cache memory ??? */
86 	unsigned long swaptotal;	/* total swap space in bytes */
87 	unsigned long swapused;		/* used swap space in bytes */
88 	unsigned long swapfree;		/* free swap space in bytes */
89 	vm_object_t object;
90 
91 	if (uio->uio_rw != UIO_READ)
92 		return (EOPNOTSUPP);
93 
94 	memtotal = physmem * PAGE_SIZE;
95 	/*
96 	 * The correct thing here would be:
97 	 *
98 	memfree = cnt.v_free_count * PAGE_SIZE;
99 	memused = memtotal - memfree;
100 	 *
101 	 * but it might mislead linux binaries into thinking there
102 	 * is very little memory left, so we cheat and tell them that
103 	 * all memory that isn't wired down is free.
104 	 */
105 	memused = cnt.v_wire_count * PAGE_SIZE;
106 	memfree = memtotal - memused;
107 	if (swapblist == NULL) {
108 		swaptotal = 0;
109 		swapfree = 0;
110 	} else {
111 		swaptotal = swapblist->bl_blocks * 1024; /* XXX why 1024? */
112 		swapfree = swapblist->bl_root->u.bmu_avail * PAGE_SIZE;
113 	}
114 	swapused = swaptotal - swapfree;
115 	memshared = 0;
116 	for (object = TAILQ_FIRST(&vm_object_list); object != NULL;
117 	    object = TAILQ_NEXT(object, object_list))
118 		if (object->shadow_count > 1)
119 			memshared += object->resident_page_count;
120 	memshared *= PAGE_SIZE;
121 	/*
122 	 * We'd love to be able to write:
123 	 *
124 	buffers = bufspace;
125 	 *
126 	 * but bufspace is internal to vfs_bio.c and we don't feel
127 	 * like unstaticizing it just for linprocfs's sake.
128 	 */
129 	buffers = 0;
130 	cached = cnt.v_cache_count * PAGE_SIZE;
131 
132 	ps = psbuf;
133 	ps += sprintf(ps,
134 		"        total:    used:    free:  shared: buffers:  cached:\n"
135 		"Mem:  %lu %lu %lu %lu %lu %lu\n"
136 		"Swap: %lu %lu %lu\n"
137 		"MemTotal: %9lu kB\n"
138 		"MemFree:  %9lu kB\n"
139 		"MemShared:%9lu kB\n"
140 		"Buffers:  %9lu kB\n"
141 		"Cached:   %9lu kB\n"
142 		"SwapTotal:%9lu kB\n"
143 		"SwapFree: %9lu kB\n",
144 		memtotal, memused, memfree, memshared, buffers, cached,
145 		swaptotal, swapused, swapfree,
146 		memtotal >> 10, memfree >> 10,
147 		memshared >> 10, buffers >> 10, cached >> 10,
148 		swaptotal >> 10, swapfree >> 10);
149 
150 	xlen = ps - psbuf;
151 	xlen -= uio->uio_offset;
152 	ps = psbuf + uio->uio_offset;
153 	xlen = imin(xlen, uio->uio_resid);
154 	return (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
155 }
156 
157 int
158 linprocfs_docpuinfo(curp, p, pfs, uio)
159 	struct proc *curp;
160 	struct proc *p;
161 	struct pfsnode *pfs;
162 	struct uio *uio;
163 {
164 	char *ps;
165 	int xlen;
166 	char psbuf[512];		/* XXX - conservative */
167 	char *class;
168 #if 0
169 	extern char *cpu_model;		/* Yuck */
170 #endif
171 
172 	if (uio->uio_rw != UIO_READ)
173 		return (EOPNOTSUPP);
174 
175 	switch (cpu_class) {
176 	case CPUCLASS_286:
177 		class = "286";
178 		break;
179 	case CPUCLASS_386:
180 		class = "386";
181 		break;
182 	case CPUCLASS_486:
183 		class = "486";
184 		break;
185 	case CPUCLASS_586:
186 		class = "586";
187 		break;
188 	case CPUCLASS_686:
189 		class = "686";
190 		break;
191 	default:
192 		class = "unknown";
193 		break;
194 	}
195 
196 	ps = psbuf;
197 	ps += sprintf(ps,
198 			"processor       : %d\n"
199 			"cpu             : %.3s\n"
200 			"model           : %.20s\n"
201 			"vendor_id       : %.20s\n"
202 			"stepping        : %d\n",
203 			0, class, "unknown", cpu_vendor, cpu_id);
204 
205 	xlen = ps - psbuf;
206 	xlen -= uio->uio_offset;
207 	ps = psbuf + uio->uio_offset;
208 	xlen = imin(xlen, uio->uio_resid);
209 	return (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
210 }
211 
212 int
213 linprocfs_dostat(curp, p, pfs, uio)
214 	struct proc *curp;
215 	struct proc *p;
216 	struct pfsnode *pfs;
217 	struct uio *uio;
218 {
219         char *ps;
220 	char psbuf[512];
221 	int xlen;
222 
223 	ps = psbuf;
224 	ps += sprintf(ps,
225 		      "cpu %ld %ld %ld %ld\n"
226 		      "disk 0 0 0 0\n"
227 		      "page %u %u\n"
228 		      "swap %u %u\n"
229 		      "intr %u\n"
230 		      "ctxt %u\n"
231 		      "btime %ld\n",
232 		      T2J(cp_time[CP_USER]),
233 		      T2J(cp_time[CP_NICE]),
234 		      T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/),
235 		      T2J(cp_time[CP_IDLE]),
236 		      cnt.v_vnodepgsin,
237 		      cnt.v_vnodepgsout,
238 		      cnt.v_swappgsin,
239 		      cnt.v_swappgsout,
240 		      cnt.v_intr,
241 		      cnt.v_swtch,
242 		      boottime.tv_sec);
243 	xlen = ps - psbuf;
244 	xlen -= uio->uio_offset;
245 	ps = psbuf + uio->uio_offset;
246 	xlen = imin(xlen, uio->uio_resid);
247 	return (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
248 }
249 
250 int
251 linprocfs_douptime(curp, p, pfs, uio)
252 	struct proc *curp;
253 	struct proc *p;
254 	struct pfsnode *pfs;
255 	struct uio *uio;
256 {
257 	char *ps;
258 	int xlen;
259 	char psbuf[64];
260 	struct timeval tv;
261 	long ip, fp;
262 
263 	getmicrouptime(&tv);
264 	ps = psbuf;
265 	ps += sprintf(ps, "%ld.%02ld %ld.%02ld\n",
266 		      tv.tv_sec, tv.tv_usec / 10000,
267 		      T2S(cp_time[CP_IDLE]), T2J(cp_time[CP_IDLE]) % 100);
268 	xlen = ps - psbuf;
269 	xlen -= uio->uio_offset;
270 	ps = psbuf + uio->uio_offset;
271 	xlen = imin(xlen, uio->uio_resid);
272 	return (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
273 }
274 
275 int
276 linprocfs_doversion(curp, p, pfs, uio)
277 	struct proc *curp;
278 	struct proc *p;
279 	struct pfsnode *pfs;
280 	struct uio *uio;
281 {
282         char *ps;
283 	int xlen;
284 
285 	ps = version; /* XXX not entirely correct */
286 	for (xlen = 0; ps[xlen] != '\n'; ++xlen)
287 		/* nothing */ ;
288 	++xlen;
289 	xlen -= uio->uio_offset;
290 	ps += uio->uio_offset;
291 	xlen = imin(xlen, uio->uio_resid);
292 	return (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
293 }
294 
295