diff options
Diffstat (limited to 'sys/compat/linux/linux.c')
-rw-r--r-- | sys/compat/linux/linux.c | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/sys/compat/linux/linux.c b/sys/compat/linux/linux.c new file mode 100644 index 0000000..d1d7877 --- /dev/null +++ b/sys/compat/linux/linux.c @@ -0,0 +1,205 @@ +/*- + * Copyright (c) 2015 Dmitry Chagin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/signalvar.h> + +#include <compat/linux/linux.h> + + +static int bsd_to_linux_sigtbl[LINUX_SIGTBLSZ] = { + LINUX_SIGHUP, /* SIGHUP */ + LINUX_SIGINT, /* SIGINT */ + LINUX_SIGQUIT, /* SIGQUIT */ + LINUX_SIGILL, /* SIGILL */ + LINUX_SIGTRAP, /* SIGTRAP */ + LINUX_SIGABRT, /* SIGABRT */ + 0, /* SIGEMT */ + LINUX_SIGFPE, /* SIGFPE */ + LINUX_SIGKILL, /* SIGKILL */ + LINUX_SIGBUS, /* SIGBUS */ + LINUX_SIGSEGV, /* SIGSEGV */ + LINUX_SIGSYS, /* SIGSYS */ + LINUX_SIGPIPE, /* SIGPIPE */ + LINUX_SIGALRM, /* SIGALRM */ + LINUX_SIGTERM, /* SIGTERM */ + LINUX_SIGURG, /* SIGURG */ + LINUX_SIGSTOP, /* SIGSTOP */ + LINUX_SIGTSTP, /* SIGTSTP */ + LINUX_SIGCONT, /* SIGCONT */ + LINUX_SIGCHLD, /* SIGCHLD */ + LINUX_SIGTTIN, /* SIGTTIN */ + LINUX_SIGTTOU, /* SIGTTOU */ + LINUX_SIGIO, /* SIGIO */ + LINUX_SIGXCPU, /* SIGXCPU */ + LINUX_SIGXFSZ, /* SIGXFSZ */ + LINUX_SIGVTALRM,/* SIGVTALRM */ + LINUX_SIGPROF, /* SIGPROF */ + LINUX_SIGWINCH, /* SIGWINCH */ + 0, /* SIGINFO */ + LINUX_SIGUSR1, /* SIGUSR1 */ + LINUX_SIGUSR2 /* SIGUSR2 */ +}; + +static int linux_to_bsd_sigtbl[LINUX_SIGTBLSZ] = { + SIGHUP, /* LINUX_SIGHUP */ + SIGINT, /* LINUX_SIGINT */ + SIGQUIT, /* LINUX_SIGQUIT */ + SIGILL, /* LINUX_SIGILL */ + SIGTRAP, /* LINUX_SIGTRAP */ + SIGABRT, /* LINUX_SIGABRT */ + SIGBUS, /* LINUX_SIGBUS */ + SIGFPE, /* LINUX_SIGFPE */ + SIGKILL, /* LINUX_SIGKILL */ + SIGUSR1, /* LINUX_SIGUSR1 */ + SIGSEGV, /* LINUX_SIGSEGV */ + SIGUSR2, /* LINUX_SIGUSR2 */ + SIGPIPE, /* LINUX_SIGPIPE */ + SIGALRM, /* LINUX_SIGALRM */ + SIGTERM, /* LINUX_SIGTERM */ + SIGBUS, /* LINUX_SIGSTKFLT */ + SIGCHLD, /* LINUX_SIGCHLD */ + SIGCONT, /* LINUX_SIGCONT */ + SIGSTOP, /* LINUX_SIGSTOP */ + SIGTSTP, /* LINUX_SIGTSTP */ + SIGTTIN, /* LINUX_SIGTTIN */ + SIGTTOU, /* LINUX_SIGTTOU */ + SIGURG, /* LINUX_SIGURG */ + SIGXCPU, /* LINUX_SIGXCPU */ + SIGXFSZ, /* LINUX_SIGXFSZ */ + SIGVTALRM, /* LINUX_SIGVTALARM */ + SIGPROF, /* LINUX_SIGPROF */ + SIGWINCH, /* LINUX_SIGWINCH */ + SIGIO, /* LINUX_SIGIO */ + /* + * FreeBSD does not have SIGPWR signal, map Linux SIGPWR signal + * to the first unused FreeBSD signal number. Since Linux supports + * signals from 1 to 64 we are ok here as our SIGRTMIN = 65. + */ + SIGRTMIN, /* LINUX_SIGPWR */ + SIGSYS /* LINUX_SIGSYS */ +}; + +/* + * Map Linux RT signals to the FreeBSD RT signals. + */ +static inline int +linux_to_bsd_rt_signal(int sig) +{ + + return (SIGRTMIN + 1 + sig - LINUX_SIGRTMIN); +} + +static inline int +bsd_to_linux_rt_signal(int sig) +{ + + return (sig - SIGRTMIN - 1 + LINUX_SIGRTMIN); +} + +int +linux_to_bsd_signal(int sig) +{ + + KASSERT(sig > 0 && sig <= LINUX_SIGRTMAX, ("Invalid Linux signal\n")); + + if (sig < LINUX_SIGRTMIN) + return (linux_to_bsd_sigtbl[_SIG_IDX(sig)]); + + return (linux_to_bsd_rt_signal(sig)); +} + +int +bsd_to_linux_signal(int sig) +{ + + if (sig <= LINUX_SIGTBLSZ) + return (bsd_to_linux_sigtbl[_SIG_IDX(sig)]); + if (sig == SIGRTMIN) + return (LINUX_SIGPWR); + + return (bsd_to_linux_rt_signal(sig)); +} + +int +linux_to_bsd_sigaltstack(int lsa) +{ + int bsa = 0; + + if (lsa & LINUX_SS_DISABLE) + bsa |= SS_DISABLE; + /* + * Linux ignores SS_ONSTACK flag for ss + * parameter while FreeBSD prohibits it. + */ + return (bsa); +} + +int +bsd_to_linux_sigaltstack(int bsa) +{ + int lsa = 0; + + if (bsa & SS_DISABLE) + lsa |= LINUX_SS_DISABLE; + if (bsa & SS_ONSTACK) + lsa |= LINUX_SS_ONSTACK; + return (lsa); +} + +void +linux_to_bsd_sigset(l_sigset_t *lss, sigset_t *bss) +{ + int b, l; + + SIGEMPTYSET(*bss); + for (l = 1; l <= LINUX_SIGRTMAX; l++) { + if (LINUX_SIGISMEMBER(*lss, l)) { + b = linux_to_bsd_signal(l); + if (b) + SIGADDSET(*bss, b); + } + } +} + +void +bsd_to_linux_sigset(sigset_t *bss, l_sigset_t *lss) +{ + int b, l; + + LINUX_SIGEMPTYSET(*lss); + for (b = 1; b <= SIGRTMAX; b++) { + if (SIGISMEMBER(*bss, b)) { + l = bsd_to_linux_signal(b); + if (l) + LINUX_SIGADDSET(*lss, l); + } + } +} |