xref: /minix/minix/servers/mib/kern.c (revision d2532d3d)
1 /* MIB service - kern.c - implementation of the CTL_KERN subtree */
2 
3 #include "mib.h"
4 
5 #include <sys/svrctl.h>
6 #include <minix/sysinfo.h>
7 #include <machine/partition.h>
8 
9 #include "servers/vfs/const.h"
10 #include "servers/vfs/dmap.h"
11 
12 static char hostname[MAXHOSTNAMELEN], domainname[MAXHOSTNAMELEN];
13 
14 /*
15  * Verification for CTL_KERN KERN_SECURELVL.
16  */
17 static int
18 mib_kern_securelvl(struct mib_call * call __unused, struct mib_node * node,
19 	void * ptr, size_t size __unused)
20 {
21 	int v;
22 
23 	memcpy(&v, ptr, sizeof(v));
24 
25 	/*
26 	 * Only ever allow the security level to be increased.  This is a mock
27 	 * implementation.  TODO: implement actual support for security levels.
28 	 */
29 	return (v >= node->node_int);
30 }
31 
32 /*
33  * Implementation of CTL_KERN KERN_CLOCKRATE.
34  */
35 static ssize_t
36 mib_kern_clockrate(struct mib_call * call __unused,
37 	struct mib_node * node __unused, struct mib_oldp * oldp,
38 	struct mib_newp * newp __unused)
39 {
40 	struct clockinfo clockinfo;
41 
42 	memset(&clockinfo, 0, sizeof(clockinfo));
43 
44 	clockinfo.hz = sys_hz();
45 	clockinfo.tick = 1000000 / clockinfo.hz;
46 	clockinfo.profhz = clockinfo.hz;
47 	clockinfo.stathz = clockinfo.hz;
48 
49 	/*
50 	 * Number of microseconds that can be corrected per clock tick through
51 	 * adjtime(2).  The kernel allows correction of one clock tick per
52 	 * clock tick, which means it should be the same as .tick.. I think.
53 	 * TODO: get this from the kernel itself.
54 	 */
55 	clockinfo.tickadj = clockinfo.tick;
56 
57 	return mib_copyout(oldp, 0, &clockinfo, sizeof(clockinfo));
58 }
59 
60 /*
61  * Implementation of CTL_KERN KERN_PROFILING.
62  */
63 static ssize_t
64 mib_kern_profiling(struct mib_call * call __unused,
65 	struct mib_node * node __unused, struct mib_oldp * oldp __unused,
66 	struct mib_newp * newp __unused)
67 {
68 
69 	/* As per sysctl(7).  We have a different profiling API. */
70 	return EOPNOTSUPP;
71 }
72 
73 /*
74  * Implementation of CTL_KERN KERN_HARDCLOCK_TICKS.
75  */
76 static ssize_t
77 mib_kern_hardclock_ticks(struct mib_call * call __unused,
78 	struct mib_node * node __unused, struct mib_oldp * oldp,
79 	struct mib_newp * newp __unused)
80 {
81 	int uptime;
82 
83 	/*
84 	 * The number of hardclock (hardware clock driver) ticks is what we
85 	 * call the number of monotonic clock ticks AKA the uptime clock ticks.
86 	 */
87 	uptime = (int)getticks();
88 
89 	return mib_copyout(oldp, 0, &uptime, sizeof(uptime));
90 }
91 
92 /*
93  * Implementation of CTL_KERN KERN_ROOT_DEVICE.
94  */
95 static ssize_t
96 mib_kern_root_device(struct mib_call * call __unused,
97 	struct mib_node * node __unused, struct mib_oldp * oldp,
98 	struct mib_newp * newp __unused)
99 {
100 	char name[PATH_MAX];
101 	struct sysgetenv sysgetenv;
102 
103 	sysgetenv.key = __UNCONST("rootdevname");
104 	sysgetenv.keylen = strlen(sysgetenv.key) + 1;
105 	sysgetenv.val = name;
106 	sysgetenv.vallen = sizeof(name);
107 
108 	if (svrctl(PMGETPARAM, &sysgetenv) != 0)
109 		return EINVAL;
110 
111 	name[MIN(sysgetenv.vallen, sizeof(name) - 1)] = '\0';
112 
113 	return mib_copyout(oldp, 0, name, strlen(name) + 1);
114 }
115 
116 /*
117  * Implementation of CTL_KERN KERN_CCPU.
118  */
119 static ssize_t
120 mib_kern_ccpu(struct mib_call * call __unused,
121 	struct mib_node * node __unused, struct mib_oldp * oldp,
122 	struct mib_newp * newp __unused)
123 {
124 	int ccpu;
125 
126 	ccpu = (int)cpuavg_getccpu();
127 
128 	return mib_copyout(oldp, 0, &ccpu, sizeof(ccpu));
129 }
130 
131 /*
132  * Implementation of CTL_KERN KERN_CP_TIME.
133  */
134 static ssize_t
135 mib_kern_cp_time(struct mib_call * call, struct mib_node * node __unused,
136 	struct mib_oldp * oldp, struct mib_newp * newp __unused)
137 {
138 	uint64_t ticks[MINIX_CPUSTATES], sum[MINIX_CPUSTATES];
139 	unsigned int cpu;
140 	int i, r, do_sum;
141 
142 	/*
143 	 * If a subnode is provided, it identifies the CPU number for which to
144 	 * return information.  If no subnode is provided, but a size is given
145 	 * that allows returning information for all CPUs, return information
146 	 * for all of them in an array.  If no such size is given either,
147 	 * return a summation of all CPU statistics.  Both we and the kernel
148 	 * are considering the number of configured CPUs (hw.ncpu).
149 	 */
150 	if (call->call_namelen > 1)
151 		return EINVAL;
152 
153 	if (call->call_namelen == 1) {
154 		/* Do not bother saving on this call if oldp is NULL. */
155 		if ((r = sys_getcputicks(ticks, call->call_name[0])) != OK)
156 			return r;
157 
158 		return mib_copyout(oldp, 0, ticks, sizeof(ticks));
159 	}
160 
161 	if (oldp == NULL)
162 		return sizeof(ticks); /* implying a summation request */
163 
164 	do_sum = (mib_getoldlen(oldp) == sizeof(ticks));
165 
166 	if (do_sum)
167 		memset(&sum, 0, sizeof(sum));
168 
169 	for (cpu = 0; cpu < CONFIG_MAX_CPUS; cpu++) {
170 		if ((r = sys_getcputicks(ticks, cpu)) != OK)
171 			return r;
172 
173 		if (do_sum) {
174 			for (i = 0; i < MINIX_CPUSTATES; i++)
175 				sum[i] += ticks[i];
176 		} else {
177 			if ((r = mib_copyout(oldp, cpu * sizeof(ticks), ticks,
178 			    sizeof(ticks))) < 0)
179 				return r;
180 		}
181 	}
182 
183 	if (do_sum)
184 		return mib_copyout(oldp, 0, sum, sizeof(sum));
185 	else
186 		return cpu * sizeof(ticks);
187 }
188 
189 /*
190  * Implementation of CTL_KERN KERN_CONSDEV.
191  */
192 static ssize_t
193 mib_kern_consdev(struct mib_call * call __unused,
194 	struct mib_node * node __unused, struct mib_oldp * oldp,
195 	struct mib_newp * newp __unused)
196 {
197 	dev_t dev;
198 
199 	dev = makedev(TTY_MAJOR, CONS_MINOR);
200 
201 	/* No support for legacy 32-bit requests. */
202 	return mib_copyout(oldp, 0, &dev, sizeof(dev));
203 }
204 
205 /*
206  * Verification for CTL_KERN KERN_FORKFSLEEP.
207  */
208 static int
209 mib_kern_forkfsleep(struct mib_call * call __unused,
210 	struct mib_node * node __unused, void * ptr, size_t size __unused)
211 {
212 	int v;
213 
214 	memcpy(&v, ptr, sizeof(v));
215 
216 	return (v >= 0 && v <= MAXSLP * 1000); /* rules from NetBSD */
217 }
218 
219 /*
220  * Implementation of CTL_KERN KERN_DRIVERS.
221  */
222 static ssize_t
223 mib_kern_drivers(struct mib_call * call __unused,
224 	struct mib_node * node __unused, struct mib_oldp * oldp,
225 	struct mib_newp * newp __unused)
226 {
227 	struct dmap dmap_tab[NR_DEVICES];
228 	struct kinfo_drivers drivers[NR_DEVICES + 1];
229 	unsigned int count;
230 	devmajor_t maj;
231 
232 	/*
233 	 * On MINIX3, we list only drivers that are actually running.
234 	 */
235 
236 	if (getsysinfo(VFS_PROC_NR, SI_DMAP_TAB, dmap_tab,
237 	    sizeof(dmap_tab)) != OK)
238 		return EINVAL;
239 
240 	count = 0;
241 
242 	/*
243 	 * Compatibility hack.  NetBSD userland expects that the name of the
244 	 * PTY driver is "pts".  Add an extra entry for this purpose if needed.
245 	 */
246 	if (dmap_tab[PTY_MAJOR].dmap_driver != NONE &&
247 	    strcmp(dmap_tab[PTY_MAJOR].dmap_label, "pts")) {
248 		if (mib_inrange(oldp, 0)) {
249 			memset(&drivers[0], 0, sizeof(drivers[0]));
250 			strlcpy(drivers[count].d_name, "pts",
251 			    sizeof(drivers[0].d_name));
252 			drivers[count].d_bmajor = -1;
253 			drivers[count].d_cmajor = PTY_MAJOR;
254 		}
255 		count++;
256 	}
257 
258 	for (maj = 0; maj < NR_DEVICES; maj++) {
259 		if (dmap_tab[maj].dmap_driver == NONE)
260 			continue;
261 
262 		if (mib_inrange(oldp, sizeof(drivers[0]) * count)) {
263 			memset(&drivers[count], 0, sizeof(drivers[0]));
264 
265 			strlcpy(drivers[count].d_name,
266 			    dmap_tab[maj].dmap_label,
267 			    sizeof(drivers[0].d_name));
268 
269 			/*
270 			 * We do not know whether the device is a block device,
271 			 * character device, or both.  In any case, a driver
272 			 * has only one major number.
273 			 */
274 			drivers[count].d_bmajor = maj;
275 			drivers[count].d_cmajor = maj;
276 		}
277 		count++;
278 	}
279 
280 	return mib_copyout(oldp, 0, drivers, count * sizeof(drivers[0]));
281 }
282 
283 /*
284  * Implementation of CTL_KERN KERN_BOOTTIME.
285  */
286 static ssize_t
287 mib_kern_boottime(struct mib_call * call __unused,
288 	struct mib_node * node __unused, struct mib_oldp * oldp,
289 	struct mib_newp * newp __unused)
290 {
291 	struct timeval tv;
292 
293 	memset(&tv, 0, sizeof(tv));
294 
295 	if (getuptime(NULL, NULL, &tv.tv_sec) != OK)
296 		return EINVAL;
297 
298 	return mib_copyout(oldp, 0, &tv, sizeof(tv));
299 }
300 
301 /* The CTL_KERN KERN_SYSVIPC nodes. */
302 static struct mib_node mib_kern_ipc_table[] = {
303 /* 1*/	/* KERN_SYSVIPC_INFO: not yet supported */
304 /* 2*/	[KERN_SYSVIPC_MSG]	= MIB_INT(_P | _RO, 0, "sysvmsg", "System V "
305 				    "style message support available"),
306 /* 3*/	[KERN_SYSVIPC_SEM]	= MIB_INT(_P | _RO, 1, "sysvsem", "System V "
307 				    "style semaphore support available"),
308 /* 4*/	[KERN_SYSVIPC_SHM]	= MIB_INT(_P | _RO, 1, "sysvshm", "System V "
309 				    "style shared memory support available"),
310 /* 5*/	/* KERN_SYSVIPC_SHMMAX: not yet supported */
311 /* 6*/	/* KERN_SYSVIPC_SHMMNI: not yet supported */
312 /* 7*/	/* KERN_SYSVIPC_SHMSEG: not yet supported */
313 /* 8*/	/* KERN_SYSVIPC_SHMMAXPGS: not yet supported */
314 /* 9*/	/* KERN_SYSVIPC_SHMUSEPHYS: not yet supported */
315 	/* In addition, NetBSD has a number of dynamic nodes here. */
316 };
317 
318 /* The CTL_KERN nodes. */
319 static struct mib_node mib_kern_table[] = {
320 /* 1*/	[KERN_OSTYPE]		= MIB_STRING(_P | _RO, OS_NAME, "ostype",
321 				    "Operating system type"),
322 /* 2*/	[KERN_OSRELEASE]	= MIB_STRING(_P | _RO, OS_RELEASE, "osrelease",
323 				    "Operating system release"),
324 /* 3*/	[KERN_OSREV]		= MIB_INT(_P | _RO , OS_REV, "osrevision",
325 				    "Operating system revision"),
326 /* 4*/	[KERN_VERSION]		= MIB_STRING(_P | _RO, OS_VERSION, "version",
327 				    "Kernel version"),
328 /* 5*/	[KERN_MAXVNODES]	= MIB_INT(_P | _RO, NR_VNODES, "maxvnodes",
329 				    "Maximum number of vnodes"),
330 /* 6*/	[KERN_MAXPROC]		= MIB_INT(_P | _RO, NR_PROCS, "maxproc",
331 				    "Maximum number of simultaneous "
332 				    "processes"),
333 /* 7*/	[KERN_MAXFILES]		= MIB_INT(_P | _RO, NR_VNODES, "maxfiles",
334 				    "Maximum number of open files"),
335 /* 8*/	[KERN_ARGMAX]		= MIB_INT(_P | _RO, ARG_MAX, "argmax",
336 				    "Maximum number of bytes of arguments to "
337 				    "execve(2)"),
338 /* 9*/	[KERN_SECURELVL]	= MIB_INTV(_P | _RW, -1, mib_kern_securelvl,
339 				    "securelevel", "System security level"),
340 /*10*/	[KERN_HOSTNAME]		= MIB_STRING(_P | _RW, hostname, "hostname",
341 				    "System hostname"),
342 /*11*/	[KERN_HOSTID]		= MIB_INT(_P | _RW | CTLFLAG_HEX, 0, "hostid",
343 				    "System host ID number"),
344 /*12*/	[KERN_CLOCKRATE]	= MIB_FUNC(_P | _RO | CTLTYPE_STRUCT,
345 				    sizeof(struct clockinfo),
346 				    mib_kern_clockrate, "clockrate",
347 				    "Kernel clock rates"),
348 /*13*/	/* KERN_VNODE: not yet implemented */
349 /*14*/	/* KERN_PROC: not yet implemented */
350 /*15*/	/* KERN_FILE: not yet implemented */
351 /*16*/	[KERN_PROF]		= MIB_FUNC(_P | _RO | CTLTYPE_NODE, 0,
352 				    mib_kern_profiling, "profiling",
353 				    "Profiling information (not available)"),
354 /*17*/	[KERN_POSIX1]		= MIB_INT(_P | _RO, _POSIX_VERSION,
355 				    "posix1version", "Version of ISO/IEC 9945 "
356 				    "(POSIX 1003.1) with which the operating "
357 				    "system attempts to comply"),
358 /*18*/	[KERN_NGROUPS]		= MIB_INT(_P | _RO, NGROUPS_MAX, "ngroups",
359 				    "Maximum number of supplemental groups"),
360 /*19*/	[KERN_JOB_CONTROL]	= MIB_INT(_P | _RO, 0, "job_control",
361 				    "Whether job control is available"),
362 /*20*/	[KERN_SAVED_IDS]	= MIB_INT(_P | _RO, 0, "saved_ids",
363 				    "Whether POSIX saved set-group/user ID is "
364 				    "available"),
365 /*21*/	/* KERN_OBOOTTIME: obsolete */
366 /*22*/	[KERN_DOMAINNAME]	= MIB_STRING(_P | _RW, domainname,
367 				    "domainname", "YP domain name"),
368 /*23*/	[KERN_MAXPARTITIONS]	= MIB_INT(_P | _RO, NR_PARTITIONS,
369 				    "maxpartitions", "Maximum number of "
370 				    "partitions allowed per disk"),
371 /*24*/	/* KERN_RAWPARTITION: incompatible with our device node scheme */
372 /*25*/	/* KERN_NTPTIME: not yet supported */
373 /*26*/	/* KERN_TIMEX: not yet supported */
374 /*27*/	/* KERN_AUTONICETIME: not yet supported */
375 /*28*/	/* KERN_AUTONICEVAL: not yet supported */
376 /*29*/	[KERN_RTC_OFFSET]	= MIB_INT(_P | _RW, 0, "rtc_offset", "Offset "
377 				    "of real time clock from UTC in minutes"),
378 /*30*/	[KERN_ROOT_DEVICE]	= MIB_FUNC(_P | _RO | CTLTYPE_STRING, 0,
379 				    mib_kern_root_device, "root_device",
380 				    "Name of the root device"),
381 /*31*/	[KERN_MSGBUFSIZE]	= MIB_INT(_P | _RO, DIAG_BUFSIZE, "msgbufsize",
382 				    "Size of the kernel message buffer"),
383 /*32*/	[KERN_FSYNC]		= MIB_INT(_P | _RO, 1, "fsync", "Whether the "
384 				    "POSIX 1003.1b File Synchronization Option"
385 				    " is available on this system"),
386 /*33*/	/* KERN_OLDSYSVMSG: obsolete */
387 /*34*/	/* KERN_OLDSYSVSEM: obsolete */
388 /*35*/	/* KERN_OLDSYSVSHM: obsolete */
389 /*36*/	/* KERN_OLDSHORTCORENAME: obsolete */
390 /*37*/	[KERN_SYNCHRONIZED_IO]	= MIB_INT(_P | _RO, 0, "synchronized_io",
391 				    "Whether the POSIX 1003.1b Synchronized "
392 				    "I/O Option is available on this system"),
393 /*38*/	[KERN_IOV_MAX]		= MIB_INT(_P | _RO, IOV_MAX, "iov_max",
394 				    "Maximum number of iovec structures per "
395 				    "process"),
396 /*39*/	/* KERN_MBUF: not yet supported */
397 /*40*/	[KERN_MAPPED_FILES]	= MIB_INT(_P | _RO, 1, "mapped_files",
398 				    "Whether the POSIX 1003.1b Memory Mapped "
399 				    "Files Option is available on this "
400 				    "system"),
401 /*41*/	[KERN_MEMLOCK]		= MIB_INT(_P | _RO, 0, "memlock", "Whether "
402 				    "the POSIX 1003.1b Process Memory Locking "
403 				    "Option is available on this system"),
404 /*42*/	[KERN_MEMLOCK_RANGE]	= MIB_INT(_P | _RO, 0, "memlock_range",
405 				    "Whether the POSIX 1003.1b Range Memory "
406 				    "Locking Option is available on this "
407 				    "system"),
408 /*43*/	[KERN_MEMORY_PROTECTION]= MIB_INT(_P | _RO, 0, "memory_protection",
409 				    "Whether the POSIX 1003.1b Memory "
410 				    "Protection Option is available on this "
411 				    "system"),
412 /*44*/	/* KERN_LOGIN_NAME_MAX: not yet supported */
413 /*45*/	/* KERN_DEFCORENAME: obsolete */
414 /*46*/	/* KERN_LOGSIGEXIT: not yet supported */
415 /*47*/	[KERN_PROC2]		= MIB_FUNC(_P | _RO | CTLTYPE_NODE, 0,
416 				    mib_kern_proc2, "proc2",
417 				    "Machine-independent process information"),
418 /*48*/	[KERN_PROC_ARGS]	= MIB_FUNC(_P | _RO | CTLTYPE_NODE, 0,
419 				    mib_kern_proc_args, "proc_args",
420 				    "Process argument information"),
421 /*49*/	[KERN_FSCALE]		= MIB_INT(_P | _RO, FSCALE, "fscale",
422 				    "Kernel fixed-point scale factor"),
423 /*50*/	[KERN_CCPU]		= MIB_FUNC(_P | _RO | CTLTYPE_INT, sizeof(int),
424 				    mib_kern_ccpu, "ccpu",
425 				    "Scheduler exponential decay value"),
426 /*51*/	[KERN_CP_TIME]		= MIB_FUNC(_P | _RO | CTLTYPE_NODE, 0,
427 				    mib_kern_cp_time, "cp_time", "Clock ticks "
428 				    "spent in different CPU states"),
429 /*52*/	/* KERN_OLDSYSVIPC_INFO: obsolete */
430 /*53*/	/* KERN_MSGBUF: not yet supported */
431 /*54*/	[KERN_CONSDEV]		= MIB_FUNC(_P | _RO | CTLTYPE_STRUCT,
432 				    sizeof(dev_t), mib_kern_consdev, "consdev",
433 				    "Console device"),
434 /*55*/	[KERN_MAXPTYS]		= MIB_INT(_P | _RO, NR_PTYS, "maxptys",
435 				    "Maximum number of pseudo-ttys"),
436 /*56*/	/* KERN_PIPE: not yet supported */
437 /*57*/	[KERN_MAXPHYS]		= MIB_INT(_P | _RO, 4*1024*1024, "maxphys",
438 				    "Maximum raw I/O transfer size"),
439 				    /* 4MB is the upper limit for AHCI */
440 /*58*/	/* KERN_SBMAX: not yet supported */
441 /*59*/	/* KERN_TKSTAT: not yet supported */
442 /*60*/	[KERN_MONOTONIC_CLOCK]	= MIB_INT(_P | _RO, _POSIX_MONOTONIC_CLOCK,
443 				    "monotonic_clock",
444 				    "Implementation version of the POSIX "
445 				    "1003.1b Monotonic Clock Option"),
446 /*61*/	/* KERN_URND: not yet supported */
447 /*62*/	/* KERN_LABELSECTOR: not yet supported */
448 /*63*/	/* KERN_LABELOFFSET: not yet supported */
449 /*64*/	[KERN_LWP]		= MIB_FUNC(_P | _RO | CTLTYPE_NODE, 0,
450 				    mib_kern_lwp, "lwp",
451 				    "System-wide LWP information"),
452 /*65*/	[KERN_FORKFSLEEP]	= MIB_INTV(_P | _RW, 0, mib_kern_forkfsleep,
453 				    "forkfsleep", "Milliseconds to sleep on "
454 				    "fork failure due to process limits"),
455 /*66*/	/* KERN_POSIX_THREADS: not yet supported */
456 /*67*/	/* KERN_POSIX_SEMAPHORES: not yet supported */
457 /*68*/	/* KERN_POSIX_BARRIERS: not yet supported */
458 /*69*/	/* KERN_POSIX_TIMERS: not yet supported */
459 /*70*/	/* KERN_POSIX_SPIN_LOCKS: not yet supported */
460 /*71*/	/* KERN_POSIX_READER_WRITER_LOCKS: not yet supported */
461 /*72*/	[KERN_DUMP_ON_PANIC]	= MIB_INT(_P | _RO, 0, "dump_on_panic",
462 				    "Perform a crash dump on system panic"),
463 /*73*/	/* KERN_SOMAXKVA: not yet supported */
464 /*74*/	/* KERN_ROOT_PARTITION: incompatible with our device node scheme */
465 /*75*/	[KERN_DRIVERS]		= MIB_FUNC(_P | _RO | CTLTYPE_STRUCT, 0,
466 				    mib_kern_drivers, "drivers",
467 				    "List of all drivers with block and "
468 				    "character device numbers"),
469 /*76*/	/* KERN_BUF: not yet supported */
470 /*77*/	/* KERN_FILE2: not yet supported */
471 /*78*/	/* KERN_VERIEXEC: not yet supported */
472 /*79*/	/* KERN_CP_ID: not yet supported */
473 /*80*/	[KERN_HARDCLOCK_TICKS]	= MIB_FUNC(_P | _RO | CTLFLAG_UNSIGNED |
474 				    CTLTYPE_INT, sizeof(int),
475 				    mib_kern_hardclock_ticks,
476 				    "hardclock_ticks",
477 				    "Number of hardclock ticks"),
478 /*81*/	/* KERN_ARND: not yet supported */
479 /*82*/	[KERN_SYSVIPC]		= MIB_NODE(_P | _RO, mib_kern_ipc_table, "ipc",
480 				    "SysV IPC options"),
481 /*83*/	[KERN_BOOTTIME]		= MIB_FUNC(_P | _RO | CTLTYPE_STRUCT,
482 				    sizeof(struct timeval), mib_kern_boottime,
483 				    "boottime", "System boot time"),
484 /*84*/	/* KERN_EVCNT: not yet supported */
485 };
486 
487 /*
488  * Initialize the CTL_KERN subtree.
489  */
490 void
491 mib_kern_init(struct mib_node * node)
492 {
493 
494 	MIB_INIT_ENODE(node, mib_kern_table);
495 }
496