1 /* MIB service - kern.c - implementation of the CTL_KERN subtree */
5 #include <sys/svrctl.h>
6 #include <minix/sysinfo.h>
7 #include <machine/partition.h>
9 #include "servers/vfs/const.h"
10 #include "servers/vfs/dmap.h"
12 static char hostname
[MAXHOSTNAMELEN
], domainname
[MAXHOSTNAMELEN
];
15 * Verification for CTL_KERN KERN_SECURELVL.
18 mib_kern_securelvl(struct mib_call
* call __unused
, struct mib_node
* node
,
19 void * ptr
, size_t size __unused
)
23 memcpy(&v
, ptr
, sizeof(v
));
26 * Only ever allow the security level to be increased. This is a mock
27 * implementation. TODO: implement actual support for security levels.
29 return (v
>= node
->node_int
);
33 * Implementation of CTL_KERN KERN_CLOCKRATE.
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
)
40 struct clockinfo clockinfo
;
42 memset(&clockinfo
, 0, sizeof(clockinfo
));
44 clockinfo
.hz
= sys_hz();
45 clockinfo
.tick
= 1000000 / clockinfo
.hz
;
46 clockinfo
.profhz
= clockinfo
.hz
;
47 clockinfo
.stathz
= clockinfo
.hz
;
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.
55 clockinfo
.tickadj
= clockinfo
.tick
;
57 return mib_copyout(oldp
, 0, &clockinfo
, sizeof(clockinfo
));
61 * Implementation of CTL_KERN KERN_PROFILING.
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
)
69 /* As per sysctl(7). We have a different profiling API. */
74 * Implementation of CTL_KERN KERN_HARDCLOCK_TICKS.
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
)
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.
87 uptime
= (int)getticks();
89 return mib_copyout(oldp
, 0, &uptime
, sizeof(uptime
));
93 * Implementation of CTL_KERN KERN_ROOT_DEVICE.
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
)
101 struct sysgetenv sysgetenv
;
103 sysgetenv
.key
= __UNCONST("rootdevname");
104 sysgetenv
.keylen
= strlen(sysgetenv
.key
) + 1;
105 sysgetenv
.val
= name
;
106 sysgetenv
.vallen
= sizeof(name
);
108 if (svrctl(PMGETPARAM
, &sysgetenv
) != 0)
111 name
[MIN(sysgetenv
.vallen
, sizeof(name
) - 1)] = '\0';
113 return mib_copyout(oldp
, 0, name
, strlen(name
) + 1);
117 * Implementation of CTL_KERN KERN_CCPU.
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
)
126 ccpu
= (int)cpuavg_getccpu();
128 return mib_copyout(oldp
, 0, &ccpu
, sizeof(ccpu
));
132 * Implementation of CTL_KERN KERN_CP_TIME.
135 mib_kern_cp_time(struct mib_call
* call
, struct mib_node
* node __unused
,
136 struct mib_oldp
* oldp
, struct mib_newp
* newp __unused
)
138 uint64_t ticks
[MINIX_CPUSTATES
], sum
[MINIX_CPUSTATES
];
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).
150 if (call
->call_namelen
> 1)
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
)
158 return mib_copyout(oldp
, 0, ticks
, sizeof(ticks
));
162 return sizeof(ticks
); /* implying a summation request */
164 do_sum
= (mib_getoldlen(oldp
) == sizeof(ticks
));
167 memset(&sum
, 0, sizeof(sum
));
169 for (cpu
= 0; cpu
< CONFIG_MAX_CPUS
; cpu
++) {
170 if ((r
= sys_getcputicks(ticks
, cpu
)) != OK
)
174 for (i
= 0; i
< MINIX_CPUSTATES
; i
++)
177 if ((r
= mib_copyout(oldp
, cpu
* sizeof(ticks
), ticks
,
184 return mib_copyout(oldp
, 0, sum
, sizeof(sum
));
186 return cpu
* sizeof(ticks
);
190 * Implementation of CTL_KERN KERN_CONSDEV.
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
)
199 dev
= makedev(TTY_MAJOR
, CONS_MINOR
);
201 /* No support for legacy 32-bit requests. */
202 return mib_copyout(oldp
, 0, &dev
, sizeof(dev
));
206 * Verification for CTL_KERN KERN_FORKFSLEEP.
209 mib_kern_forkfsleep(struct mib_call
* call __unused
,
210 struct mib_node
* node __unused
, void * ptr
, size_t size __unused
)
214 memcpy(&v
, ptr
, sizeof(v
));
216 return (v
>= 0 && v
<= MAXSLP
* 1000); /* rules from NetBSD */
220 * Implementation of CTL_KERN KERN_DRIVERS.
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
)
227 struct dmap dmap_tab
[NR_DEVICES
];
228 struct kinfo_drivers drivers
[NR_DEVICES
+ 1];
233 * On MINIX3, we list only drivers that are actually running.
236 if (getsysinfo(VFS_PROC_NR
, SI_DMAP_TAB
, dmap_tab
,
237 sizeof(dmap_tab
)) != OK
)
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.
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
;
258 for (maj
= 0; maj
< NR_DEVICES
; maj
++) {
259 if (dmap_tab
[maj
].dmap_driver
== NONE
)
262 if (mib_inrange(oldp
, sizeof(drivers
[0]) * count
)) {
263 memset(&drivers
[count
], 0, sizeof(drivers
[0]));
265 strlcpy(drivers
[count
].d_name
,
266 dmap_tab
[maj
].dmap_label
,
267 sizeof(drivers
[0].d_name
));
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.
274 drivers
[count
].d_bmajor
= maj
;
275 drivers
[count
].d_cmajor
= maj
;
280 return mib_copyout(oldp
, 0, drivers
, count
* sizeof(drivers
[0]));
284 * Implementation of CTL_KERN KERN_BOOTTIME.
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
)
293 memset(&tv
, 0, sizeof(tv
));
295 if (getuptime(NULL
, NULL
, &tv
.tv_sec
) != OK
)
298 return mib_copyout(oldp
, 0, &tv
, sizeof(tv
));
302 * Mock implementation of CTL_KERN KERN_SYSVIPC KERN_SYSVIPC_INFO. Normally,
303 * the IPC service overrides the entire "kern.ipc" subtree. Therefore, this
304 * function will only ever be called when the IPC service is *not* running.
307 mib_kern_ipc_info(struct mib_call
* call
, struct mib_node
* node __unused
,
308 struct mib_oldp
* oldp __unused
, struct mib_newp
* newp __unused
)
311 /* The caller must always specify the resouce type (sem/shm/msg). */
312 if (call
->call_namelen
!= 1)
318 /* The CTL_KERN KERN_SYSVIPC nodes, when not overridden by the IPC service. */
319 static struct mib_node mib_kern_ipc_table
[] = {
320 /* 1*/ [KERN_SYSVIPC_INFO
] = MIB_FUNC(_P
| _RO
| CTLTYPE_NODE
, 0,
321 mib_kern_ipc_info
, "sysvipc_info",
322 "System V style IPC information"),
323 /* 2*/ [KERN_SYSVIPC_MSG
] = MIB_INT(_P
| _RO
, 0, "sysvmsg", "System V "
324 "style message support available"),
325 /* 3*/ [KERN_SYSVIPC_SEM
] = MIB_INT(_P
| _RO
, 0, "sysvsem", "System V "
326 "style semaphore support available"),
327 /* 4*/ [KERN_SYSVIPC_SHM
] = MIB_INT(_P
| _RO
, 0, "sysvshm", "System V "
328 "style shared memory support available"),
331 /* The CTL_KERN nodes. */
332 static struct mib_node mib_kern_table
[] = {
333 /* 1*/ [KERN_OSTYPE
] = MIB_STRING(_P
| _RO
, OS_NAME
, "ostype",
334 "Operating system type"),
335 /* 2*/ [KERN_OSRELEASE
] = MIB_STRING(_P
| _RO
, OS_RELEASE
, "osrelease",
336 "Operating system release"),
337 /* 3*/ [KERN_OSREV
] = MIB_INT(_P
| _RO
, OS_REV
, "osrevision",
338 "Operating system revision"),
339 /* 4*/ [KERN_VERSION
] = MIB_STRING(_P
| _RO
, OS_VERSION
, "version",
341 /* 5*/ [KERN_MAXVNODES
] = MIB_INT(_P
| _RO
, NR_VNODES
, "maxvnodes",
342 "Maximum number of vnodes"),
343 /* 6*/ [KERN_MAXPROC
] = MIB_INT(_P
| _RO
, NR_PROCS
, "maxproc",
344 "Maximum number of simultaneous "
346 /* 7*/ [KERN_MAXFILES
] = MIB_INT(_P
| _RO
, NR_VNODES
, "maxfiles",
347 "Maximum number of open files"),
348 /* 8*/ [KERN_ARGMAX
] = MIB_INT(_P
| _RO
, ARG_MAX
, "argmax",
349 "Maximum number of bytes of arguments to "
351 /* 9*/ [KERN_SECURELVL
] = MIB_INTV(_P
| _RW
, -1, mib_kern_securelvl
,
352 "securelevel", "System security level"),
353 /*10*/ [KERN_HOSTNAME
] = MIB_STRING(_P
| _RW
, hostname
, "hostname",
355 /*11*/ [KERN_HOSTID
] = MIB_INT(_P
| _RW
| CTLFLAG_HEX
, 0, "hostid",
356 "System host ID number"),
357 /*12*/ [KERN_CLOCKRATE
] = MIB_FUNC(_P
| _RO
| CTLTYPE_STRUCT
,
358 sizeof(struct clockinfo
),
359 mib_kern_clockrate
, "clockrate",
360 "Kernel clock rates"),
361 /*13*/ /* KERN_VNODE: not yet implemented */
362 /*14*/ /* KERN_PROC: not yet implemented */
363 /*15*/ /* KERN_FILE: not yet implemented */
364 /*16*/ [KERN_PROF
] = MIB_FUNC(_P
| _RO
| CTLTYPE_NODE
, 0,
365 mib_kern_profiling
, "profiling",
366 "Profiling information (not available)"),
367 /*17*/ [KERN_POSIX1
] = MIB_INT(_P
| _RO
, _POSIX_VERSION
,
368 "posix1version", "Version of ISO/IEC 9945 "
369 "(POSIX 1003.1) with which the operating "
370 "system attempts to comply"),
371 /*18*/ [KERN_NGROUPS
] = MIB_INT(_P
| _RO
, NGROUPS_MAX
, "ngroups",
372 "Maximum number of supplemental groups"),
373 /*19*/ [KERN_JOB_CONTROL
] = MIB_INT(_P
| _RO
, 0, "job_control",
374 "Whether job control is available"),
375 /*20*/ [KERN_SAVED_IDS
] = MIB_INT(_P
| _RO
, 0, "saved_ids",
376 "Whether POSIX saved set-group/user ID is "
378 /*21*/ /* KERN_OBOOTTIME: obsolete */
379 /*22*/ [KERN_DOMAINNAME
] = MIB_STRING(_P
| _RW
, domainname
,
380 "domainname", "YP domain name"),
381 /*23*/ [KERN_MAXPARTITIONS
] = MIB_INT(_P
| _RO
, NR_PARTITIONS
,
382 "maxpartitions", "Maximum number of "
383 "partitions allowed per disk"),
384 /*24*/ /* KERN_RAWPARTITION: incompatible with our device node scheme */
385 /*25*/ /* KERN_NTPTIME: not yet supported */
386 /*26*/ /* KERN_TIMEX: not yet supported */
387 /*27*/ /* KERN_AUTONICETIME: not yet supported */
388 /*28*/ /* KERN_AUTONICEVAL: not yet supported */
389 /*29*/ [KERN_RTC_OFFSET
] = MIB_INT(_P
| _RW
, 0, "rtc_offset", "Offset "
390 "of real time clock from UTC in minutes"),
391 /*30*/ [KERN_ROOT_DEVICE
] = MIB_FUNC(_P
| _RO
| CTLTYPE_STRING
, 0,
392 mib_kern_root_device
, "root_device",
393 "Name of the root device"),
394 /*31*/ [KERN_MSGBUFSIZE
] = MIB_INT(_P
| _RO
, DIAG_BUFSIZE
, "msgbufsize",
395 "Size of the kernel message buffer"),
396 /*32*/ [KERN_FSYNC
] = MIB_INT(_P
| _RO
, 1, "fsync", "Whether the "
397 "POSIX 1003.1b File Synchronization Option"
398 " is available on this system"),
399 /*33*/ /* KERN_OLDSYSVMSG: obsolete */
400 /*34*/ /* KERN_OLDSYSVSEM: obsolete */
401 /*35*/ /* KERN_OLDSYSVSHM: obsolete */
402 /*36*/ /* KERN_OLDSHORTCORENAME: obsolete */
403 /*37*/ [KERN_SYNCHRONIZED_IO
] = MIB_INT(_P
| _RO
, 0, "synchronized_io",
404 "Whether the POSIX 1003.1b Synchronized "
405 "I/O Option is available on this system"),
406 /*38*/ [KERN_IOV_MAX
] = MIB_INT(_P
| _RO
, IOV_MAX
, "iov_max",
407 "Maximum number of iovec structures per "
409 /*39*/ /* KERN_MBUF: not yet supported */
410 /*40*/ [KERN_MAPPED_FILES
] = MIB_INT(_P
| _RO
, 1, "mapped_files",
411 "Whether the POSIX 1003.1b Memory Mapped "
412 "Files Option is available on this "
414 /*41*/ [KERN_MEMLOCK
] = MIB_INT(_P
| _RO
, 0, "memlock", "Whether "
415 "the POSIX 1003.1b Process Memory Locking "
416 "Option is available on this system"),
417 /*42*/ [KERN_MEMLOCK_RANGE
] = MIB_INT(_P
| _RO
, 0, "memlock_range",
418 "Whether the POSIX 1003.1b Range Memory "
419 "Locking Option is available on this "
421 /*43*/ [KERN_MEMORY_PROTECTION
]= MIB_INT(_P
| _RO
, 0, "memory_protection",
422 "Whether the POSIX 1003.1b Memory "
423 "Protection Option is available on this "
425 /*44*/ /* KERN_LOGIN_NAME_MAX: not yet supported */
426 /*45*/ /* KERN_DEFCORENAME: obsolete */
427 /*46*/ /* KERN_LOGSIGEXIT: not yet supported */
428 /*47*/ [KERN_PROC2
] = MIB_FUNC(_P
| _RO
| CTLTYPE_NODE
, 0,
429 mib_kern_proc2
, "proc2",
430 "Machine-independent process information"),
431 /*48*/ [KERN_PROC_ARGS
] = MIB_FUNC(_P
| _RO
| CTLTYPE_NODE
, 0,
432 mib_kern_proc_args
, "proc_args",
433 "Process argument information"),
434 /*49*/ [KERN_FSCALE
] = MIB_INT(_P
| _RO
, FSCALE
, "fscale",
435 "Kernel fixed-point scale factor"),
436 /*50*/ [KERN_CCPU
] = MIB_FUNC(_P
| _RO
| CTLTYPE_INT
, sizeof(int),
437 mib_kern_ccpu
, "ccpu",
438 "Scheduler exponential decay value"),
439 /*51*/ [KERN_CP_TIME
] = MIB_FUNC(_P
| _RO
| CTLTYPE_NODE
, 0,
440 mib_kern_cp_time
, "cp_time", "Clock ticks "
441 "spent in different CPU states"),
442 /*52*/ /* KERN_OLDSYSVIPC_INFO: obsolete */
443 /*53*/ /* KERN_MSGBUF: not yet supported */
444 /*54*/ [KERN_CONSDEV
] = MIB_FUNC(_P
| _RO
| CTLTYPE_STRUCT
,
445 sizeof(dev_t
), mib_kern_consdev
, "consdev",
447 /*55*/ [KERN_MAXPTYS
] = MIB_INT(_P
| _RO
, NR_PTYS
, "maxptys",
448 "Maximum number of pseudo-ttys"),
449 /*56*/ /* KERN_PIPE: not yet supported */
450 /*57*/ [KERN_MAXPHYS
] = MIB_INT(_P
| _RO
, 4*1024*1024, "maxphys",
451 "Maximum raw I/O transfer size"),
452 /* 4MB is the upper limit for AHCI */
453 /*58*/ /* KERN_SBMAX: not yet supported */
454 /*59*/ /* KERN_TKSTAT: not yet supported */
455 /*60*/ [KERN_MONOTONIC_CLOCK
] = MIB_INT(_P
| _RO
, _POSIX_MONOTONIC_CLOCK
,
457 "Implementation version of the POSIX "
458 "1003.1b Monotonic Clock Option"),
459 /*61*/ /* KERN_URND: not yet supported */
460 /*62*/ /* KERN_LABELSECTOR: not yet supported */
461 /*63*/ /* KERN_LABELOFFSET: not yet supported */
462 /*64*/ [KERN_LWP
] = MIB_FUNC(_P
| _RO
| CTLTYPE_NODE
, 0,
464 "System-wide LWP information"),
465 /*65*/ [KERN_FORKFSLEEP
] = MIB_INTV(_P
| _RW
, 0, mib_kern_forkfsleep
,
466 "forkfsleep", "Milliseconds to sleep on "
467 "fork failure due to process limits"),
468 /*66*/ /* KERN_POSIX_THREADS: not yet supported */
469 /*67*/ /* KERN_POSIX_SEMAPHORES: not yet supported */
470 /*68*/ /* KERN_POSIX_BARRIERS: not yet supported */
471 /*69*/ /* KERN_POSIX_TIMERS: not yet supported */
472 /*70*/ /* KERN_POSIX_SPIN_LOCKS: not yet supported */
473 /*71*/ /* KERN_POSIX_READER_WRITER_LOCKS: not yet supported */
474 /*72*/ [KERN_DUMP_ON_PANIC
] = MIB_INT(_P
| _RO
, 0, "dump_on_panic",
475 "Perform a crash dump on system panic"),
476 /*73*/ /* KERN_SOMAXKVA: not yet supported */
477 /*74*/ /* KERN_ROOT_PARTITION: incompatible with our device node scheme */
478 /*75*/ [KERN_DRIVERS
] = MIB_FUNC(_P
| _RO
| CTLTYPE_STRUCT
, 0,
479 mib_kern_drivers
, "drivers",
480 "List of all drivers with block and "
481 "character device numbers"),
482 /*76*/ /* KERN_BUF: not yet supported */
483 /*77*/ /* KERN_FILE2: not yet supported */
484 /*78*/ /* KERN_VERIEXEC: not yet supported */
485 /*79*/ /* KERN_CP_ID: not yet supported */
486 /*80*/ [KERN_HARDCLOCK_TICKS
] = MIB_FUNC(_P
| _RO
| CTLFLAG_UNSIGNED
|
487 CTLTYPE_INT
, sizeof(int),
488 mib_kern_hardclock_ticks
,
490 "Number of hardclock ticks"),
491 /*81*/ /* KERN_ARND: not yet supported */
492 /*82*/ [KERN_SYSVIPC
] = MIB_NODE(_P
| _RO
, mib_kern_ipc_table
, "ipc",
494 /*83*/ [KERN_BOOTTIME
] = MIB_FUNC(_P
| _RO
| CTLTYPE_STRUCT
,
495 sizeof(struct timeval
), mib_kern_boottime
,
496 "boottime", "System boot time"),
497 /*84*/ /* KERN_EVCNT: not yet supported */
501 * Initialize the CTL_KERN subtree.
504 mib_kern_init(struct mib_node
* node
)
507 MIB_INIT_ENODE(node
, mib_kern_table
);