xref: /freebsd/sys/kern/p1003_1b.c (revision 8451d0dd78c0a9c0383485b18aba9f081a9db8bb)
160727d8bSWarner Losh /*-
28a6472b7SPeter Dufault  * Copyright (c) 1996, 1997, 1998
38a6472b7SPeter Dufault  *	HD Associates, Inc.  All rights reserved.
48a6472b7SPeter Dufault  *
58a6472b7SPeter Dufault  * Redistribution and use in source and binary forms, with or without
68a6472b7SPeter Dufault  * modification, are permitted provided that the following conditions
78a6472b7SPeter Dufault  * are met:
88a6472b7SPeter Dufault  * 1. Redistributions of source code must retain the above copyright
98a6472b7SPeter Dufault  *    notice, this list of conditions and the following disclaimer.
108a6472b7SPeter Dufault  * 2. Redistributions in binary form must reproduce the above copyright
118a6472b7SPeter Dufault  *    notice, this list of conditions and the following disclaimer in the
128a6472b7SPeter Dufault  *    documentation and/or other materials provided with the distribution.
138a6472b7SPeter Dufault  * 3. All advertising materials mentioning features or use of this software
148a6472b7SPeter Dufault  *    must display the following acknowledgement:
158a6472b7SPeter Dufault  *	This product includes software developed by HD Associates, Inc
168a6472b7SPeter Dufault  * 4. Neither the name of the author nor the names of any co-contributors
178a6472b7SPeter Dufault  *    may be used to endorse or promote products derived from this software
188a6472b7SPeter Dufault  *    without specific prior written permission.
198a6472b7SPeter Dufault  *
208a6472b7SPeter Dufault  * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES AND CONTRIBUTORS ``AS IS'' AND
218a6472b7SPeter Dufault  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
228a6472b7SPeter Dufault  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
238a6472b7SPeter Dufault  * ARE DISCLAIMED.  IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE
248a6472b7SPeter Dufault  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
258a6472b7SPeter Dufault  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
268a6472b7SPeter Dufault  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
278a6472b7SPeter Dufault  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
288a6472b7SPeter Dufault  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
298a6472b7SPeter Dufault  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
308a6472b7SPeter Dufault  * SUCH DAMAGE.
318a6472b7SPeter Dufault  */
328a6472b7SPeter Dufault 
338a6472b7SPeter Dufault /* p1003_1b: Real Time common code.
348a6472b7SPeter Dufault  */
358a6472b7SPeter Dufault 
36f4636c59SDavid E. O'Brien #include <sys/cdefs.h>
37f4636c59SDavid E. O'Brien __FBSDID("$FreeBSD$");
38f4636c59SDavid E. O'Brien 
39b565fb9eSAlfred Perlstein #include "opt_posix.h"
40b565fb9eSAlfred Perlstein 
418a6472b7SPeter Dufault #include <sys/param.h>
428a6472b7SPeter Dufault #include <sys/systm.h>
438a6472b7SPeter Dufault #include <sys/kernel.h>
44fb919e4dSMark Murray #include <sys/lock.h>
458a6472b7SPeter Dufault #include <sys/module.h>
46fb919e4dSMark Murray #include <sys/mutex.h>
47acd3428bSRobert Watson #include <sys/priv.h>
48fb919e4dSMark Murray #include <sys/proc.h>
49bdd04ab1STom Rhodes #include <sys/posix4.h>
50fe24ab5fSJohn Baldwin #include <sys/syscallsubr.h>
518a6472b7SPeter Dufault #include <sys/sysctl.h>
52fb919e4dSMark Murray #include <sys/sysent.h>
53fb919e4dSMark Murray #include <sys/syslog.h>
54fb919e4dSMark Murray #include <sys/sysproto.h>
558a6472b7SPeter Dufault 
568a6472b7SPeter Dufault MALLOC_DEFINE(M_P31B, "p1003.1b", "Posix 1003.1B");
578a6472b7SPeter Dufault 
58873fbcd7SRobert Watson /* The system calls return ENOSYS if an entry is called that is not run-time
59873fbcd7SRobert Watson  * supported.  I am also logging since some programs start to use this when
60873fbcd7SRobert Watson  * they shouldn't.  That will be removed if annoying.
612a61a110SPeter Dufault  */
628a6472b7SPeter Dufault int
63b40ce416SJulian Elischer syscall_not_present(struct thread *td, const char *s, struct nosys_args *uap)
648a6472b7SPeter Dufault {
658a6472b7SPeter Dufault 	log(LOG_ERR, "cmd %s pid %d tried to use non-present %s\n",
66431f8906SJulian Elischer 			td->td_name, td->td_proc->p_pid, s);
672a61a110SPeter Dufault 
682a61a110SPeter Dufault 	/* a " return nosys(p, uap); " here causes a core dump.
692a61a110SPeter Dufault 	 */
702a61a110SPeter Dufault 
712a61a110SPeter Dufault 	return ENOSYS;
728a6472b7SPeter Dufault }
738a6472b7SPeter Dufault 
748a6472b7SPeter Dufault #if !defined(_KPOSIX_PRIORITY_SCHEDULING)
758a6472b7SPeter Dufault 
76e9189611SPeter Wemm /* Not configured but loadable via a module:
778a6472b7SPeter Dufault  */
788a6472b7SPeter Dufault 
79f6c040a2SDavid Xu static int
80f6c040a2SDavid Xu sched_attach(void)
818a6472b7SPeter Dufault {
828a6472b7SPeter Dufault 	return 0;
838a6472b7SPeter Dufault }
848a6472b7SPeter Dufault 
858a6472b7SPeter Dufault SYSCALL_NOT_PRESENT_GEN(sched_setparam)
868a6472b7SPeter Dufault SYSCALL_NOT_PRESENT_GEN(sched_getparam)
878a6472b7SPeter Dufault SYSCALL_NOT_PRESENT_GEN(sched_setscheduler)
888a6472b7SPeter Dufault SYSCALL_NOT_PRESENT_GEN(sched_getscheduler)
898a6472b7SPeter Dufault SYSCALL_NOT_PRESENT_GEN(sched_yield)
908a6472b7SPeter Dufault SYSCALL_NOT_PRESENT_GEN(sched_get_priority_max)
918a6472b7SPeter Dufault SYSCALL_NOT_PRESENT_GEN(sched_get_priority_min)
928a6472b7SPeter Dufault SYSCALL_NOT_PRESENT_GEN(sched_rr_get_interval)
938a6472b7SPeter Dufault #else
948a6472b7SPeter Dufault 
958a6472b7SPeter Dufault /* Configured in kernel version:
968a6472b7SPeter Dufault  */
978a6472b7SPeter Dufault static struct ksched *ksched;
988a6472b7SPeter Dufault 
99f6c040a2SDavid Xu static int
100f6c040a2SDavid Xu sched_attach(void)
1018a6472b7SPeter Dufault {
1028a6472b7SPeter Dufault 	int ret = ksched_attach(&ksched);
1038a6472b7SPeter Dufault 
1048a6472b7SPeter Dufault 	if (ret == 0)
10534c1c599SJohn Baldwin 		p31b_setcfg(CTL_P1003_1B_PRIORITY_SCHEDULING, 200112L);
1068a6472b7SPeter Dufault 
1078a6472b7SPeter Dufault 	return ret;
1088a6472b7SPeter Dufault }
1098a6472b7SPeter Dufault 
110f6c040a2SDavid Xu int
111*8451d0ddSKip Macy sys_sched_setparam(struct thread *td, struct sched_setparam_args *uap)
1128a6472b7SPeter Dufault {
113b40ce416SJulian Elischer 	struct thread *targettd;
1141af55356SRobert Watson 	struct proc *targetp;
1158a6472b7SPeter Dufault 	int e;
116aebde782SPeter Dufault 	struct sched_param sched_param;
1172afac34dSMatthew Dillon 
118e8f7a952SRobert Watson 	e = copyin(uap->param, &sched_param, sizeof(sched_param));
119e8f7a952SRobert Watson 	if (e)
120e8f7a952SRobert Watson 		return (e);
121aebde782SPeter Dufault 
122e84b7987SRobert Watson 	if (uap->pid == 0) {
123b40ce416SJulian Elischer 		targetp = td->td_proc;
124b40ce416SJulian Elischer 		targettd = td;
125e84b7987SRobert Watson 		PROC_LOCK(targetp);
12624af5900SDavid Xu 	} else {
127e84b7987SRobert Watson 		targetp = pfind(uap->pid);
12865343c78SDavid Xu 		if (targetp == NULL)
12965343c78SDavid Xu 			return (ESRCH);
13065343c78SDavid Xu 		targettd = FIRST_THREAD_IN_PROC(targetp);
131e84b7987SRobert Watson 	}
132e84b7987SRobert Watson 
133f44d9e24SJohn Baldwin 	e = p_cansched(td, targetp);
1342afac34dSMatthew Dillon 	if (e == 0) {
13565343c78SDavid Xu 		e = ksched_setparam(ksched, targettd,
13664e55bf4SRobert Watson 			(const struct sched_param *)&sched_param);
1372afac34dSMatthew Dillon 	}
138e631cff3SDavid Xu 	PROC_UNLOCK(targetp);
13964e55bf4SRobert Watson 	return (e);
1408a6472b7SPeter Dufault }
1418a6472b7SPeter Dufault 
142f6c040a2SDavid Xu int
143*8451d0ddSKip Macy sys_sched_getparam(struct thread *td, struct sched_getparam_args *uap)
1448a6472b7SPeter Dufault {
1458a6472b7SPeter Dufault 	int e;
146aebde782SPeter Dufault 	struct sched_param sched_param;
147b40ce416SJulian Elischer 	struct thread *targettd;
1481af55356SRobert Watson 	struct proc *targetp;
1498a6472b7SPeter Dufault 
150e84b7987SRobert Watson 	if (uap->pid == 0) {
151b40ce416SJulian Elischer 		targetp = td->td_proc;
152b40ce416SJulian Elischer 		targettd = td;
153e84b7987SRobert Watson 		PROC_LOCK(targetp);
15424af5900SDavid Xu 	} else {
155e84b7987SRobert Watson 		targetp = pfind(uap->pid);
1562afac34dSMatthew Dillon 		if (targetp == NULL) {
15765343c78SDavid Xu 			return (ESRCH);
1582afac34dSMatthew Dillon 		}
1596617724cSJeff Roberson 		targettd = FIRST_THREAD_IN_PROC(targetp);
160e84b7987SRobert Watson 	}
161e84b7987SRobert Watson 
162f44d9e24SJohn Baldwin 	e = p_cansee(td, targetp);
163e631cff3SDavid Xu 	if (e == 0) {
16465343c78SDavid Xu 		e = ksched_getparam(ksched, targettd, &sched_param);
165e631cff3SDavid Xu 	}
166e84b7987SRobert Watson 	PROC_UNLOCK(targetp);
1672afac34dSMatthew Dillon 	if (e == 0)
16864e55bf4SRobert Watson 		e = copyout(&sched_param, uap->param, sizeof(sched_param));
16964e55bf4SRobert Watson 	return (e);
1708a6472b7SPeter Dufault }
171b40ce416SJulian Elischer 
172f6c040a2SDavid Xu int
173*8451d0ddSKip Macy sys_sched_setscheduler(struct thread *td, struct sched_setscheduler_args *uap)
1748a6472b7SPeter Dufault {
1758a6472b7SPeter Dufault 	int e;
176aebde782SPeter Dufault 	struct sched_param sched_param;
177b40ce416SJulian Elischer 	struct thread *targettd;
1781af55356SRobert Watson 	struct proc *targetp;
1791af55356SRobert Watson 
180acd3428bSRobert Watson 	/* Don't allow non root user to set a scheduler policy. */
181acd3428bSRobert Watson 	e = priv_check(td, PRIV_SCHED_SET);
182acd3428bSRobert Watson 	if (e)
183acd3428bSRobert Watson 		return (e);
184f705bbe8SDavid Xu 
185e8f7a952SRobert Watson 	e = copyin(uap->param, &sched_param, sizeof(sched_param));
186e8f7a952SRobert Watson 	if (e)
187e8f7a952SRobert Watson 		return (e);
188aebde782SPeter Dufault 
189e84b7987SRobert Watson 	if (uap->pid == 0) {
190b40ce416SJulian Elischer 		targetp = td->td_proc;
191b40ce416SJulian Elischer 		targettd = td;
192e84b7987SRobert Watson 		PROC_LOCK(targetp);
19324af5900SDavid Xu 	} else {
194e84b7987SRobert Watson 		targetp = pfind(uap->pid);
19565343c78SDavid Xu 		if (targetp == NULL)
19665343c78SDavid Xu 			return (ESRCH);
19765343c78SDavid Xu 		targettd = FIRST_THREAD_IN_PROC(targetp);
198e84b7987SRobert Watson 	}
199e84b7987SRobert Watson 
200f44d9e24SJohn Baldwin 	e = p_cansched(td, targetp);
2012afac34dSMatthew Dillon 	if (e == 0) {
20265343c78SDavid Xu 		e = ksched_setscheduler(ksched, targettd,
203b40ce416SJulian Elischer 			uap->policy, (const struct sched_param *)&sched_param);
2042afac34dSMatthew Dillon 	}
205e631cff3SDavid Xu 	PROC_UNLOCK(targetp);
20664e55bf4SRobert Watson 	return (e);
2078a6472b7SPeter Dufault }
208b40ce416SJulian Elischer 
209f6c040a2SDavid Xu int
210*8451d0ddSKip Macy sys_sched_getscheduler(struct thread *td, struct sched_getscheduler_args *uap)
2118a6472b7SPeter Dufault {
21265343c78SDavid Xu 	int e, policy;
213b40ce416SJulian Elischer 	struct thread *targettd;
2141af55356SRobert Watson 	struct proc *targetp;
2158a6472b7SPeter Dufault 
216e84b7987SRobert Watson 	if (uap->pid == 0) {
217b40ce416SJulian Elischer 		targetp = td->td_proc;
218b40ce416SJulian Elischer 		targettd = td;
219e84b7987SRobert Watson 		PROC_LOCK(targetp);
22024af5900SDavid Xu 	} else {
221e84b7987SRobert Watson 		targetp = pfind(uap->pid);
222931e4573SDavid Xu 		if (targetp == NULL)
223931e4573SDavid Xu 			return (ESRCH);
2246617724cSJeff Roberson 		targettd = FIRST_THREAD_IN_PROC(targetp);
225e84b7987SRobert Watson 	}
226e84b7987SRobert Watson 
227f44d9e24SJohn Baldwin 	e = p_cansee(td, targetp);
22865343c78SDavid Xu 	if (e == 0) {
22965343c78SDavid Xu 		e = ksched_getscheduler(ksched, targettd, &policy);
23065343c78SDavid Xu 		td->td_retval[0] = policy;
23165343c78SDavid Xu 	}
232e631cff3SDavid Xu 	PROC_UNLOCK(targetp);
23364e55bf4SRobert Watson 
23464e55bf4SRobert Watson 	return (e);
2358a6472b7SPeter Dufault }
236b40ce416SJulian Elischer 
237f6c040a2SDavid Xu int
238*8451d0ddSKip Macy sys_sched_yield(struct thread *td, struct sched_yield_args *uap)
2398a6472b7SPeter Dufault {
2402afac34dSMatthew Dillon 
24105dc0eb2SJeff Roberson 	sched_relinquish(curthread);
24205dc0eb2SJeff Roberson 	return 0;
2438a6472b7SPeter Dufault }
244b40ce416SJulian Elischer 
245f6c040a2SDavid Xu int
246*8451d0ddSKip Macy sys_sched_get_priority_max(struct thread *td,
2478a6472b7SPeter Dufault     struct sched_get_priority_max_args *uap)
2488a6472b7SPeter Dufault {
24965343c78SDavid Xu 	int error, prio;
2502afac34dSMatthew Dillon 
25165343c78SDavid Xu 	error = ksched_get_priority_max(ksched, uap->policy, &prio);
25265343c78SDavid Xu 	td->td_retval[0] = prio;
2532afac34dSMatthew Dillon 	return (error);
2548a6472b7SPeter Dufault }
255b40ce416SJulian Elischer 
256f6c040a2SDavid Xu int
257*8451d0ddSKip Macy sys_sched_get_priority_min(struct thread *td,
2588a6472b7SPeter Dufault     struct sched_get_priority_min_args *uap)
2598a6472b7SPeter Dufault {
26065343c78SDavid Xu 	int error, prio;
261b40ce416SJulian Elischer 
26265343c78SDavid Xu 	error = ksched_get_priority_min(ksched, uap->policy, &prio);
26365343c78SDavid Xu 	td->td_retval[0] = prio;
2642afac34dSMatthew Dillon 	return (error);
2658a6472b7SPeter Dufault }
266b40ce416SJulian Elischer 
267f6c040a2SDavid Xu int
268*8451d0ddSKip Macy sys_sched_rr_get_interval(struct thread *td,
2698a6472b7SPeter Dufault     struct sched_rr_get_interval_args *uap)
2708a6472b7SPeter Dufault {
271fe24ab5fSJohn Baldwin 	struct timespec timespec;
272fe24ab5fSJohn Baldwin 	int error;
273fe24ab5fSJohn Baldwin 
274fe24ab5fSJohn Baldwin 	error = kern_sched_rr_get_interval(td, uap->pid, &timespec);
275fe24ab5fSJohn Baldwin 	if (error == 0)
276fe24ab5fSJohn Baldwin 		error = copyout(&timespec, uap->interval, sizeof(timespec));
277fe24ab5fSJohn Baldwin 	return (error);
278fe24ab5fSJohn Baldwin }
279fe24ab5fSJohn Baldwin 
280f6c040a2SDavid Xu int
281f6c040a2SDavid Xu kern_sched_rr_get_interval(struct thread *td, pid_t pid,
282fe24ab5fSJohn Baldwin     struct timespec *ts)
283fe24ab5fSJohn Baldwin {
2848a6472b7SPeter Dufault 	int e;
285b40ce416SJulian Elischer 	struct thread *targettd;
2861af55356SRobert Watson 	struct proc *targetp;
2878a6472b7SPeter Dufault 
288fe24ab5fSJohn Baldwin 	if (pid == 0) {
289b40ce416SJulian Elischer 		targettd = td;
290b40ce416SJulian Elischer 		targetp = td->td_proc;
291e84b7987SRobert Watson 		PROC_LOCK(targetp);
29265343c78SDavid Xu 	} else {
293931e4573SDavid Xu 		targetp = pfind(pid);
294931e4573SDavid Xu 		if (targetp == NULL)
29565343c78SDavid Xu 			return (ESRCH);
296931e4573SDavid Xu 		targettd = FIRST_THREAD_IN_PROC(targetp);
297e84b7987SRobert Watson 	}
298e84b7987SRobert Watson 
299f44d9e24SJohn Baldwin 	e = p_cansee(td, targetp);
300a11acc6fSAlfred Perlstein 	if (e == 0)
30165343c78SDavid Xu 		e = ksched_rr_get_interval(ksched, targettd, ts);
302fe24ab5fSJohn Baldwin 	PROC_UNLOCK(targetp);
30364e55bf4SRobert Watson 	return (e);
3048a6472b7SPeter Dufault }
3058a6472b7SPeter Dufault 
3068a6472b7SPeter Dufault #endif
3078a6472b7SPeter Dufault 
308f6c040a2SDavid Xu static void
309f6c040a2SDavid Xu p31binit(void *notused)
3108a6472b7SPeter Dufault {
3118a6472b7SPeter Dufault 	(void) sched_attach();
312ce47711dSPeter Dufault 	p31b_setcfg(CTL_P1003_1B_PAGESIZE, PAGE_SIZE);
3138a6472b7SPeter Dufault }
3148a6472b7SPeter Dufault 
3158a6472b7SPeter Dufault SYSINIT(p31b, SI_SUB_P1003_1B, SI_ORDER_FIRST, p31binit, NULL);
316