12be05b70SDaniel Eischen /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
38a36da99SPedro F. Giffuni *
42be05b70SDaniel Eischen * Copyright (c) 2002 Daniel M. Eischen <deischen@freebsd.org>
52be05b70SDaniel Eischen * All rights reserved.
62be05b70SDaniel Eischen *
72be05b70SDaniel Eischen * Redistribution and use in source and binary forms, with or without
82be05b70SDaniel Eischen * modification, are permitted provided that the following conditions
92be05b70SDaniel Eischen * are met:
102be05b70SDaniel Eischen * 1. Redistributions of source code must retain the above copyright
112be05b70SDaniel Eischen * notice, this list of conditions and the following disclaimer.
122be05b70SDaniel Eischen * 2. Redistributions in binary form must reproduce the above copyright
132be05b70SDaniel Eischen * notice, this list of conditions and the following disclaimer in the
142be05b70SDaniel Eischen * documentation and/or other materials provided with the distribution.
152be05b70SDaniel Eischen *
162be05b70SDaniel Eischen * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
172be05b70SDaniel Eischen * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
182be05b70SDaniel Eischen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
192be05b70SDaniel Eischen * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
202be05b70SDaniel Eischen * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
212be05b70SDaniel Eischen * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
222be05b70SDaniel Eischen * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
232be05b70SDaniel Eischen * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
242be05b70SDaniel Eischen * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
252be05b70SDaniel Eischen * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
262be05b70SDaniel Eischen * SUCH DAMAGE.
272be05b70SDaniel Eischen */
28677b542eSDavid E. O'Brien
292be05b70SDaniel Eischen #include <sys/param.h>
302be05b70SDaniel Eischen #include <sys/kernel.h>
312be05b70SDaniel Eischen #include <sys/lock.h>
322be05b70SDaniel Eischen #include <sys/mutex.h>
332be05b70SDaniel Eischen #include <sys/proc.h>
34fc0de8f0SJohn Baldwin #include <sys/syscallsubr.h>
352be05b70SDaniel Eischen #include <sys/systm.h>
362be05b70SDaniel Eischen #include <sys/sysproto.h>
372be05b70SDaniel Eischen #include <sys/signalvar.h>
382be05b70SDaniel Eischen #include <sys/ucontext.h>
392be05b70SDaniel Eischen
402be05b70SDaniel Eischen /*
41873fbcd7SRobert Watson * The first two fields of a ucontext_t are the signal mask and the machine
42873fbcd7SRobert Watson * context. The next field is uc_link; we want to avoid destroying the link
43873fbcd7SRobert Watson * when copying out contexts.
442be05b70SDaniel Eischen */
45fc2fca74SJake Burkholder #define UC_COPY_SIZE offsetof(ucontext_t, uc_link)
462be05b70SDaniel Eischen
472be05b70SDaniel Eischen #ifndef _SYS_SYSPROTO_H_
482be05b70SDaniel Eischen struct getcontext_args {
492be05b70SDaniel Eischen struct __ucontext *ucp;
502be05b70SDaniel Eischen }
512be05b70SDaniel Eischen struct setcontext_args {
522be05b70SDaniel Eischen const struct __ucontext_t *ucp;
532be05b70SDaniel Eischen }
542be05b70SDaniel Eischen struct swapcontext_args {
552be05b70SDaniel Eischen struct __ucontext *oucp;
562be05b70SDaniel Eischen const struct __ucontext_t *ucp;
572be05b70SDaniel Eischen }
582be05b70SDaniel Eischen #endif
592be05b70SDaniel Eischen
602be05b70SDaniel Eischen int
sys_getcontext(struct thread * td,struct getcontext_args * uap)618451d0ddSKip Macy sys_getcontext(struct thread *td, struct getcontext_args *uap)
622be05b70SDaniel Eischen {
632be05b70SDaniel Eischen ucontext_t uc;
642be05b70SDaniel Eischen int ret;
652be05b70SDaniel Eischen
662be05b70SDaniel Eischen if (uap->ucp == NULL)
672be05b70SDaniel Eischen ret = EINVAL;
682be05b70SDaniel Eischen else {
6989f652d1SGordon Tetlow bzero(&uc, sizeof(ucontext_t));
70fcaa2925SMarcel Moolenaar get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
7194df4b85SJohn Baldwin PROC_LOCK(td->td_proc);
724093529dSJeff Roberson uc.uc_sigmask = td->td_sigmask;
7394df4b85SJohn Baldwin PROC_UNLOCK(td->td_proc);
742be05b70SDaniel Eischen ret = copyout(&uc, uap->ucp, UC_COPY_SIZE);
752be05b70SDaniel Eischen }
762be05b70SDaniel Eischen return (ret);
772be05b70SDaniel Eischen }
782be05b70SDaniel Eischen
792be05b70SDaniel Eischen int
sys_setcontext(struct thread * td,struct setcontext_args * uap)808451d0ddSKip Macy sys_setcontext(struct thread *td, struct setcontext_args *uap)
812be05b70SDaniel Eischen {
822be05b70SDaniel Eischen ucontext_t uc;
832be05b70SDaniel Eischen int ret;
842be05b70SDaniel Eischen
852be05b70SDaniel Eischen if (uap->ucp == NULL)
862be05b70SDaniel Eischen ret = EINVAL;
872be05b70SDaniel Eischen else {
882be05b70SDaniel Eischen ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
892be05b70SDaniel Eischen if (ret == 0) {
902be05b70SDaniel Eischen ret = set_mcontext(td, &uc.uc_mcontext);
912be05b70SDaniel Eischen if (ret == 0) {
92d6e029adSKonstantin Belousov kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask,
93d6e029adSKonstantin Belousov NULL, 0);
942be05b70SDaniel Eischen }
952be05b70SDaniel Eischen }
962be05b70SDaniel Eischen }
97fc2fca74SJake Burkholder return (ret == 0 ? EJUSTRETURN : ret);
982be05b70SDaniel Eischen }
992be05b70SDaniel Eischen
1002be05b70SDaniel Eischen int
sys_swapcontext(struct thread * td,struct swapcontext_args * uap)1018451d0ddSKip Macy sys_swapcontext(struct thread *td, struct swapcontext_args *uap)
1022be05b70SDaniel Eischen {
1032be05b70SDaniel Eischen ucontext_t uc;
1042be05b70SDaniel Eischen int ret;
1052be05b70SDaniel Eischen
1062be05b70SDaniel Eischen if (uap->oucp == NULL || uap->ucp == NULL)
1072be05b70SDaniel Eischen ret = EINVAL;
1082be05b70SDaniel Eischen else {
10989f652d1SGordon Tetlow bzero(&uc, sizeof(ucontext_t));
110fcaa2925SMarcel Moolenaar get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
11194df4b85SJohn Baldwin PROC_LOCK(td->td_proc);
1124093529dSJeff Roberson uc.uc_sigmask = td->td_sigmask;
11394df4b85SJohn Baldwin PROC_UNLOCK(td->td_proc);
1142be05b70SDaniel Eischen ret = copyout(&uc, uap->oucp, UC_COPY_SIZE);
1152be05b70SDaniel Eischen if (ret == 0) {
1162be05b70SDaniel Eischen ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
1172be05b70SDaniel Eischen if (ret == 0) {
1182be05b70SDaniel Eischen ret = set_mcontext(td, &uc.uc_mcontext);
1192be05b70SDaniel Eischen if (ret == 0) {
120d6e029adSKonstantin Belousov kern_sigprocmask(td, SIG_SETMASK,
121d6e029adSKonstantin Belousov &uc.uc_sigmask, NULL, 0);
1222be05b70SDaniel Eischen }
1232be05b70SDaniel Eischen }
1242be05b70SDaniel Eischen }
1252be05b70SDaniel Eischen }
126fc2fca74SJake Burkholder return (ret == 0 ? EJUSTRETURN : ret);
1272be05b70SDaniel Eischen }
128