[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2 07/19] bsd-user: add support for freebsd signal r
From: |
Stacey Son |
Subject: |
[Qemu-devel] [PATCH v2 07/19] bsd-user: add support for freebsd signal related system calls |
Date: |
Fri, 8 Nov 2013 10:33:25 -0600 |
This change adds support or stubs for signal related system calls including
sigtimedwait(2), sigaction(2), sigprocmask(2), sigpending(2), sigsuspend(2),
sigreturn(2), sigwait(2), sigwaitinfo(2), sigqueue(2), sigaltstack(2),
kill(2), killpg(2), and pdkill(2).
Signed-off-by: Stacey Son <address@hidden>
---
bsd-user/arm/target_arch_signal.h | 257 ++++++++++
bsd-user/bsd-signal.h | 232 +++++++++
bsd-user/errno_defs.h | 13 +-
bsd-user/freebsd/os-signal.h | 43 ++
bsd-user/freebsd/target_os_siginfo.h | 110 ++++
bsd-user/freebsd/target_os_signal.h | 79 +++
bsd-user/i386/target_arch_signal.h | 94 ++++
bsd-user/mips/target_arch_signal.h | 237 +++++++++
bsd-user/mips64/target_arch_signal.h | 236 +++++++++
bsd-user/netbsd/target_os_siginfo.h | 82 +++
bsd-user/netbsd/target_os_signal.h | 70 +++
bsd-user/openbsd/target_os_siginfo.h | 82 +++
bsd-user/openbsd/target_os_signal.h | 70 +++
bsd-user/qemu.h | 33 +-
bsd-user/signal.c | 907 ++++++++++++++++++++++++++++++++-
bsd-user/sparc/target_arch_signal.h | 77 +++
bsd-user/sparc64/target_arch_signal.h | 94 ++++
bsd-user/syscall.c | 59 +++
bsd-user/x86_64/target_arch_signal.h | 94 ++++
19 files changed, 2852 insertions(+), 17 deletions(-)
create mode 100644 bsd-user/arm/target_arch_signal.h
create mode 100644 bsd-user/bsd-signal.h
create mode 100644 bsd-user/freebsd/os-signal.h
create mode 100644 bsd-user/freebsd/target_os_siginfo.h
create mode 100644 bsd-user/freebsd/target_os_signal.h
create mode 100644 bsd-user/i386/target_arch_signal.h
create mode 100644 bsd-user/mips/target_arch_signal.h
create mode 100644 bsd-user/mips64/target_arch_signal.h
create mode 100644 bsd-user/netbsd/target_os_siginfo.h
create mode 100644 bsd-user/netbsd/target_os_signal.h
create mode 100644 bsd-user/openbsd/target_os_siginfo.h
create mode 100644 bsd-user/openbsd/target_os_signal.h
create mode 100644 bsd-user/sparc/target_arch_signal.h
create mode 100644 bsd-user/sparc64/target_arch_signal.h
create mode 100644 bsd-user/x86_64/target_arch_signal.h
diff --git a/bsd-user/arm/target_arch_signal.h
b/bsd-user/arm/target_arch_signal.h
new file mode 100644
index 0000000..048bd4f
--- /dev/null
+++ b/bsd-user/arm/target_arch_signal.h
@@ -0,0 +1,257 @@
+/*
+ * arm signal definitions
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _TARGET_ARCH_SIGNAL_H_
+#define _TARGET_ARCH_SIGNAL_H_
+
+#include "cpu.h"
+
+#define TARGET_REG_R0 0
+#define TARGET_REG_R1 1
+#define TARGET_REG_R2 2
+#define TARGET_REG_R3 3
+#define TARGET_REG_R4 4
+#define TARGET_REG_R5 5
+#define TARGET_REG_R6 6
+#define TARGET_REG_R7 7
+#define TARGET_REG_R8 8
+#define TARGET_REG_R9 9
+#define TARGET_REG_R10 10
+#define TARGET_REG_R11 11
+#define TARGET_REG_R12 12
+#define TARGET_REG_R13 13
+#define TARGET_REG_R14 14
+#define TARGET_REG_R15 15
+#define TARGET_REG_CPSR 16
+#define TARGET__NGREG 17
+/* Convenience synonyms */
+#define TARGET_REG_FP TARGET_REG_R11
+#define TARGET_REG_SP TARGET_REG_R13
+#define TARGET_REG_LR TARGET_REG_R14
+#define TARGET_REG_PC TARGET_REG_R15
+
+#define TARGET_INSN_SIZE 4 /* arm instruction size */
+
+/* Size of the signal trampolin code. See _sigtramp(). */
+#define TARGET_SZSIGCODE ((abi_ulong)(8 * TARGET_INSN_SIZE))
+
+/* compare to arm/include/_limits.h */
+#define TARGET_MINSIGSTKSZ (1024 * 4) /* min sig stack size
*/
+#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768) /* recommended size
*/
+
+/* arm/arm/machdep.c */
+#define TARGET_MC_GET_CLEAR_RET 0x0001
+#define TARGET_MC_ADD_MAGIC 0x0002
+#define TARGET_MC_SET_ONSTACK 0x0004
+
+struct target_sigcontext {
+ target_sigset_t sc_mask; /* signal mask to retstore */
+ int32_t sc_onstack; /* sigstack state to restore */
+ abi_long sc_pc; /* pc at time of signal */
+ abi_long sc_reg[32]; /* processor regs 0 to 31 */
+ abi_long mullo, mulhi; /* mullo and mulhi registers */
+ int32_t sc_fpused; /* fp has been used */
+ abi_long sc_fpregs[33]; /* fp regs 0 to 31 & csr */
+ abi_long sc_fpc_eir; /* fp exception instr reg */
+ /* int32_t reserved[8]; */
+};
+
+typedef struct {
+ uint32_t __fp_fpsr;
+ struct {
+ uint32_t __fp_exponent;
+ uint32_t __fp_mantissa_hi;
+ uint32_t __fp_mantissa_lo;
+ } __fp_fr[8];
+} target__fpregset_t;
+
+typedef struct {
+ uint32_t __vfp_fpscr;
+ uint32_t __vfp_fstmx[33];
+ uint32_t __vfp_fpsid;
+} target__vfpregset_t;
+
+typedef struct target_mcontext {
+ uint32_t __gregs[TARGET__NGREG];
+ union {
+ target__fpregset_t __fpregs;
+ target__vfpregset_t __vfpregs;
+ } __fpu;
+} target_mcontext_t;
+
+typedef struct target_ucontext {
+ target_sigset_t uc_sigmask;
+ target_mcontext_t uc_mcontext;
+ abi_ulong uc_link;
+ target_stack_t uc_stack;
+ int32_t uc_flags;
+ int32_t __spare__[4];
+} target_ucontext_t;
+
+struct target_sigframe {
+ target_siginfo_t sf_si; /* saved siginfo */
+ target_ucontext_t sf_uc; /* saved ucontext */
+};
+
+
+/* compare to sys/arm/include/frame.h */
+struct target_trapframe {
+ abi_ulong tf_spsr; /* Zero on arm26 */
+ abi_ulong tf_r0;
+ abi_ulong tf_r1;
+ abi_ulong tf_r2;
+ abi_ulong tf_r3;
+ abi_ulong tf_r4;
+ abi_ulong tf_r5;
+ abi_ulong tf_r6;
+ abi_ulong tf_r7;
+ abi_ulong tf_r8;
+ abi_ulong tf_r9;
+ abi_ulong tf_r10;
+ abi_ulong tf_r11;
+ abi_ulong tf_r12;
+ abi_ulong tf_usr_sp;
+ abi_ulong tf_usr_lr;
+ abi_ulong tf_svc_sp; /* Not used on arm26 */
+ abi_ulong tf_svc_lr; /* Not used on arm26 */
+ abi_ulong tf_pc;
+};
+
+/*
+ * Compare to arm/arm/machdep.c sendsig()
+ * Assumes that target stack frame memory is locked.
+ */
+static inline abi_long
+set_sigtramp_args(CPUARMState *regs, int sig, struct target_sigframe *frame,
+ abi_ulong frame_addr, struct target_sigaction *ka)
+{
+ /*
+ * Arguments to signal handler:
+ * r0 = signal number
+ * r1 = siginfo pointer
+ * r2 = ucontext pointer
+ * r5 = ucontext pointer
+ * pc = signal handler pointer
+ * sp = sigframe struct pointer
+ * lr = sigtramp at base of user stack
+ */
+
+ regs->regs[0] = sig;
+ regs->regs[1] = frame_addr +
+ offsetof(struct target_sigframe, sf_si);
+ regs->regs[2] = frame_addr +
+ offsetof(struct target_sigframe, sf_uc);
+
+ /* the trampoline uses r5 as the uc address */
+ regs->regs[5] = frame_addr +
+ offsetof(struct target_sigframe, sf_uc);
+ regs->regs[TARGET_REG_PC] = ka->_sa_handler;
+ regs->regs[TARGET_REG_SP] = frame_addr;
+ regs->regs[TARGET_REG_LR] = TARGET_PS_STRINGS - TARGET_SZSIGCODE;
+
+ return 0;
+}
+
+/*
+ * Compare to arm/arm/machdep.c get_mcontext()
+ * Assumes that the memory is locked if mcp points to user memory.
+ */
+static inline abi_long get_mcontext(CPUARMState *regs, target_mcontext_t *mcp,
+ int flags)
+{
+ int err = 0;
+ uint32_t *gr = mcp->__gregs;
+
+
+ if (flags & TARGET_MC_GET_CLEAR_RET) {
+ gr[TARGET_REG_R0] = 0;
+ } else {
+ gr[TARGET_REG_R0] = tswap32(regs->regs[0]);
+ }
+
+ gr[TARGET_REG_R1] = tswap32(regs->regs[1]);
+ gr[TARGET_REG_R2] = tswap32(regs->regs[2]);
+ gr[TARGET_REG_R3] = tswap32(regs->regs[3]);
+ gr[TARGET_REG_R4] = tswap32(regs->regs[4]);
+ gr[TARGET_REG_R5] = tswap32(regs->regs[5]);
+ gr[TARGET_REG_R6] = tswap32(regs->regs[6]);
+ gr[TARGET_REG_R7] = tswap32(regs->regs[7]);
+ gr[TARGET_REG_R8] = tswap32(regs->regs[8]);
+ gr[TARGET_REG_R9] = tswap32(regs->regs[9]);
+ gr[TARGET_REG_R10] = tswap32(regs->regs[10]);
+ gr[TARGET_REG_R11] = tswap32(regs->regs[11]);
+ gr[TARGET_REG_R12] = tswap32(regs->regs[12]);
+
+ gr[TARGET_REG_SP] = tswap32(regs->regs[13]);
+ gr[TARGET_REG_LR] = tswap32(regs->regs[14]);
+ gr[TARGET_REG_PC] = tswap32(regs->regs[15]);
+ gr[TARGET_REG_CPSR] = tswap32(cpsr_read(regs));
+
+ return err;
+}
+
+/* Compare to arm/arm/machdep.c set_mcontext() */
+static inline abi_long set_mcontext(CPUARMState *regs, target_mcontext_t *mcp,
+ int srflag)
+{
+ int err = 0;
+ const uint32_t *gr = mcp->__gregs;
+ uint32_t cpsr;
+
+ regs->regs[0] = tswap32(gr[TARGET_REG_R0]);
+ regs->regs[1] = tswap32(gr[TARGET_REG_R1]);
+ regs->regs[2] = tswap32(gr[TARGET_REG_R2]);
+ regs->regs[3] = tswap32(gr[TARGET_REG_R3]);
+ regs->regs[4] = tswap32(gr[TARGET_REG_R4]);
+ regs->regs[5] = tswap32(gr[TARGET_REG_R5]);
+ regs->regs[6] = tswap32(gr[TARGET_REG_R6]);
+ regs->regs[7] = tswap32(gr[TARGET_REG_R7]);
+ regs->regs[8] = tswap32(gr[TARGET_REG_R8]);
+ regs->regs[9] = tswap32(gr[TARGET_REG_R9]);
+ regs->regs[10] = tswap32(gr[TARGET_REG_R10]);
+ regs->regs[11] = tswap32(gr[TARGET_REG_R11]);
+ regs->regs[12] = tswap32(gr[TARGET_REG_R12]);
+
+ regs->regs[13] = tswap32(gr[TARGET_REG_SP]);
+ regs->regs[14] = tswap32(gr[TARGET_REG_LR]);
+ regs->regs[15] = tswap32(gr[TARGET_REG_PC]);
+ cpsr = tswap32(gr[TARGET_REG_CPSR]);
+ cpsr_write(regs, cpsr, CPSR_USER | CPSR_EXEC);
+
+ return err;
+}
+
+/* Compare to arm/arm/machdep.c sys_sigreturn() */
+static inline abi_long get_ucontext_sigreturn(CPUARMState *regs,
+ abi_ulong target_sf, abi_ulong *target_uc)
+{
+ uint32_t cpsr = cpsr_read(regs);
+
+ *target_uc = 0;
+
+ if ((cpsr & CPSR_M) != ARM_CPU_MODE_USR ||
+ (cpsr & (CPSR_I | CPSR_F)) != 0) {
+ return -TARGET_EINVAL;
+ }
+
+ *target_uc = target_sf + offsetof(struct target_sigframe, sf_uc);
+
+ return 0;
+}
+
+
+#endif /* !_TARGET_ARCH_SIGNAL_H_ */
diff --git a/bsd-user/bsd-signal.h b/bsd-user/bsd-signal.h
new file mode 100644
index 0000000..48a8b56
--- /dev/null
+++ b/bsd-user/bsd-signal.h
@@ -0,0 +1,232 @@
+/*
+ * signal related system call shims
+ *
+ * Copyright (c) 2013 Stacey D. Son
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __BSD_SIGNAL_H_
+#define __BSD_SIGNAL_H_
+
+/* sigaction(2) */
+static inline abi_long do_bsd_sigaction(abi_long arg1, abi_long arg2,
+ abi_long arg3)
+{
+ abi_long ret;
+ struct target_sigaction *old_act, act, oact, *pact;
+
+ if (arg2) {
+ if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1)) {
+ return -TARGET_EFAULT;
+ }
+ act._sa_handler = old_act->_sa_handler;
+ act.sa_flags = old_act->sa_flags;
+ memcpy(&act.sa_mask, &old_act->sa_mask, sizeof(target_sigset_t));
+ unlock_user_struct(old_act, arg2, 0);
+ pact = &act;
+ } else {
+ pact = NULL;
+ }
+ ret = get_errno(do_sigaction(arg1, pact, &oact));
+ if (!is_error(ret) && arg3) {
+ if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0)) {
+ return -TARGET_EFAULT;
+ }
+ old_act->_sa_handler = oact._sa_handler;
+ old_act->sa_flags = oact.sa_flags;
+ memcpy(&old_act->sa_mask, &oact.sa_mask, sizeof(target_sigset_t));
+ unlock_user_struct(old_act, arg3, 1);
+ }
+ return ret;
+}
+
+
+/* sigprocmask(2) */
+static inline abi_long do_bsd_sigprocmask(abi_long arg1, abi_ulong arg2,
+ abi_ulong arg3)
+{
+ abi_long ret;
+ void *p;
+ sigset_t set, oldset, *set_ptr;
+ int how;
+
+ if (arg2) {
+ switch (arg1) {
+ case TARGET_SIG_BLOCK:
+ how = SIG_BLOCK;
+ break;
+
+ case TARGET_SIG_UNBLOCK:
+ how = SIG_UNBLOCK;
+ break;
+
+ case TARGET_SIG_SETMASK:
+ how = SIG_SETMASK;
+ break;
+
+ default:
+ return -TARGET_EFAULT;
+ }
+ p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1);
+ if (p == NULL) {
+ return -TARGET_EFAULT;
+ }
+ target_to_host_sigset(&set, p);
+ unlock_user(p, arg2, 0);
+ set_ptr = &set;
+ } else {
+ how = 0;
+ set_ptr = NULL;
+ }
+ ret = get_errno(sigprocmask(how, set_ptr, &oldset));
+ if (!is_error(ret) && arg3) {
+ p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0);
+ if (p == NULL) {
+ return -TARGET_EFAULT;
+ }
+ host_to_target_sigset(p, &oldset);
+ unlock_user(p, arg3, sizeof(target_sigset_t));
+ }
+ return ret;
+}
+
+/* sigpending(2) */
+static inline abi_long do_bsd_sigpending(abi_long arg1)
+{
+ abi_long ret;
+ void *p;
+ sigset_t set;
+
+ ret = get_errno(sigpending(&set));
+ if (!is_error(ret)) {
+ p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0);
+ if (p == NULL) {
+ return -TARGET_EFAULT;
+ }
+ host_to_target_sigset(p, &set);
+ unlock_user(p, arg1, sizeof(target_sigset_t));
+ }
+ return ret;
+}
+
+/* sigsuspend(2) */
+static inline abi_long do_bsd_sigsuspend(abi_long arg1, abi_long arg2)
+{
+ void *p;
+ sigset_t set;
+
+ p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
+ if (p == NULL) {
+ return -TARGET_EFAULT;
+ }
+ target_to_host_sigset(&set, p);
+ unlock_user(p, arg1, 0);
+
+ return get_errno(sigsuspend(&set));
+}
+
+/* sigreturn(2) */
+static inline abi_long do_bsd_sigreturn(void *cpu_env, abi_long arg1)
+{
+
+ return do_sigreturn(cpu_env, arg1);
+}
+
+/* sigvec(2) - not defined */
+/* sigblock(2) - not defined */
+/* sigsetmask(2) - not defined */
+/* sigstack(2) - not defined */
+
+/* sigwait(2) */
+static inline abi_long do_bsd_sigwait(abi_ulong arg1, abi_ulong arg2,
+ abi_long arg3)
+{
+ abi_long ret;
+ void *p;
+ sigset_t set;
+ int sig;
+
+ p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
+ if (p == NULL) {
+ return -TARGET_EFAULT;
+ }
+ target_to_host_sigset(&set, p);
+ unlock_user(p, arg1, 0);
+ ret = get_errno(sigwait(&set, &sig));
+ if (!is_error(ret) && arg2) {
+ ret = put_user_s32(sig, arg2);
+ }
+ return ret;
+}
+
+/* sigwaitinfo(2) */
+static inline abi_long do_bsd_sigwaitinfo(abi_ulong arg1, abi_ulong arg2)
+{
+ abi_long ret;
+ void *p;
+ sigset_t set;
+ siginfo_t uinfo;
+
+ p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
+ if (p == NULL) {
+ return -TARGET_EFAULT;
+ }
+ target_to_host_sigset(&set, p);
+ unlock_user(p, arg1, 0);
+ ret = get_errno(sigwaitinfo(&set, &uinfo));
+ if (!is_error(ret) && arg2) {
+ p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0);
+ if (p == NULL) {
+ return -TARGET_EFAULT;
+ }
+ host_to_target_siginfo(p, &uinfo);
+ unlock_user(p, arg2, sizeof(target_siginfo_t));
+ }
+ return ret;
+}
+
+/* sigqueue(2) */
+static inline abi_long do_bsd_sigqueue(abi_long arg1, abi_long arg2,
+ abi_ulong arg3)
+{
+ union sigval value;
+
+ value.sival_ptr = (void *)(uintptr_t)arg3;
+ return get_errno(sigqueue(arg1, target_to_host_signal(arg2), value));
+}
+
+/* sigaltstck(2) */
+static inline abi_long do_bsd_sigaltstack(void *cpu_env, abi_ulong arg1,
+ abi_ulong arg2)
+{
+
+ return do_sigaltstack(arg1, arg2, get_sp_from_cpustate(cpu_env));
+}
+
+/* kill(2) */
+static inline abi_long do_bsd_kill(abi_long pid, abi_long sig)
+{
+
+ return get_errno(kill(pid, target_to_host_signal(sig)));
+}
+
+/* killpg(2) */
+static inline abi_long do_bsd_killpg(abi_long pg, abi_long sig)
+{
+
+ return get_errno(killpg(pg, target_to_host_signal(sig)));
+}
+
+#endif /* ! __BSD_SIGNAL_H_ */
diff --git a/bsd-user/errno_defs.h b/bsd-user/errno_defs.h
index 1efa502..f01181d 100644
--- a/bsd-user/errno_defs.h
+++ b/bsd-user/errno_defs.h
@@ -1,6 +1,3 @@
-/* $OpenBSD: errno.h,v 1.20 2007/09/03 14:37:52 millert Exp $ */
-/* $NetBSD: errno.h,v 1.10 1996/01/20 01:33:53 jtc Exp $ */
-
/*
* Copyright (c) 1982, 1986, 1989, 1993
* The Regents of the University of California. All rights reserved.
@@ -37,6 +34,9 @@
* @(#)errno.h 8.5 (Berkeley) 1/21/94
*/
+#ifndef _ERRNO_DEFS_H_
+#define _ERRNO_DEFS_H_
+
#define TARGET_EPERM 1 /* Operation not permitted */
#define TARGET_ENOENT 2 /* No such file or directory */
#define TARGET_ESRCH 3 /* No such process */
@@ -147,3 +147,10 @@
#define TARGET_EIDRM 89 /* Identifier removed */
#define TARGET_ENOMSG 90 /* No message of desired type
*/
#define TARGET_ELAST 90 /* Must be equal largest errno
*/
+
+/* Internal errors: */
+#define TARGET_EJUSTRETURN 254 /* Just return without
+ modifing regs */
+#define TARGET_ERESTART 255 /* Restart syscall */
+
+#endif /* ! _ERRNO_DEFS_H_ */
diff --git a/bsd-user/freebsd/os-signal.h b/bsd-user/freebsd/os-signal.h
new file mode 100644
index 0000000..d4a26da
--- /dev/null
+++ b/bsd-user/freebsd/os-signal.h
@@ -0,0 +1,43 @@
+/*
+ * FreeBSD signal system call shims
+ *
+ * Copyright (c) 2013 Stacey D. Son
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __FREEBSD_OS_SIGNAL_H_
+#define __FREEBSD_OS_SIGNAL_H_
+
+#include <sys/procdesc.h>
+
+#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
+/* pdkill(2) */
+static inline abi_long do_freebsd_pdkill(abi_long arg1, abi_long arg2)
+{
+
+ return get_errno(pdkill(arg1, arg2));
+}
+
+#else
+
+static inline abi_long do_freebsd_pdkill(abi_long arg1, abi_long arg2)
+{
+
+ qemu_log("qemu: Unsupported syscall pdkill()\n");
+ return -TARGET_ENOSYS;
+}
+#endif /* ! __FreeBSD_version > 900000 */
+
+#endif /* ! __FREEBSD_OS_SIGNAL_H_ */
diff --git a/bsd-user/freebsd/target_os_siginfo.h
b/bsd-user/freebsd/target_os_siginfo.h
new file mode 100644
index 0000000..39180ec
--- /dev/null
+++ b/bsd-user/freebsd/target_os_siginfo.h
@@ -0,0 +1,110 @@
+/*
+ * FreeBSD siginfo related definitions
+ *
+ * Copyright (c) 2013 Stacey D. Son
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _TARGET_OS_SIGINFO_H_
+#define _TARGET_OS_SIGINFO_H_
+
+#define TARGET_NSIG 128
+#define TARGET_NSIG_BPW (sizeof(uint32_t) * 8)
+#define TARGET_NSIG_WORDS (TARGET_NSIG / TARGET_NSIG_BPW)
+
+/* this struct defines a stack used during syscall handling */
+typedef struct target_sigaltstack {
+ abi_long ss_sp;
+ abi_ulong ss_size;
+ abi_long ss_flags;
+} target_stack_t;
+
+typedef struct {
+ uint32_t __bits[TARGET_NSIG_WORDS];
+} target_sigset_t;
+
+struct target_sigaction {
+ abi_ulong _sa_handler;
+ int32_t sa_flags;
+ target_sigset_t sa_mask;
+};
+
+union target_sigval {
+ int32_t sival_int;
+ abi_ulong sival_ptr;
+ int32_t sigval_int;
+ abi_ulong sigval_ptr;
+};
+
+typedef struct target_siginfo {
+ int32_t si_signo; /* signal number */
+ int32_t si_errno; /* errno association */
+ int32_t si_code; /* signal code */
+ int32_t si_pid; /* sending process */
+ int32_t si_uid; /* sender's ruid */
+ int32_t si_status; /* exit value */
+ abi_ulong si_addr; /* faulting instruction */
+ union target_sigval si_value; /* signal value */
+ union {
+ struct {
+ int32_t _trapno; /* machine specific trap code */
+ } _fault;
+
+ /* POSIX.1b timers */
+ struct {
+ int32_t _timerid;
+ int32_t _overrun;
+ } _timer;
+
+ struct {
+ int32_t _mqd;
+ } _mesgp;
+
+ /* SIGPOLL */
+ struct {
+ int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
+ } _poll;
+
+ struct {
+ abi_long __spare1__;
+ int32_t __spare2_[7];
+ } __spare__;
+ } _reason;
+} target_siginfo_t;
+
+#define target_si_signo si_signo
+#define target_si_code si_code
+#define target_si_errno si_errno
+#define target_si_addr si_addr
+
+/* SIGILL si_codes */
+#define TARGET_ILL_ILLOPC (1) /* Illegal opcode. */
+#define TARGET_ILL_ILLOPN (2) /* Illegal operand. */
+#define TARGET_ILL_ILLADR (3) /* Illegal addressing mode. */
+#define TARGET_ILL_ILLTRP (4) /* Illegal trap. */
+#define TARGET_ILL_PRVOPC (5) /* Privileged opcode. */
+#define TARGET_ILL_PRVREG (6) /* Privileged register. */
+#define TARGET_ILL_COPROC (7) /* Coprocessor error. */
+#define TARGET_ILL_BADSTK (8) /* Internal stack error. */
+
+/* SIGSEGV si_codes */
+#define TARGET_SEGV_MAPERR (1) /* address not mapped to object */
+#define TARGET_SEGV_ACCERR (2) /* invalid permissions for mapped
+ object */
+
+/* SIGTRAP si_codes */
+#define TARGET_TRAP_BRKPT (1) /* process beakpoint */
+#define TARGET_TRAP_TRACE (2) /* process trace trap */
+
+#endif /* !_TARGET_OS_SIGINFO_H_ */
diff --git a/bsd-user/freebsd/target_os_signal.h
b/bsd-user/freebsd/target_os_signal.h
new file mode 100644
index 0000000..d7004c8
--- /dev/null
+++ b/bsd-user/freebsd/target_os_signal.h
@@ -0,0 +1,79 @@
+#ifndef _TARGET_OS_SIGNAL_H_
+#define _TARGET_OS_SIGNAL_H_
+
+#include "target_os_siginfo.h"
+#include "target_arch_signal.h"
+
+/* Compare to sys/signal.h */
+#define TARGET_SIGHUP 1 /* hangup */
+#define TARGET_SIGINT 2 /* interrupt */
+#define TARGET_SIGQUIT 3 /* quit */
+#define TARGET_SIGILL 4 /* illegal instruction (not reset when caught)
*/
+#define TARGET_SIGTRAP 5 /* trace trap (not reset when caught) */
+#define TARGET_SIGABRT 6 /* abort() */
+#define TARGET_SIGIOT SIGABRT /* compatibility */
+#define TARGET_SIGEMT 7 /* EMT instruction */
+#define TARGET_SIGFPE 8 /* floating point exception */
+#define TARGET_SIGKILL 9 /* kill (cannot be caught or ignored) */
+#define TARGET_SIGBUS 10 /* bus error */
+#define TARGET_SIGSEGV 11 /* segmentation violation */
+#define TARGET_SIGSYS 12 /* bad argument to system call */
+#define TARGET_SIGPIPE 13 /* write on a pipe with no one to read it */
+#define TARGET_SIGALRM 14 /* alarm clock */
+#define TARGET_SIGTERM 15 /* software termination signal from kill */
+#define TARGET_SIGURG 16 /* urgent condition on IO channel */
+#define TARGET_SIGSTOP 17 /* sendable stop signal not from tty */
+#define TARGET_SIGTSTP 18 /* stop signal from tty */
+#define TARGET_SIGCONT 19 /* continue a stopped process */
+#define TARGET_SIGCHLD 20 /* to parent on child stop or exit */
+#define TARGET_SIGTTIN 21 /* to readers pgrp upon background tty read */
+#define TARGET_SIGTTOU 22 /* like TTIN for output
if(tp->t_local<OSTOP)*/
+#define TARGET_SIGIO 23 /* input/output possible signal */
+#define TARGET_SIGXCPU 24 /* exceeded CPU time limit */
+#define TARGET_SIGXFSZ 25 /* exceeded file size limit */
+#define TARGET_SIGVTALRM 26 /* virtual time alarm */
+#define TARGET_SIGPROF 27 /* profiling time alarm */
+#define TARGET_SIGWINCH 28 /* window size changes */
+#define TARGET_SIGINFO 29 /* information request */
+#define TARGET_SIGUSR1 30 /* user defined signal 1 */
+#define TARGET_SIGUSR2 31 /* user defined signal 2 */
+#define TARGET_SIGTHR 32 /* reserved by thread library */
+#define TARGET_SIGLWP SIGTHR /* compatibility */
+#define TARGET_SIGLIBRT 33 /* reserved by the real-time library */
+#define TARGET_SIGRTMIN 65
+#define TARGET_SIGRTMAX 126
+#define TARGET_QEMU_ESIGRETURN 255 /* fake errno value for use by sigreturn */
+
+/*
+ * Language spec says we must list exactly one parameter, even though we
+ * actually supply three. Ugh!
+ */
+#define TARGET_SIG_DFL ((abi_long)0) /* default signal handling */
+#define TARGET_SIG_IGN ((abi_long)1) /* ignore signal */
+#define TARGET_SIG_ERR ((abi_long)-1) /* error return from signal */
+
+#define TARGET_SA_ONSTACK 0x0001 /* take signal on signal stack */
+#define TARGET_SA_RESTART 0x0002 /* restart system on signal return */
+#define TARGET_SA_RESETHAND 0x0004 /* reset to SIG_DFL when taking signal */
+#define TARGET_SA_NODEFER 0x0010 /* don't mask the signal we're delivering
*/
+#define TARGET_SA_NOCLDWAIT 0x0020 /* don't create zombies (assign to pid 1)
*/
+#define TARGET_SA_USERTRAMP 0x0100 /* do not bounce off kernel's sigtramp */
+#define TARGET_SA_NOCLDSTOP 0x0008 /* do not generate SIGCHLD on child stop */
+#define TARGET_SA_SIGINFO 0x0040 /* generate siginfo_t */
+
+/*
+ * Flags for sigprocmask:
+ */
+#define TARGET_SIG_BLOCK 1 /* block specified signal set */
+#define TARGET_SIG_UNBLOCK 2 /* unblock specified signal set */
+#define TARGET_SIG_SETMASK 3 /* set specified signal set */
+
+#define TARGET_BADSIG SIG_ERR
+
+/*
+ * sigaltstack control
+ */
+#define TARGET_SS_ONSTACK 0x0001 /* take signals on alternate stack */
+#define TARGET_SS_DISABLE 0x0004 /* disable taking signals on alternate
stack*/
+
+#endif /* !_TARGET_OS_SIGNAL_H_ */
diff --git a/bsd-user/i386/target_arch_signal.h
b/bsd-user/i386/target_arch_signal.h
new file mode 100644
index 0000000..e2387b2
--- /dev/null
+++ b/bsd-user/i386/target_arch_signal.h
@@ -0,0 +1,94 @@
+/*
+ * i386 dependent signal definitions
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef TARGET_ARCH_SIGNAL_H
+#define TARGET_ARCH_SIGNAL_H
+
+#include "cpu.h"
+
+/* Size of the signal trampolin code placed on the stack. */
+/* #define TARGET_SZSIGCODE (0) */ /* XXX to be added. */
+
+/* compare to x86/include/_limits.h */
+#define TARGET_MINSIGSTKSZ (512 * 4) /* min sig stack size */
+#define TARGET_SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended size */
+
+#define TARGET_MC_GET_CLEAR_RET 0x0001
+
+struct target_sigcontext {
+ /* to be added */
+};
+
+typedef struct target_mcontext {
+} target_mcontext_t;
+
+typedef struct target_ucontext {
+ target_sigset_t uc_sigmask;
+ target_mcontext_t uc_mcontext;
+ abi_ulong uc_link;
+ target_stack_t uc_stack;
+ int32_t uc_flags;
+ int32_t __spare__[4];
+} target_ucontext_t;
+
+struct target_sigframe {
+ abi_ulong sf_signum;
+ abi_ulong sf_siginfo; /* code or pointer to sf_si */
+ abi_ulong sf_ucontext; /* points to sf_uc */
+ abi_ulong sf_addr; /* undocumented 4th arg */
+ target_ucontext_t sf_uc; /* = *sf_uncontext */
+ target_siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case)*/
+ uint32_t __spare__[2];
+};
+
+/*
+ * Compare to i386/i386/machdep.c sendsig()
+ * Assumes that target stack frame memory is locked.
+ */
+static inline abi_long set_sigtramp_args(CPUX86State *regs,
+ int sig, struct target_sigframe *frame, abi_ulong frame_addr,
+ struct target_sigaction *ka)
+{
+ /* XXX */
+ return -TARGET_EOPNOTSUPP;
+}
+
+/* Compare to i386/i386/machdep.c get_mcontext() */
+static inline abi_long get_mcontext(CPUX86State *regs,
+ target_mcontext_t *mcp, int flags)
+{
+ /* XXX */
+ return -TARGET_EOPNOTSUPP;
+}
+
+/* Compare to i386/i386/machdep.c set_mcontext() */
+static inline abi_long set_mcontext(CPUX86State *regs,
+ target_mcontext_t *mcp, int srflag)
+{
+ /* XXX */
+ return -TARGET_EOPNOTSUPP;
+}
+
+static inline abi_long get_ucontext_sigreturn(CPUX86State *regs,
+ abi_ulong target_sf, abi_ulong *target_uc)
+{
+ /* XXX */
+ *target_uc = 0;
+ return -TARGET_EOPNOTSUPP;
+}
+
+#endif /* TARGET_ARCH_SIGNAL_H */
diff --git a/bsd-user/mips/target_arch_signal.h
b/bsd-user/mips/target_arch_signal.h
new file mode 100644
index 0000000..79d6f65
--- /dev/null
+++ b/bsd-user/mips/target_arch_signal.h
@@ -0,0 +1,237 @@
+/*
+ * mips signal definitions
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _TARGET_ARCH_SIGNAL_H_
+#define _TARGET_ARCH_SIGNAL_H_
+
+#include "cpu.h"
+
+#define TARGET_INSN_SIZE 4 /* mips instruction size */
+
+/* Size of the signal trampolin code. See insall_sigtramp(). */
+#define TARGET_SZSIGCODE ((abi_ulong)(4 * TARGET_INSN_SIZE))
+
+/* compare to mips/include/_limits.h */
+#define TARGET_MINSIGSTKSZ (512 * 4) /* min sig stack size
*/
+#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768) /* recommended size
*/
+
+/* compare to sys/mips/include/asm.h */
+#define TARGET_SZREG 8
+#define TARGET_CALLFRAME_SIZ (TARGET_SZREG * 4)
+
+/* mips/mips/pm_machdep.c */
+#define TARGET_UCONTEXT_MAGIC 0xACEDBADE
+#define TARGET_MC_GET_CLEAR_RET 0x0001
+#define TARGET_MC_ADD_MAGIC 0x0002
+#define TARGET_MC_SET_ONSTACK 0x0004
+
+struct target_sigcontext {
+ target_sigset_t sc_mask; /* signal mask to retstore */
+ int32_t sc_onstack; /* sigstack state to restore */
+ abi_long sc_pc; /* pc at time of signal */
+ abi_long sc_reg[32]; /* processor regs 0 to 31 */
+ abi_long mullo, mulhi; /* mullo and mulhi registers */
+ int32_t sc_fpused; /* fp has been used */
+ abi_long sc_fpregs[33]; /* fp regs 0 to 31 & csr */
+ abi_long sc_fpc_eir; /* fp exception instr reg */
+ /* int32_t reserved[8]; */
+};
+
+typedef struct target_mcontext {
+ int32_t mc_onstack; /* sigstack state to restore */
+ abi_long mc_pc; /* pc at time of signal */
+ abi_long mc_regs[32]; /* process regs 0 to 31 */
+ abi_long sr; /* status register */
+ abi_long mullo, mulhi;
+ int32_t mc_fpused; /* fp has been used */
+ abi_long mc_fpregs[33]; /* fp regs 0 to 32 & csr */
+ abi_long mc_fpc_eir; /* fp exception instr reg */
+ abi_ulong mc_tls; /* pointer to TLS area */
+} target_mcontext_t;
+
+typedef struct target_ucontext {
+ target_sigset_t uc_sigmask;
+ target_mcontext_t uc_mcontext;
+ abi_ulong uc_link;
+ target_stack_t uc_stack;
+ int32_t uc_flags;
+ int32_t __spare__[4];
+} target_ucontext_t;
+
+struct target_sigframe {
+ abi_ulong sf_signum;
+ abi_ulong sf_siginfo; /* code or pointer to sf_si */
+ abi_ulong sf_ucontext; /* points to sf_uc */
+ abi_ulong sf_addr; /* undocumented 4th arg */
+ target_ucontext_t sf_uc; /* = *sf_uncontext */
+ target_siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case)*/
+ uint32_t __spare__[2];
+};
+
+/*
+ * Compare to mips/mips/pm_machdep.c sendsig()
+ * Assumes that target stack frame memory is locked.
+ */
+static inline abi_long
+set_sigtramp_args(CPUMIPSState *regs, int sig, struct target_sigframe *frame,
+ abi_ulong frame_addr, struct target_sigaction *ka)
+{
+
+ /* frame->sf_si.si_addr = regs->CP0_BadVAddr; */
+
+ /* MIPS only struct target_sigframe members: */
+ frame->sf_signum = sig;
+ frame->sf_siginfo = frame_addr + offsetof(struct target_sigframe, sf_si);
+ frame->sf_ucontext = frame_addr + offsetof(struct target_sigframe, sf_uc);
+
+ /*
+ * Arguments to signal handler:
+ * a0 ($4) = signal number
+ * a1 ($5) = siginfo pointer
+ * a2 ($6) = ucontext pointer
+ * PC = signal handler pointer
+ * t9 ($25) = signal handler pointer
+ * $29 = point to sigframe struct
+ * ra ($31) = sigtramp at base of user stack
+ */
+ regs->active_tc.gpr[4] = sig;
+ regs->active_tc.gpr[5] = frame_addr +
+ offsetof(struct target_sigframe, sf_si);
+ regs->active_tc.gpr[6] = frame_addr +
+ offsetof(struct target_sigframe, sf_uc);
+ regs->active_tc.gpr[25] = regs->active_tc.PC = ka->_sa_handler;
+ regs->active_tc.gpr[29] = frame_addr;
+ regs->active_tc.gpr[31] = TARGET_PS_STRINGS - TARGET_SZSIGCODE;
+
+ return 0;
+}
+
+/*
+ * Compare to mips/mips/pm_machdep.c get_mcontext()
+ * Assumes that the memory is locked if mcp points to user memory.
+ */
+static inline abi_long get_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp,
+ int flags)
+{
+ int i, err = 0;
+
+ if (flags & TARGET_MC_ADD_MAGIC) {
+ mcp->mc_regs[0] = tswapal(TARGET_UCONTEXT_MAGIC);
+ } else {
+ mcp->mc_regs[0] = 0;
+ }
+
+ if (flags & TARGET_MC_SET_ONSTACK) {
+ mcp->mc_onstack = tswapal(1);
+ } else {
+ mcp->mc_onstack = 0;
+ }
+
+ for (i = 1; i < 32; i++) {
+ mcp->mc_regs[i] = tswapal(regs->active_tc.gpr[i]);
+ }
+
+#if 0 /* XXX FP is not used right now */
+ abi_ulong used_fp = used_math() ? TARGET_MDTD_FPUSED : 0;
+
+ mcp->mc_fpused = used_fp;
+ if (used_fp) {
+ preempt_disable();
+ if (!is_fpu_owner()) {
+ own_fpu();
+ for (i = 0; i < 33; i++) {
+ mcp->mc_fpregs[i] = tswapal(regs->active_fpu.fpr[i]);
+ }
+ }
+ preempt_enable();
+ }
+#else
+ mcp->mc_fpused = 0;
+#endif
+
+ if (flags & TARGET_MC_GET_CLEAR_RET) {
+ mcp->mc_regs[2] = 0; /* v0 = 0 */
+ mcp->mc_regs[3] = 0; /* v1 = 0 */
+ mcp->mc_regs[7] = 0; /* a3 = 0 */
+ }
+
+ mcp->mc_pc = tswapal(regs->active_tc.PC);
+ mcp->mullo = tswapal(regs->active_tc.LO[0]);
+ mcp->mulhi = tswapal(regs->active_tc.HI[0]);
+ mcp->mc_tls = tswapal(regs->tls_value);
+
+ /* Don't do any of the status and cause registers. */
+
+ return err;
+}
+
+/* Compare to mips/mips/pm_machdep.c set_mcontext() */
+static inline abi_long set_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp,
+ int srflag)
+{
+ int i, err = 0;
+
+ for (i = 1; i < 32; i++) {
+ regs->active_tc.gpr[i] = tswapal(mcp->mc_regs[i]);
+ }
+
+#if 0 /* XXX FP is not used right now */
+ abi_ulong used_fp = 0;
+
+ used_fp = tswapal(mcp->mc_fpused)
+ conditional_used_math(used_fp);
+
+ preempt_disabled();
+ if (used_math()) {
+ /* restore fpu context if we have used it before */
+ own_fpu();
+ for (i = 0; i < 32; i++) {
+ regs->active_fpu.fpr[i] = tswapal(mcp->mc_fpregs[i]);
+ }
+ } else {
+ /* Signal handler may have used FPU. Give it up. */
+ lose_fpu();
+ }
+ preempt_enable();
+#endif
+
+ regs->CP0_EPC = tswapal(mcp->mc_pc);
+ regs->active_tc.LO[0] = tswapal(mcp->mullo);
+ regs->active_tc.HI[0] = tswapal(mcp->mulhi);
+ regs->tls_value = tswapal(mcp->mc_tls);
+
+ if (srflag) {
+ /* doing sigreturn() */
+ regs->active_tc.PC = regs->CP0_EPC;
+ regs->CP0_EPC = 0; /* XXX for nested signals ? */
+ }
+
+ /* Don't do any of the status and cause registers. */
+
+ return err;
+}
+
+static inline abi_long get_ucontext_sigreturn(CPUMIPSState *regs,
+ abi_ulong target_sf, abi_ulong *target_uc)
+{
+
+ *target_uc = target_sf;
+ return 0;
+}
+
+
+#endif /* !_TARGET_ARCH_SIGNAL_H_ */
diff --git a/bsd-user/mips64/target_arch_signal.h
b/bsd-user/mips64/target_arch_signal.h
new file mode 100644
index 0000000..07d281e
--- /dev/null
+++ b/bsd-user/mips64/target_arch_signal.h
@@ -0,0 +1,236 @@
+/*
+ * mips64 signal definitions
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _TARGET_ARCH_SIGNAL_H_
+#define _TARGET_ARCH_SIGNAL_H_
+
+#include "cpu.h"
+
+#define TARGET_INSN_SIZE 4 /* mips64 instruction size */
+
+/* Size of the signal trampolin code placed on the stack. */
+#define TARGET_SZSIGCODE ((abi_ulong)(4 * TARGET_INSN_SIZE))
+
+#define TARGET_MINSIGSTKSZ (512 * 4)
+#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
+
+/* compare to sys/mips/include/asm.h */
+#define TARGET_SZREG 8
+#define TARGET_CALLFRAME_SIZ (TARGET_SZREG * 4)
+
+/* mips/mips/pm_machdep.c */
+#define TARGET_UCONTEXT_MAGIC 0xACEDBADE
+#define TARGET_MC_GET_CLEAR_RET 0x0001
+#define TARGET_MC_ADD_MAGIC 0x0002
+#define TARGET_MC_SET_ONSTACK 0x0004
+
+struct target_sigcontext {
+ target_sigset_t sc_mask; /* signal mask to retstore */
+ int32_t sc_onstack; /* sigstack state to restore */
+ abi_long sc_pc; /* pc at time of signal */
+ abi_long sc_reg[32]; /* processor regs 0 to 31 */
+ abi_long mullo, mulhi; /* mullo and mulhi registers */
+ int32_t sc_fpused; /* fp has been used */
+ abi_long sc_fpregs[33]; /* fp regs 0 to 31 & csr */
+ abi_long sc_fpc_eir; /* fp exception instr reg */
+ /* int32_t reserved[8]; */
+};
+
+typedef struct target_mcontext {
+ int32_t mc_onstack; /* sigstack state to restore */
+ abi_long mc_pc; /* pc at time of signal */
+ abi_long mc_regs[32]; /* process regs 0 to 31 */
+ abi_long sr; /* status register */
+ abi_long mullo, mulhi;
+ int32_t mc_fpused; /* fp has been used */
+ abi_long mc_fpregs[33]; /* fp regs 0 to 32 & csr */
+ abi_long mc_fpc_eir; /* fp exception instr reg */
+ abi_ulong mc_tls; /* pointer to TLS area */
+} target_mcontext_t;
+
+typedef struct target_ucontext {
+ target_sigset_t uc_sigmask;
+ target_mcontext_t uc_mcontext;
+ abi_ulong uc_link;
+ target_stack_t uc_stack;
+ int32_t uc_flags;
+ int32_t __spare__[4];
+} target_ucontext_t;
+
+struct target_sigframe {
+ abi_ulong sf_signum;
+ abi_ulong sf_siginfo; /* code or pointer to sf_si */
+ abi_ulong sf_ucontext; /* points to sf_uc */
+ abi_ulong sf_addr; /* undocumented 4th arg */
+ target_ucontext_t sf_uc; /* = *sf_uncontext */
+ target_siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case)*/
+ uint32_t __spare__[2];
+};
+
+/*
+ * Compare to mips/mips/pm_machdep.c sendsig()
+ * Assumes that target stack frame memory is locked.
+ */
+static inline abi_long
+set_sigtramp_args(CPUMIPSState *regs, int sig, struct target_sigframe *frame,
+ abi_ulong frame_addr, struct target_sigaction *ka)
+{
+
+ /* frame->sf_si.si_addr = regs->CP0_BadVAddr; */
+
+ /* MIPS only struct target_sigframe members: */
+ frame->sf_signum = sig;
+ frame->sf_siginfo = frame_addr + offsetof(struct target_sigframe, sf_si);
+ frame->sf_ucontext = frame_addr + offsetof(struct target_sigframe, sf_uc);
+
+ /*
+ * Arguments to signal handler:
+ * a0 ($4) = signal number
+ * a1 ($5) = siginfo pointer
+ * a2 ($6) = ucontext pointer
+ * PC = signal handler pointer
+ * t9 ($25) = signal handler pointer
+ * $29 = point to sigframe struct
+ * ra ($31) = sigtramp at base of user stack
+ */
+ regs->active_tc.gpr[4] = sig;
+ regs->active_tc.gpr[5] = frame_addr +
+ offsetof(struct target_sigframe, sf_si);
+ regs->active_tc.gpr[6] = frame_addr +
+ offsetof(struct target_sigframe, sf_uc);
+ regs->active_tc.gpr[25] = regs->active_tc.PC = ka->_sa_handler;
+ regs->active_tc.gpr[29] = frame_addr;
+ regs->active_tc.gpr[31] = TARGET_PS_STRINGS - TARGET_SZSIGCODE;
+
+ return 0;
+}
+
+/*
+ * Compare to mips/mips/pm_machdep.c get_mcontext()
+ * Assumes that the memory is locked if mcp points to user memory.
+ */
+static inline abi_long get_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp,
+ int flags)
+{
+ int i, err = 0;
+
+ if (flags & TARGET_MC_ADD_MAGIC) {
+ mcp->mc_regs[0] = tswapal(TARGET_UCONTEXT_MAGIC);
+ } else {
+ mcp->mc_regs[0] = 0;
+ }
+
+ if (flags & TARGET_MC_SET_ONSTACK) {
+ mcp->mc_onstack = tswapal(1);
+ } else {
+ mcp->mc_onstack = 0;
+ }
+
+ for (i = 1; i < 32; i++) {
+ mcp->mc_regs[i] = tswapal(regs->active_tc.gpr[i]);
+ }
+
+#if 0 /* XXX FP is not used right now */
+ abi_ulong used_fp = used_math() ? TARGET_MDTD_FPUSED : 0;
+
+ mcp->mc_fpused = used_fp;
+ if (used_fp) {
+ preempt_disable();
+ if (!is_fpu_owner()) {
+ own_fpu();
+ for (i = 0; i < 33; i++) {
+ mcp->mc_fpregs[i] = tswapal(regs->active_fpu.fpr[i]);
+ }
+ }
+ preempt_enable();
+ }
+#else
+ mcp->mc_fpused = 0;
+#endif
+
+ if (flags & TARGET_MC_GET_CLEAR_RET) {
+ mcp->mc_regs[2] = 0; /* v0 = 0 */
+ mcp->mc_regs[3] = 0; /* v1 = 0 */
+ mcp->mc_regs[7] = 0; /* a3 = 0 */
+ }
+
+ mcp->mc_pc = tswapal(regs->active_tc.PC);
+ mcp->mullo = tswapal(regs->active_tc.LO[0]);
+ mcp->mulhi = tswapal(regs->active_tc.HI[0]);
+ mcp->mc_tls = tswapal(regs->tls_value);
+
+ /* Don't do any of the status and cause registers. */
+
+ return err;
+}
+
+/* Compare to mips/mips/pm_machdep.c set_mcontext() */
+static inline abi_long set_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp,
+ int srflag)
+{
+ int i, err = 0;
+
+ for (i = 1; i < 32; i++) {
+ regs->active_tc.gpr[i] = tswapal(mcp->mc_regs[i]);
+ }
+
+#if 0 /* XXX FP is not used right now */
+ abi_ulong used_fp = 0;
+
+ used_fp = tswapal(mcp->mc_fpused)
+ conditional_used_math(used_fp);
+
+ preempt_disabled();
+ if (used_math()) {
+ /* restore fpu context if we have used it before */
+ own_fpu();
+ for (i = 0; i < 32; i++) {
+ regs->active_fpu.fpr[i] = tswapal(mcp->mc_fpregs[i]);
+ }
+ } else {
+ /* Signal handler may have used FPU. Give it up. */
+ lose_fpu();
+ }
+ preempt_enable();
+#endif
+
+ regs->CP0_EPC = tswapal(mcp->mc_pc);
+ regs->active_tc.LO[0] = tswapal(mcp->mullo);
+ regs->active_tc.HI[0] = tswapal(mcp->mulhi);
+ regs->tls_value = tswapal(mcp->mc_tls);
+
+ if (srflag) {
+ /* doing sigreturn() */
+ regs->active_tc.PC = regs->CP0_EPC;
+ regs->CP0_EPC = 0; /* XXX for nested signals ? */
+ }
+
+ /* Don't do any of the status and cause registers. */
+
+ return err;
+}
+
+static inline abi_long get_ucontext_sigreturn(CPUMIPSState *regs,
+ abi_ulong target_sf, abi_ulong *target_uc)
+{
+
+ /* mips passes ucontext struct as the stack frame */
+ *target_uc = target_sf;
+ return 0;
+}
+
+#endif /* !_TARGET_ARCH_SIGNAL_H_ */
diff --git a/bsd-user/netbsd/target_os_siginfo.h
b/bsd-user/netbsd/target_os_siginfo.h
new file mode 100644
index 0000000..667c19c
--- /dev/null
+++ b/bsd-user/netbsd/target_os_siginfo.h
@@ -0,0 +1,82 @@
+#ifndef _TARGET_OS_SIGINFO_H_
+#define _TARGET_OS_SIGINFO_H_
+
+#define TARGET_NSIG 32 /* counting 0; could be 33 (mask is 1-32) */
+#define TARGET_NSIG_BPW (sizeof(uint32_t) * 8)
+#define TARGET_NSIG_WORDS (TARGET_NSIG / TARGET_NSIG_BPW)
+
+/* this struct defines a stack used during syscall handling */
+typedef struct target_sigaltstack {
+ abi_long ss_sp;
+ abi_ulong ss_size;
+ abi_long ss_flags;
+} target_stack_t;
+
+typedef struct {
+ uint32_t __bits[TARGET_NSIG_WORDS];
+} target_sigset_t
+
+struct target_sigaction {
+ abi_ulong _sa_handler;
+ int32_t sa_flags;
+ target_sigset_t sa_mask;
+};
+
+/* Compare to sys/siginfo.h */
+typedef union target_sigval {
+ int sival_int;
+ abi_ulong sival_ptr;
+} target_sigval_t;
+
+struct target_ksiginfo {
+ int32_t _signo;
+ int32_t _code;
+ int32_t _errno;
+#if TARGET_ABI_BITS == 64
+ int32_t _pad;
+#endif
+ union {
+ struct {
+ int32_t _pid;
+ int32_t _uid;
+ target_sigval_t _value;
+ } _rt;
+
+ struct {
+ int32_t _pid;
+ int32_t _uid;
+ int32_t _struct;
+ /* clock_t _utime; */
+ /* clock_t _stime; */
+ } _child;
+
+ struct {
+ abi_ulong _addr;
+ int32_t _trap;
+ } _fault;
+
+ struct {
+ long _band;
+ int _fd;
+ } _poll;
+ } _reason;
+};
+
+typedef union target_siginfo {
+ int8_t si_pad[128];
+ struct target_ksiginfo _info;
+} target_siginfo_t;
+
+#define target_si_signo _info._signo
+#define target_si_code _info._code
+#define target_si_errno _info._errno
+#define target_si_addr _info._reason._fault._addr
+
+#define TARGET_SEGV_MAPERR 1
+#define TARGET_SEGV_ACCERR 2
+
+#define TARGET_TRAP_BRKPT 1
+#define TARGET_TRAP_TRACE 2
+
+
+#endif /* ! _TARGET_OS_SIGINFO_H_ */
diff --git a/bsd-user/netbsd/target_os_signal.h
b/bsd-user/netbsd/target_os_signal.h
new file mode 100644
index 0000000..d39a26f
--- /dev/null
+++ b/bsd-user/netbsd/target_os_signal.h
@@ -0,0 +1,70 @@
+#ifndef _TARGET_OS_SIGNAL_H_
+#define _TARGET_OS_SIGNAL_H_
+
+#include "target_os_siginfo.h"
+#include "target_arch_signal.h"
+
+#define TARGET_SIGHUP 1 /* hangup */
+#define TARGET_SIGINT 2 /* interrupt */
+#define TARGET_SIGQUIT 3 /* quit */
+#define TARGET_SIGILL 4 /* illegal instruction (not reset when caught)
*/
+#define TARGET_SIGTRAP 5 /* trace trap (not reset when caught) */
+#define TARGET_SIGABRT 6 /* abort() */
+#define TARGET_SIGIOT SIGABRT /* compatibility */
+#define TARGET_SIGEMT 7 /* EMT instruction */
+#define TARGET_SIGFPE 8 /* floating point exception */
+#define TARGET_SIGKILL 9 /* kill (cannot be caught or ignored) */
+#define TARGET_SIGBUS 10 /* bus error */
+#define TARGET_SIGSEGV 11 /* segmentation violation */
+#define TARGET_SIGSYS 12 /* bad argument to system call */
+#define TARGET_SIGPIPE 13 /* write on a pipe with no one to read it */
+#define TARGET_SIGALRM 14 /* alarm clock */
+#define TARGET_SIGTERM 15 /* software termination signal from kill */
+#define TARGET_SIGURG 16 /* urgent condition on IO channel */
+#define TARGET_SIGSTOP 17 /* sendable stop signal not from tty */
+#define TARGET_SIGTSTP 18 /* stop signal from tty */
+#define TARGET_SIGCONT 19 /* continue a stopped process */
+#define TARGET_SIGCHLD 20 /* to parent on child stop or exit */
+#define TARGET_SIGTTIN 21 /* to readers pgrp upon background tty read */
+#define TARGET_SIGTTOU 22 /* like TTIN for output if
+ (tp->t_local<OSTOP) */
+#define TARGET_SIGIO 23 /* input/output possible signal */
+#define TARGET_SIGXCPU 24 /* exceeded CPU time limit */
+#define TARGET_SIGXFSZ 25 /* exceeded file size limit */
+#define TARGET_SIGVTALRM 26 /* virtual time alarm */
+#define TARGET_SIGPROF 27 /* profiling time alarm */
+#define TARGET_SIGWINCH 28 /* window size changes */
+#define TARGET_SIGINFO 29 /* information request */
+#define TARGET_SIGUSR1 30 /* user defined signal 1 */
+#define TARGET_SIGUSR2 31 /* user defined signal 2 */
+
+/*
+ * Language spec says we must list exactly one parameter, even though we
+ * actually supply three. Ugh!
+ */
+#define TARGET_SIG_DFL ((void (*)(int))0)
+#define TARGET_SIG_IGN ((void (*)(int))1)
+#define TARGET_SIG_ERR ((void (*)(int))-1)
+
+#define TARGET_SA_ONSTACK 0x0001 /* take signal on signal stack */
+#define TARGET_SA_RESTART 0x0002 /* restart system on signal return */
+#define TARGET_SA_RESETHAND 0x0004 /* reset to SIG_DFL when taking signal */
+#define TARGET_SA_NODEFER 0x0010 /* don't mask the signal we're delivering
*/
+#define TARGET_SA_NOCLDWAIT 0x0020 /* don't create zombies (assign to pid 1)
*/
+#define TARGET_SA_USERTRAMP 0x0100 /* do not bounce off kernel's sigtramp */
+#define TARGET_SA_NOCLDSTOP 0x0008 /* do not generate SIGCHLD on child stop */
+#define TARGET_SA_SIGINFO 0x0040 /* generate siginfo_t */
+
+/*
+ * Flags for sigprocmask:
+ */
+#define TARGET_SIG_BLOCK 1 /* block specified signal set */
+#define TARGET_SIG_UNBLOCK 2 /* unblock specified signal set */
+#define TARGET_SIG_SETMASK 3 /* set specified signal set */
+
+#define TARGET_BADSIG SIG_ERR
+
+#define TARGET_SS_ONSTACK 0x0001 /* take signals on alternate stack */
+#define TARGET_SS_DISABLE 0x0004 /* disable taking signals on alternate stack
*/
+
+#endif /* !_TARGET_OS_SIGNAL_H_ */
diff --git a/bsd-user/openbsd/target_os_siginfo.h
b/bsd-user/openbsd/target_os_siginfo.h
new file mode 100644
index 0000000..baf646a
--- /dev/null
+++ b/bsd-user/openbsd/target_os_siginfo.h
@@ -0,0 +1,82 @@
+#ifndef _TARGET_OS_SIGINFO_H_
+#define _TARGET_OS_SIGINFO_H_
+
+#define TARGET_NSIG 32 /* counting 0; could be 33 (mask is 1-32) */
+#define TARGET_NSIG_BPW (sizeof(uint32_t) * 8)
+#define TARGET_NSIG_WORDS (TARGET_NSIG / TARGET_NSIG_BPW)
+
+/* this struct defines a stack used during syscall handling */
+typedef struct target_sigaltstack {
+ abi_long ss_sp;
+ abi_ulong ss_size;
+ abi_long ss_flags;
+} target_stack_t;
+
+typedef struct {
+ uint32_t __bits[TARGET_NSIG_WORDS];
+} target_sigset_t
+
+struct target_sigaction {
+ abi_ulong _sa_handler;
+ int32_t sa_flags;
+ target_sigset_t sa_mask;
+};
+
+/* Compare to sys/siginfo.h */
+typedef union target_sigval {
+ int sival_int;
+ abi_ulong sival_ptr;
+} target_sigval_t;
+
+struct target_ksiginfo {
+ int32_t _signo;
+ int32_t _code;
+ int32_t _errno;
+#if TARGET_ABI_BITS == 64
+ int32_t _pad;
+#endif
+ union {
+ struct {
+ int32_t _pid;
+ int32_t _uid;
+ target_sigval_t _value;
+ } _rt;
+
+ struct {
+ int32_t _pid;
+ int32_t _uid;
+ int32_t _struct;
+ /* clock_t _utime; */
+ /* clock_t _stime; */
+ } _child;
+
+ struct {
+ abi_ulong _addr;
+ int32_t _trap;
+ } _fault;
+
+ struct {
+ long _band;
+ int _fd;
+ } _poll;
+ } _reason;
+};
+
+typedef union target_siginfo {
+ int8_t si_pad[128];
+ struct target_ksiginfo _info;
+} target_siginfo_t;
+
+#define target_si_signo _info._signo
+#define target_si_code _info._code
+#define target_si_errno _info._errno
+#define target_si_addr _info._reason._fault._addr
+
+#define TARGET_SEGV_MAPERR 1
+#define TARGET_SEGV_ACCERR 2
+
+#define TARGET_TRAP_BRKPT 1
+#define TARGET_TRAP_TRACE 2
+
+
+#endif /* ! _TARGET_OS_SIGINFO_H_ */
diff --git a/bsd-user/openbsd/target_os_signal.h
b/bsd-user/openbsd/target_os_signal.h
new file mode 100644
index 0000000..d39a26f
--- /dev/null
+++ b/bsd-user/openbsd/target_os_signal.h
@@ -0,0 +1,70 @@
+#ifndef _TARGET_OS_SIGNAL_H_
+#define _TARGET_OS_SIGNAL_H_
+
+#include "target_os_siginfo.h"
+#include "target_arch_signal.h"
+
+#define TARGET_SIGHUP 1 /* hangup */
+#define TARGET_SIGINT 2 /* interrupt */
+#define TARGET_SIGQUIT 3 /* quit */
+#define TARGET_SIGILL 4 /* illegal instruction (not reset when caught)
*/
+#define TARGET_SIGTRAP 5 /* trace trap (not reset when caught) */
+#define TARGET_SIGABRT 6 /* abort() */
+#define TARGET_SIGIOT SIGABRT /* compatibility */
+#define TARGET_SIGEMT 7 /* EMT instruction */
+#define TARGET_SIGFPE 8 /* floating point exception */
+#define TARGET_SIGKILL 9 /* kill (cannot be caught or ignored) */
+#define TARGET_SIGBUS 10 /* bus error */
+#define TARGET_SIGSEGV 11 /* segmentation violation */
+#define TARGET_SIGSYS 12 /* bad argument to system call */
+#define TARGET_SIGPIPE 13 /* write on a pipe with no one to read it */
+#define TARGET_SIGALRM 14 /* alarm clock */
+#define TARGET_SIGTERM 15 /* software termination signal from kill */
+#define TARGET_SIGURG 16 /* urgent condition on IO channel */
+#define TARGET_SIGSTOP 17 /* sendable stop signal not from tty */
+#define TARGET_SIGTSTP 18 /* stop signal from tty */
+#define TARGET_SIGCONT 19 /* continue a stopped process */
+#define TARGET_SIGCHLD 20 /* to parent on child stop or exit */
+#define TARGET_SIGTTIN 21 /* to readers pgrp upon background tty read */
+#define TARGET_SIGTTOU 22 /* like TTIN for output if
+ (tp->t_local<OSTOP) */
+#define TARGET_SIGIO 23 /* input/output possible signal */
+#define TARGET_SIGXCPU 24 /* exceeded CPU time limit */
+#define TARGET_SIGXFSZ 25 /* exceeded file size limit */
+#define TARGET_SIGVTALRM 26 /* virtual time alarm */
+#define TARGET_SIGPROF 27 /* profiling time alarm */
+#define TARGET_SIGWINCH 28 /* window size changes */
+#define TARGET_SIGINFO 29 /* information request */
+#define TARGET_SIGUSR1 30 /* user defined signal 1 */
+#define TARGET_SIGUSR2 31 /* user defined signal 2 */
+
+/*
+ * Language spec says we must list exactly one parameter, even though we
+ * actually supply three. Ugh!
+ */
+#define TARGET_SIG_DFL ((void (*)(int))0)
+#define TARGET_SIG_IGN ((void (*)(int))1)
+#define TARGET_SIG_ERR ((void (*)(int))-1)
+
+#define TARGET_SA_ONSTACK 0x0001 /* take signal on signal stack */
+#define TARGET_SA_RESTART 0x0002 /* restart system on signal return */
+#define TARGET_SA_RESETHAND 0x0004 /* reset to SIG_DFL when taking signal */
+#define TARGET_SA_NODEFER 0x0010 /* don't mask the signal we're delivering
*/
+#define TARGET_SA_NOCLDWAIT 0x0020 /* don't create zombies (assign to pid 1)
*/
+#define TARGET_SA_USERTRAMP 0x0100 /* do not bounce off kernel's sigtramp */
+#define TARGET_SA_NOCLDSTOP 0x0008 /* do not generate SIGCHLD on child stop */
+#define TARGET_SA_SIGINFO 0x0040 /* generate siginfo_t */
+
+/*
+ * Flags for sigprocmask:
+ */
+#define TARGET_SIG_BLOCK 1 /* block specified signal set */
+#define TARGET_SIG_UNBLOCK 2 /* unblock specified signal set */
+#define TARGET_SIG_SETMASK 3 /* set specified signal set */
+
+#define TARGET_BADSIG SIG_ERR
+
+#define TARGET_SS_ONSTACK 0x0001 /* take signals on alternate stack */
+#define TARGET_SS_DISABLE 0x0004 /* disable taking signals on alternate stack
*/
+
+#endif /* !_TARGET_OS_SIGNAL_H_ */
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index 594de5c..0e332af 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -39,7 +39,7 @@ extern enum BSDType bsd_type;
#include "syscall_defs.h"
#include "syscall.h"
#include "target_os_vmparam.h"
-#include "target_signal.h"
+#include "target_os_signal.h"
#include "exec/gdbstub.h"
#if defined(CONFIG_USE_NPTL)
@@ -72,16 +72,16 @@ struct image_info {
#define MAX_SIGQUEUE_SIZE 1024
-struct sigqueue {
- struct sigqueue *next;
- //target_siginfo_t info;
+struct qemu_sigqueue {
+ struct qemu_sigqueue *next;
+ target_siginfo_t info;
};
struct emulated_sigtable {
int pending; /* true if signal is pending */
- struct sigqueue *first;
- struct sigqueue info; /* in order to always have memory for the
- first signal, we put it here */
+ struct qemu_sigqueue *first;
+ struct qemu_sigqueue info; /* in order to always have memory for the
+ first signal, we put it here */
};
/* NOTE: we force a big alignment so that the stack stored after is
@@ -93,8 +93,8 @@ typedef struct TaskState {
struct bsd_binprm *bprm;
struct emulated_sigtable sigtab[TARGET_NSIG];
- struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
- struct sigqueue *first_free; /* first free siginfo queue entry */
+ struct qemu_sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
+ struct qemu_sigqueue *first_free; /* first free siginfo queue entry */
int signal_pending; /* non zero if a signal may be pending */
uint8_t stack[0];
@@ -202,12 +202,19 @@ extern int do_strace;
/* signal.c */
void process_pending_signals(CPUArchState *cpu_env);
void signal_init(void);
-//int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info);
-//void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
-//void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
-long do_sigreturn(CPUArchState *env);
+int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info);
+void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
+void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
+int target_to_host_signal(int sig);
+int host_to_target_signal(int sig);
+void host_to_target_sigset(target_sigset_t *d, const sigset_t *s);
+void target_to_host_sigset(sigset_t *d, const target_sigset_t *s);
+long do_sigreturn(CPUArchState *env, abi_ulong addr);
long do_rt_sigreturn(CPUArchState *env);
abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
+int do_sigaction(int sig, const struct target_sigaction *act,
+ struct target_sigaction *oact);
+void QEMU_NORETURN force_sig(int target_sig);
/* mmap.c */
int target_mprotect(abi_ulong start, abi_ulong len, int prot);
diff --git a/bsd-user/signal.c b/bsd-user/signal.c
index 445f69e..3619b00 100644
--- a/bsd-user/signal.c
+++ b/bsd-user/signal.c
@@ -2,6 +2,7 @@
* Emulation of BSD signals
*
* Copyright (c) 2003 - 2008 Fabrice Bellard
+ * Copyright (c) 2013 Stacey Son
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,16 +24,920 @@
#include <unistd.h>
#include <signal.h>
#include <errno.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
#include "qemu.h"
-#include "target_signal.h"
//#define DEBUG_SIGNAL
+static target_stack_t target_sigaltstack_used = {
+ .ss_sp = 0,
+ .ss_size = 0,
+ .ss_flags = TARGET_SS_DISABLE,
+};
+
+static uint8_t host_to_target_signal_table[TARGET_NSIG] = {
+ [SIGHUP] = TARGET_SIGHUP,
+ [SIGINT] = TARGET_SIGINT,
+ [SIGQUIT] = TARGET_SIGQUIT,
+ [SIGILL] = TARGET_SIGILL,
+ [SIGTRAP] = TARGET_SIGTRAP,
+ [SIGABRT] = TARGET_SIGABRT,
+ [SIGEMT] = TARGET_SIGEMT,
+ [SIGFPE] = TARGET_SIGFPE,
+ [SIGKILL] = TARGET_SIGKILL,
+ [SIGBUS] = TARGET_SIGBUS,
+ [SIGSEGV] = TARGET_SIGSEGV,
+ [SIGSYS] = TARGET_SIGSYS,
+ [SIGPIPE] = TARGET_SIGPIPE,
+ [SIGALRM] = TARGET_SIGALRM,
+ [SIGTERM] = TARGET_SIGTERM,
+ [SIGURG] = TARGET_SIGURG,
+ [SIGSTOP] = TARGET_SIGSTOP,
+ [SIGTSTP] = TARGET_SIGTSTP,
+ [SIGCONT] = TARGET_SIGCONT,
+ [SIGCHLD] = TARGET_SIGCHLD,
+ [SIGTTIN] = TARGET_SIGTTIN,
+ [SIGTTOU] = TARGET_SIGTTOU,
+ [SIGIO] = TARGET_SIGIO,
+ [SIGXCPU] = TARGET_SIGXCPU,
+ [SIGXFSZ] = TARGET_SIGXFSZ,
+ [SIGVTALRM] = TARGET_SIGVTALRM,
+ [SIGPROF] = TARGET_SIGPROF,
+ [SIGWINCH] = TARGET_SIGWINCH,
+ [SIGINFO] = TARGET_SIGINFO,
+ [SIGUSR1] = TARGET_SIGUSR1,
+ [SIGUSR2] = TARGET_SIGUSR2,
+#ifdef SIGTHR
+ [SIGTHR + 3] = TARGET_SIGTHR,
+#endif
+ /* [SIGLWP] = TARGET_SIGLWP, */
+#ifdef SIGLIBRT
+ [SIGLIBRT] = TARGET_SIGLIBRT,
+#endif
+
+ /*
+ * The following signals stay the same.
+ * Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
+ * host libpthread signals. This assumes no one actually uses
+ * SIGRTMAX. To fix this properly we need to manual signal delivery
+ * multiplexed over a single host signal.
+ */
+ [SIGRTMIN] = SIGRTMAX,
+ [SIGRTMAX] = SIGRTMIN,
+};
+
+static uint8_t target_to_host_signal_table[TARGET_NSIG];
+static struct target_sigaction sigact_table[TARGET_NSIG];
+static void host_signal_handler(int host_signum, siginfo_t *info, void *puc);
+static void target_to_host_sigset_internal(sigset_t *d,
+ const target_sigset_t *s);
+
+static inline int on_sig_stack(unsigned long sp)
+{
+ return sp - target_sigaltstack_used.ss_sp <
target_sigaltstack_used.ss_size;
+}
+
+static inline int sas_ss_flags(unsigned long sp)
+{
+ return target_sigaltstack_used.ss_size == 0 ? SS_DISABLE : on_sig_stack(sp)
+ ? SS_ONSTACK : 0;
+}
+
+int host_to_target_signal(int sig)
+{
+
+ if (sig < 0 || sig >= TARGET_NSIG) {
+ return sig;
+ }
+
+ return host_to_target_signal_table[sig];
+}
+
+int target_to_host_signal(int sig)
+{
+
+ if (sig >= TARGET_NSIG) {
+ return sig;
+ }
+
+ return target_to_host_signal_table[sig];
+}
+
+static inline void target_sigemptyset(target_sigset_t *set)
+{
+
+ memset(set, 0, sizeof(*set));
+}
+
+static inline void target_sigaddset(target_sigset_t *set, int signum)
+{
+
+ signum--;
+ uint32_t mask = (uint32_t)1 << (signum % TARGET_NSIG_BPW);
+ set->__bits[signum / TARGET_NSIG_BPW] |= mask;
+}
+
+static inline int target_sigismember(const target_sigset_t *set, int signum)
+{
+
+ signum--;
+ abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
+ return (set->__bits[signum / TARGET_NSIG_BPW] & mask) != 0;
+}
+
+static void host_to_target_sigset_internal(target_sigset_t *d,
+ const sigset_t *s)
+{
+ int i;
+
+ target_sigemptyset(d);
+ for (i = 1; i <= TARGET_NSIG; i++) {
+ if (sigismember(s, i)) {
+ target_sigaddset(d, host_to_target_signal(i));
+ }
+ }
+}
+
+void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
+{
+ target_sigset_t d1;
+ int i;
+
+ host_to_target_sigset_internal(&d1, s);
+ for (i = 0; i < TARGET_NSIG_WORDS; i++) {
+ d->__bits[i] = tswap32(d1.__bits[i]);
+ }
+}
+
+static void target_to_host_sigset_internal(sigset_t *d,
+ const target_sigset_t *s)
+{
+ int i;
+
+ sigemptyset(d);
+ for (i = 1; i <= TARGET_NSIG; i++) {
+ if (target_sigismember(s, i)) {
+ sigaddset(d, target_to_host_signal(i));
+ }
+ }
+}
+
+void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
+{
+ target_sigset_t s1;
+ int i;
+
+ for (i = 0; i < TARGET_NSIG_WORDS; i++) {
+ s1.__bits[i] = tswap32(s->__bits[i]);
+ }
+ target_to_host_sigset_internal(d, &s1);
+}
+
+/* Siginfo conversion. */
+static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
+ const siginfo_t *info)
+{
+ int sig, code;
+
+ sig = host_to_target_signal(info->si_signo);
+ /* XXX should have host_to_target_si_code() */
+ code = tswap32(info->si_code);
+ tinfo->si_signo = sig;
+ tinfo->si_errno = info->si_errno;
+ tinfo->si_code = info->si_code;
+ tinfo->si_pid = info->si_pid;
+ tinfo->si_uid = info->si_uid;
+ tinfo->si_addr = (abi_ulong)(unsigned long)info->si_addr;
+ /* si_value is opaque to kernel */
+ tinfo->si_value.sival_ptr =
+ (abi_ulong)(unsigned long)info->si_value.sival_ptr;
+ if (SIGILL == sig || SIGFPE == sig || SIGSEGV == sig || SIGBUS == sig ||
+ SIGTRAP == sig) {
+ tinfo->_reason._fault._trapno = info->_reason._fault._trapno;
+ }
+#ifdef SIGPOLL
+ if (SIGPOLL == sig) {
+ tinfo->_reason._poll._band = info->_reason._poll._band;
+ }
+#endif
+ if (SI_TIMER == code) {
+ tinfo->_reason._timer._timerid = info->_reason._timer._timerid;
+ tinfo->_reason._timer._overrun = info->_reason._timer._overrun;
+ }
+}
+
+static void tswap_siginfo(target_siginfo_t *tinfo, const target_siginfo_t
*info)
+{
+ int sig, code;
+
+ sig = info->si_signo;
+ code = info->si_code;
+ tinfo->si_signo = tswap32(sig);
+ tinfo->si_errno = tswap32(info->si_errno);
+ tinfo->si_code = tswap32(info->si_code);
+ tinfo->si_pid = tswap32(info->si_pid);
+ tinfo->si_uid = tswap32(info->si_uid);
+ tinfo->si_addr = tswapal(info->si_addr);
+ if (SIGILL == sig || SIGFPE == sig || SIGSEGV == sig || SIGBUS == sig ||
+ SIGTRAP == sig) {
+ tinfo->_reason._fault._trapno = tswap32(info->_reason._fault._trapno);
+ }
+#ifdef SIGPOLL
+ if (SIGPOLL == sig) {
+ tinfo->_reason._poll._band = tswap32(info->_reason._poll._band);
+ }
+#endif
+ if (SI_TIMER == code) {
+ tinfo->_reason._timer._timerid =
tswap32(info->_reason._timer._timerid);
+ tinfo->_reason._timer._overrun =
tswap32(info->_reason._timer._overrun);
+ }
+}
+
+void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
+{
+
+ host_to_target_siginfo_noswap(tinfo, info);
+ tswap_siginfo(tinfo, tinfo);
+}
+
+/* Returns 1 if given signal should dump core if not handled. */
+static int core_dump_signal(int sig)
+{
+ switch (sig) {
+ case TARGET_SIGABRT:
+ case TARGET_SIGFPE:
+ case TARGET_SIGILL:
+ case TARGET_SIGQUIT:
+ case TARGET_SIGSEGV:
+ case TARGET_SIGTRAP:
+ case TARGET_SIGBUS:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/* Signal queue handling. */
+static inline struct qemu_sigqueue *alloc_sigqueue(CPUArchState *env)
+{
+ TaskState *ts = env->opaque;
+ struct qemu_sigqueue *q = ts->first_free;
+
+ if (!q) {
+ return NULL;
+ }
+ ts->first_free = q->next;
+ return q;
+}
+
+static inline void free_sigqueue(CPUArchState *env, struct qemu_sigqueue *q)
+{
+
+ TaskState *ts = env->opaque;
+ q->next = ts->first_free;
+ ts->first_free = q;
+}
+
+/* Abort execution with signal. */
+void QEMU_NORETURN force_sig(int target_sig)
+{
+ CPUArchState *env = thread_cpu->env_ptr;
+ TaskState *ts = (TaskState *)env->opaque;
+ int core_dumped = 0;
+ int host_sig;
+ struct sigaction act;
+
+ host_sig = target_to_host_signal(target_sig);
+ gdb_signalled(env, target_sig);
+
+ /* Dump core if supported by target binary format */
+ if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) {
+ stop_all_tasks();
+ core_dumped =
+ ((*ts->bprm->core_dump)(target_sig, env) == 0);
+ }
+ if (core_dumped) {
+ struct rlimit nodump;
+
+ /*
+ * We already dumped the core of target process, we don't want
+ * a coredump of qemu itself.
+ */
+ getrlimit(RLIMIT_CORE, &nodump);
+ nodump.rlim_cur = 0;
+ setrlimit(RLIMIT_CORE, &nodump);
+ (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) "
+ "- %s\n", target_sig, strsignal(host_sig), "core dumped");
+ }
+
+ /*
+ * The proper exit code for dying from an uncaught signal is
+ * -<signal>. The kernel doesn't allow exit() or _exit() to pass
+ * a negative value. To get the proper exit code we need to
+ * actually die from an uncaught signal. Here the default signal
+ * handler is installed, we send ourself a signal and we wait for
+ * it to arrive.
+ */
+ memset(&act, 0, sizeof(act));
+ sigfillset(&act.sa_mask);
+ act.sa_handler = SIG_DFL;
+ sigaction(host_sig, &act, NULL);
+
+ kill(getpid(), host_sig);
+
+ /*
+ * Make sure the signal isn't masked (just reuse the mask inside
+ * of act).
+ */
+ sigdelset(&act.sa_mask, host_sig);
+ sigsuspend(&act.sa_mask);
+
+ /* unreachable */
+ abort();
+}
+
+/*
+ * Queue a signal so that it will be send to the virtual CPU as soon as
+ * possible.
+ */
+int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
+{
+ TaskState *ts = env->opaque;
+ struct emulated_sigtable *k;
+ struct qemu_sigqueue *q, **pq;
+ abi_ulong handler;
+ int queue;
+
+ k = &ts->sigtab[sig - 1];
+ queue = gdb_queuesig();
+ handler = sigact_table[sig - 1]._sa_handler;
+#ifdef DEBUG_SIGNAL
+ fprintf(stderr, "queue_signal: sig=%d handler=0x%lx flags=0x%x\n", sig,
+ handler, (uint32_t)sigact_table[sig - 1].sa_flags);
+#endif
+ if (!queue && (TARGET_SIG_DFL == handler)) {
+ if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN ||
+ sig == TARGET_SIGTTOU) {
+ kill(getpid(), SIGSTOP);
+ return 0;
+ } else {
+ if (sig != TARGET_SIGCHLD &&
+ sig != TARGET_SIGURG &&
+ sig != TARGET_SIGWINCH &&
+ sig != TARGET_SIGCONT) {
+ force_sig(sig);
+ } else {
+ return 0; /* The signal was ignored. */
+ }
+ }
+ } else if (!queue && (TARGET_SIG_IGN == handler)) {
+ return 0; /* Ignored signal. */
+ } else if (!queue && (TARGET_SIG_ERR == handler)) {
+ force_sig(sig);
+ } else {
+ pq = &k->first;
+
+ /*
+ * FreeBSD signals are always queued.
+ * Linux only queues real time signals.
+ * XXX this code is not thread safe.
+ */
+ if (!k->pending) {
+ /* first signal */
+ q = &k->info;
+ } else {
+ q = alloc_sigqueue(env);
+ if (!q) {
+ return -EAGAIN;
+ }
+ while (*pq != NULL) {
+ pq = &(*pq)->next;
+ }
+ }
+ *pq = q;
+ q->info = *info;
+ q->next = NULL;
+ k->pending = 1;
+ /* Signal that a new signal is pending. */
+ ts->signal_pending = 1;
+ return 1; /* Indicates that the signal was queued. */
+ }
+}
+
+static void host_signal_handler(int host_signum, siginfo_t *info, void *puc)
+{
+ CPUArchState *env = thread_cpu->env_ptr;
+ int sig;
+ target_siginfo_t tinfo;
+
+ /*
+ * The CPU emulator uses some host signal to detect exceptions so
+ * we forward to it some signals.
+ */
+ if ((host_signum == SIGSEGV || host_signum == SIGBUS) &&
+ info->si_code < 0x10000) {
+ if (cpu_signal_handler(host_signum, info, puc)) {
+ return;
+ }
+ }
+
+ /* Get the target signal number. */
+ sig = host_to_target_signal(host_signum);
+ if (sig < 1 || sig > TARGET_NSIG) {
+ return;
+ }
+#ifdef DEBUG_SIGNAL
+ fprintf(stderr, "qemu: got signal %d\n", sig);
+#endif
+ host_to_target_siginfo_noswap(&tinfo, info);
+ if (queue_signal(env, sig, &tinfo) == 1) {
+ /* Interrupt the virtual CPU as soon as possible. */
+ cpu_exit(thread_cpu);
+ }
+}
+
+/* do_sigaltstack() returns target values and errnos. */
+/* compare to kern/kern_sig.c sys_sigaltstack() and kern_sigaltstack() */
+abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
+{
+ int ret = 0;
+ target_stack_t ss, oss, *uss;
+
+ if (uoss_addr) {
+ /* Save current signal stack params */
+ oss.ss_sp = tswapl(target_sigaltstack_used.ss_sp);
+ oss.ss_size = tswapl(target_sigaltstack_used.ss_size);
+ oss.ss_flags = tswapl(sas_ss_flags(sp));
+ }
+
+ if (uss_addr) {
+
+ if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1) ||
+ __get_user(ss.ss_sp, &uss->ss_sp) ||
+ __get_user(ss.ss_size, &uss->ss_size) ||
+ __get_user(ss.ss_flags, &uss->ss_flags)) {
+ ret = -TARGET_EFAULT;
+ goto out;
+ }
+ unlock_user_struct(uss, uss_addr, 0);
+
+ if (on_sig_stack(sp)) {
+ ret = -TARGET_EPERM;
+ goto out;
+ }
+
+ if ((ss.ss_flags & ~TARGET_SS_DISABLE) != 0) {
+ ret = -TARGET_EINVAL;
+ goto out;
+ }
+
+ if (!(ss.ss_flags & ~TARGET_SS_DISABLE)) {
+ if (ss.ss_size < TARGET_MINSIGSTKSZ) {
+ ret = -TARGET_ENOMEM;
+ goto out;
+ }
+ } else {
+ ss.ss_size = 0;
+ ss.ss_sp = 0;
+ }
+
+ target_sigaltstack_used.ss_sp = ss.ss_sp;
+ target_sigaltstack_used.ss_size = ss.ss_size;
+ }
+
+ if (uoss_addr) {
+ /* Copy out to user saved signal stack params */
+ if (copy_to_user(uoss_addr, &oss, sizeof(oss))) {
+ ret = -TARGET_EFAULT;
+ goto out;
+ }
+ }
+
+out:
+ return ret;
+}
+
+static int fatal_signal(int sig)
+{
+
+ switch (sig) {
+ case TARGET_SIGCHLD:
+ case TARGET_SIGURG:
+ case TARGET_SIGWINCH:
+ /* Ignored by default. */
+ return 0;
+ case TARGET_SIGCONT:
+ case TARGET_SIGSTOP:
+ case TARGET_SIGTSTP:
+ case TARGET_SIGTTIN:
+ case TARGET_SIGTTOU:
+ /* Job control signals. */
+ return 0;
+ default:
+ return 1;
+ }
+}
+
+/* do_sigaction() return host values and errnos */
+int do_sigaction(int sig, const struct target_sigaction *act,
+ struct target_sigaction *oact)
+{
+ struct target_sigaction *k;
+ struct sigaction act1;
+ int host_sig;
+ int ret = 0;
+
+ if (sig < 1 || sig > TARGET_NSIG || TARGET_SIGKILL == sig ||
+ TARGET_SIGSTOP == sig) {
+ return -EINVAL;
+ }
+ k = &sigact_table[sig - 1];
+#if defined(DEBUG_SIGNAL)
+ fprintf(stderr, "do_sigaction sig=%d act=%p, oact=%p\n",
+ sig, act, oact);
+#endif
+ if (oact) {
+ oact->_sa_handler = tswapal(k->_sa_handler);
+ oact->sa_flags = tswap32(k->sa_flags);
+ oact->sa_mask = k->sa_mask;
+ }
+ if (act) {
+ /* XXX: this is most likely not threadsafe. */
+ k->_sa_handler = tswapal(act->_sa_handler);
+ k->sa_flags = tswap32(act->sa_flags);
+ k->sa_mask = act->sa_mask;
+
+ /* Update the host signal state. */
+ host_sig = target_to_host_signal(sig);
+ if (host_sig != SIGSEGV && host_sig != SIGBUS) {
+ memset(&act1, 0, sizeof(struct sigaction));
+ sigfillset(&act1.sa_mask);
+ if (k->sa_flags & TARGET_SA_RESTART) {
+ act1.sa_flags |= SA_RESTART;
+ }
+ /*
+ * Note: It is important to update the host kernel signal mask to
+ * avoid getting unexpected interrupted system calls.
+ */
+ if (k->_sa_handler == TARGET_SIG_IGN) {
+ act1.sa_sigaction = (void *)SIG_IGN;
+ } else if (k->_sa_handler == TARGET_SIG_DFL) {
+ if (fatal_signal(sig)) {
+ act1.sa_flags = SA_SIGINFO;
+ act1.sa_sigaction = host_signal_handler;
+ } else {
+ act1.sa_sigaction = (void *)SIG_DFL;
+ }
+ } else {
+ act1.sa_flags = SA_SIGINFO;
+ act1.sa_sigaction = host_signal_handler;
+ }
+ ret = sigaction(host_sig, &act1, NULL);
+#if defined(DEBUG_SIGNAL)
+ fprintf(stderr, "sigaction (action = %p "
+ "(host_signal_handler = %p)) returned: %d\n",
+ act1.sa_sigaction, host_signal_handler, ret);
+#endif
+ }
+ }
+ return ret;
+}
+
+static inline abi_ulong get_sigframe(struct target_sigaction *ka,
+ CPUArchState *regs, size_t frame_size)
+{
+ abi_ulong sp;
+
+ /* Use default user stack */
+ sp = get_sp_from_cpustate(regs);
+
+ if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
+ sp = target_sigaltstack_used.ss_sp +
+ target_sigaltstack_used.ss_size;
+ }
+
+#if defined(TARGET_MIPS) || defined(TARGET_ARM)
+ return (sp - frame_size) & ~7;
+#else
+ return sp - frame_size;
+#endif
+}
+
+/* compare to mips/mips/pm_machdep.c and sparc64/sparc64/machdep.c sendsig() */
+static void setup_frame(int sig, int code, struct target_sigaction *ka,
+ target_sigset_t *set, target_siginfo_t *tinfo, CPUArchState *regs)
+{
+ struct target_sigframe *frame;
+ abi_ulong frame_addr;
+ int i;
+
+#ifdef DEBUG_SIGNAL
+ fprintf(stderr, "setup_frame()\n");
+#endif
+ frame_addr = get_sigframe(ka, regs, sizeof(*frame));
+ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+ goto give_sigsegv;
+ }
+
+ memset(frame, 0, sizeof(*frame));
+#if defined(TARGET_MIPS)
+ int mflags = on_sig_stack(frame_addr) ? TARGET_MC_ADD_MAGIC :
+ TARGET_MC_SET_ONSTACK | TARGET_MC_ADD_MAGIC;
+#else
+ int mflags = 0;
+#endif
+ if (get_mcontext(regs, &frame->sf_uc.uc_mcontext, mflags)) {
+ goto give_sigsegv;
+ }
+
+ for (i = 0; i < TARGET_NSIG_WORDS; i++) {
+ if (__put_user(set->__bits[i], &frame->sf_uc.uc_sigmask.__bits[i])) {
+ goto give_sigsegv;
+ }
+ }
+
+ if (tinfo) {
+ frame->sf_si.si_signo = tinfo->si_signo;
+ frame->sf_si.si_errno = tinfo->si_errno;
+ frame->sf_si.si_code = tinfo->si_code;
+ frame->sf_si.si_pid = tinfo->si_pid;
+ frame->sf_si.si_uid = tinfo->si_uid;
+ frame->sf_si.si_status = tinfo->si_status;
+ frame->sf_si.si_addr = tinfo->si_addr;
+
+ if (TARGET_SIGILL == sig || TARGET_SIGFPE == sig ||
+ TARGET_SIGSEGV == sig || TARGET_SIGBUS == sig ||
+ TARGET_SIGTRAP == sig) {
+ frame->sf_si._reason._fault._trapno =
tinfo->_reason._fault._trapno;
+ }
+
+ /*
+ * If si_code is one of SI_QUEUE, SI_TIMER, SI_ASYNCIO, or
+ * SI_MESGQ, then si_value contains the application-specified
+ * signal value. Otherwise, the contents of si_value are
+ * undefined.
+ */
+ if (SI_QUEUE == code || SI_TIMER == code || SI_ASYNCIO == code ||
+ SI_MESGQ == code) {
+ frame->sf_si.si_value.sival_int = tinfo->si_value.sival_int;
+ }
+
+ if (SI_TIMER == code) {
+ frame->sf_si._reason._timer._timerid =
+ tinfo->_reason._timer._timerid;
+ frame->sf_si._reason._timer._overrun =
+ tinfo->_reason._timer._overrun;
+ }
+
+#ifdef SIGPOLL
+ if (SIGPOLL == sig) {
+ frame->sf_si._reason._band = tinfo->_reason._band;
+ }
+#endif
+
+ }
+
+ if (set_sigtramp_args(regs, sig, frame, frame_addr, ka)) {
+ goto give_sigsegv;
+ }
+
+ unlock_user_struct(frame, frame_addr, 1);
+ return;
+
+give_sigsegv:
+ unlock_user_struct(frame, frame_addr, 1);
+ force_sig(TARGET_SIGSEGV);
+}
+
+static int reset_signal_mask(target_ucontext_t *ucontext)
+{
+ int i;
+ sigset_t blocked;
+ target_sigset_t target_set;
+
+ for (i = 0; i < TARGET_NSIG_WORDS; i++)
+ if (__get_user(target_set.__bits[i],
+ &ucontext->uc_sigmask.__bits[i])) {
+ return -TARGET_EFAULT;
+ }
+ target_to_host_sigset_internal(&blocked, &target_set);
+ sigprocmask(SIG_SETMASK, &blocked, NULL);
+
+ return 0;
+}
+
+long do_sigreturn(CPUArchState *regs, abi_ulong addr)
+{
+ long ret;
+ abi_ulong target_ucontext;
+ target_ucontext_t *ucontext = NULL;
+
+ /* Get the target ucontext address from the stack frame */
+ ret = get_ucontext_sigreturn(regs, addr, &target_ucontext);
+ if (is_error(ret)) {
+ return ret;
+ }
+ if (!lock_user_struct(VERIFY_READ, ucontext, target_ucontext, 0)) {
+ goto badframe;
+ }
+
+ /* Set the register state back to before the signal. */
+ if (set_mcontext(regs, &ucontext->uc_mcontext, 1)) {
+ goto badframe;
+ }
+
+ /* And reset the signal mask. */
+ if (reset_signal_mask(ucontext)) {
+ goto badframe;
+ }
+
+ unlock_user_struct(ucontext, target_ucontext, 0);
+ return -TARGET_EJUSTRETURN;
+
+badframe:
+ if (ucontext != NULL) {
+ unlock_user_struct(ucontext, target_ucontext, 0);
+ }
+ force_sig(TARGET_SIGSEGV);
+ return -TARGET_EFAULT;
+}
+
void signal_init(void)
{
+ struct sigaction act;
+ struct sigaction oact;
+ int i, j;
+ int host_sig;
+
+ /* Generate the signal conversion tables. */
+ for (i = 1; i < TARGET_NSIG; i++) {
+ if (host_to_target_signal_table[i] == 0) {
+ host_to_target_signal_table[i] = i;
+ }
+ }
+ for (i = 1; i < TARGET_NSIG; i++) {
+ j = host_to_target_signal_table[i];
+ target_to_host_signal_table[j] = i;
+ }
+
+ /*
+ * Set all host signal handlers. ALL signals are blocked during the
+ * handlers to serialize them.
+ */
+ memset(sigact_table, 0, sizeof(sigact_table));
+
+ sigfillset(&act.sa_mask);
+ act.sa_sigaction = host_signal_handler;
+ act.sa_flags = SA_SIGINFO;
+
+ for (i = 1; i <= TARGET_NSIG; i++) {
+ host_sig = target_to_host_signal(i);
+ sigaction(host_sig, NULL, &oact);
+ if (oact.sa_sigaction == (void *)SIG_IGN) {
+ sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
+ } else if (oact.sa_sigaction == (void *)SIG_DFL) {
+ sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL;
+ }
+ /*
+ * If there's already a handler installed then something has
+ * gone horribly wrong, so don't even try to handle that case.
+ * Install some handlers for our own use. We need at least
+ * SIGSEGV and SIGBUS, to detect exceptions. We can not just
+ * trap all signals because it affects syscall interrupt
+ * behavior. But do trap all default-fatal signals.
+ */
+ if (fatal_signal(i)) {
+ sigaction(host_sig, &act, NULL);
+ }
+ }
}
void process_pending_signals(CPUArchState *cpu_env)
{
+ CPUState *cpu = ENV_GET_CPU(cpu_env);
+ int sig, code;
+ abi_ulong handler;
+ sigset_t set, old_set;
+ target_sigset_t target_old_set;
+ target_siginfo_t tinfo;
+ struct emulated_sigtable *k;
+ struct target_sigaction *sa;
+ struct qemu_sigqueue *q;
+ TaskState *ts = cpu_env->opaque;
+
+ if (!ts->signal_pending) {
+ return;
+ }
+
+ /* FIXME: This is not threadsafe. */
+ k = ts->sigtab;
+ for (sig = 1; sig <= TARGET_NSIG; sig++) {
+ if (k->pending) {
+ goto handle_signal;
+ }
+ k++;
+ }
+#ifdef DEBUG_SIGNAL
+ fprintf(stderr, "qemu: process_pending_signals has no signals\n");
+#endif
+ /* If no signal is pending then just return. */
+ ts->signal_pending = 0;
+ return;
+
+handle_signal:
+#ifdef DEBUG_SIGNAL
+ fprintf(stderr, "qemu: process signal %d\n", sig);
+#endif
+
+ /* Dequeue signal. */
+ q = k->first;
+ k->first = q->next;
+ if (!k->first) {
+ k->pending = 0;
+ }
+
+ sig = gdb_handlesig(cpu, sig);
+ if (!sig) {
+ sa = NULL;
+ handler = TARGET_SIG_IGN;
+ } else {
+ sa = &sigact_table[sig - 1];
+ handler = sa->_sa_handler;
+ }
+
+ if (handler == TARGET_SIG_DFL) {
+#ifdef DEBUG_SIGNAL
+ fprintf(stderr, "qemu: TARGET_SIG_DFL\n");
+#endif
+ /*
+ * default handler : ignore some signal. The other are job
+ * control or fatal.
+ */
+ if (TARGET_SIGTSTP == sig || TARGET_SIGTTIN == sig ||
+ TARGET_SIGTTOU == sig) {
+ kill(getpid(), SIGSTOP);
+ } else if (TARGET_SIGCHLD != sig && TARGET_SIGURG != sig &&
+ TARGET_SIGWINCH != sig && TARGET_SIGCONT != sig) {
+ force_sig(sig);
+ }
+ } else if (TARGET_SIG_IGN == handler) {
+ /* ignore sig */
+#ifdef DEBUG_SIGNAL
+ fprintf(stderr, "qemu: TARGET_SIG_IGN\n");
+#endif
+ } else if (TARGET_SIG_ERR == handler) {
+#ifdef DEBUG_SIGNAL
+ fprintf(stderr, "qemu: TARGET_SIG_ERR\n");
+#endif
+ force_sig(sig);
+ } else {
+ /* compute the blocked signals during the handler execution */
+ target_to_host_sigset(&set, &sa->sa_mask);
+ /*
+ * SA_NODEFER indicates that the current signal should not be
+ * blocked during the handler.
+ */
+ if (!(sa->sa_flags & TARGET_SA_NODEFER)) {
+ sigaddset(&set, target_to_host_signal(sig));
+ }
+
+ /* block signals in the handler */
+ sigprocmask(SIG_BLOCK, &set, &old_set);
+
+ /*
+ * Save the previous blocked signal state to restore it at the
+ * end of the signal execution (see do_sigreturn).
+ */
+ host_to_target_sigset_internal(&target_old_set, &old_set);
+
+#if 0 /* not yet */
+#if defined(TARGET_I386) && !defined(TARGET_X86_64)
+ /* if the CPU is in VM86 mode, we restore the 32 bit values */
+ {
+ CPUX86State *env = cpu_env;
+ if (env->eflags & VM_MASK) {
+ save_v86_state(env);
+ }
+ }
+#endif
+#endif /* not yet */
+
+ code = q->info.si_code;
+ /* prepare the stack frame of the virtual CPU */
+ if (sa->sa_flags & TARGET_SA_SIGINFO) {
+ tswap_siginfo(&tinfo, &q->info);
+ setup_frame(sig, code, sa, &target_old_set, &tinfo, cpu_env);
+ } else {
+ setup_frame(sig, code, sa, &target_old_set, NULL, cpu_env);
+ }
+ if (sa->sa_flags & TARGET_SA_RESETHAND) {
+ sa->_sa_handler = TARGET_SIG_DFL;
+ }
+ }
+ if (q != &k->info) {
+ free_sigqueue(cpu_env, q);
+ }
}
diff --git a/bsd-user/sparc/target_arch_signal.h
b/bsd-user/sparc/target_arch_signal.h
new file mode 100644
index 0000000..f934f8c
--- /dev/null
+++ b/bsd-user/sparc/target_arch_signal.h
@@ -0,0 +1,77 @@
+#ifndef TARGET_ARCH_SIGNAL_H
+#define TARGET_ARCH_SIGNAL_H
+
+#include "cpu.h"
+
+/* Size of the signal trampolin code placed on the stack. */
+/* #define TARGET_SZSIGCODE (0) */ /* XXX to be added. */
+
+/* compare to sparc64/include/_limits.h */
+#define TARGET_MINSIGSTKSZ (1024 * 4) /* min sig stack size */
+#define TARGET_SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended size */
+
+#define TARGET_MC_GET_CLEAR_RET 0x0001
+
+struct target_sigcontext {
+ /* to be added */
+};
+
+typedef struct target_mcontext {
+} target_mcontext_t;
+
+typedef struct target_ucontext {
+ target_sigset_t uc_sigmask;
+ target_mcontext_t uc_mcontext;
+ abi_ulong uc_link;
+ target_stack_t uc_stack;
+ int32_t uc_flags;
+ int32_t __spare__[4];
+} target_ucontext_t;
+
+struct target_sigframe {
+ abi_ulong sf_signum;
+ abi_ulong sf_siginfo; /* code or pointer to sf_si */
+ abi_ulong sf_ucontext; /* points to sf_uc */
+ abi_ulong sf_addr; /* undocumented 4th arg */
+ target_ucontext_t sf_uc; /* = *sf_uncontext */
+ target_siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case)*/
+ uint32_t __spare__[2];
+};
+
+/*
+ * Compare to sparc64/sparc64/machdep.c sendsig()
+ * Assumes that target stack frame memory is locked.
+ */
+static inline abi_long set_sigtramp_args(CPUSPARCState *regs,
+ int sig, struct target_sigframe *frame, abi_ulong frame_addr,
+ struct target_sigaction *ka)
+{
+ /* XXX */
+ return -TARGET_EOPNOTSUPP;
+}
+
+/* Compare to sparc64/sparc64/machdep.c get_mcontext() */
+static inline abi_long get_mcontext(CPUSPARCState *regs,
+ target_mcontext_t *mcp, int flags)
+{
+ /* XXX */
+ return -TARGET_EOPNOTSUPP;
+}
+
+/* Compare to sparc64/space64/machdep.c set_mcontext() */
+static inline abi_long set_mcontext(CPUSPARCState *regs,
+ target_mcontext_t *mcp, int srflag)
+{
+ /* XXX */
+ return -TARGET_EOPNOTSUPP;
+}
+
+static inline abi_long get_ucontext_sigreturn(CPUSPARCState *regs,
+ abi_ulong target_sf, abi_ulong *target_uc)
+{
+ /* XXX */
+ *target_uc = 0;
+ return -TARGET_EOPNOTSUPP;
+}
+
+#endif /* TARGET_ARCH_SIGNAL_H */
diff --git a/bsd-user/sparc64/target_arch_signal.h
b/bsd-user/sparc64/target_arch_signal.h
new file mode 100644
index 0000000..1529b0f
--- /dev/null
+++ b/bsd-user/sparc64/target_arch_signal.h
@@ -0,0 +1,94 @@
+/*
+ * sparc64 dependent signal definitions
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _TARGET_ARCH_SIGNAL_H_
+#define _TARGET_ARCH_SIGNAL_H_
+
+#include "cpu.h"
+
+/* Size of the signal trampolin code placed on the stack. */
+/* #define TARGET_SZSIGCODE (0) */ /* XXX to be added. */
+
+/* compare to sparc64/include/_limits.h */
+#define TARGET_MINSIGSTKSZ (1024 * 4) /* min sig stack size */
+#define TARGET_SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended size */
+
+#define TARGET_MC_GET_CLEAR_RET 0x0001
+
+struct target_sigcontext {
+ /* to be added */
+};
+
+typedef struct target_mcontext {
+} target_mcontext_t;
+
+typedef struct target_ucontext {
+ target_sigset_t uc_sigmask;
+ target_mcontext_t uc_mcontext;
+ abi_ulong uc_link;
+ target_stack_t uc_stack;
+ int32_t uc_flags;
+ int32_t __spare__[4];
+} target_ucontext_t;
+
+struct target_sigframe {
+ abi_ulong sf_signum;
+ abi_ulong sf_siginfo; /* code or pointer to sf_si */
+ abi_ulong sf_ucontext; /* points to sf_uc */
+ abi_ulong sf_addr; /* undocumented 4th arg */
+ target_ucontext_t sf_uc; /* = *sf_uncontext */
+ target_siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case)*/
+ uint32_t __spare__[2];
+};
+
+/*
+ * Compare to sparc64/sparc64/machdep.c sendsig()
+ * Assumes that target stack frame memory is locked.
+ */
+static inline abi_long set_sigtramp_args(CPUSPARCState *regs,
+ int sig, struct target_sigframe *frame, abi_ulong frame_addr,
+ struct target_sigaction *ka)
+{
+ /* XXX */
+ return -TARGET_EOPNOTSUPP;
+}
+
+/* Compare to sparc64/sparc64/machdep.c get_mcontext() */
+static inline abi_long get_mcontext(CPUSPARCState *regs,
+ target_mcontext_t *mcp, int flags)
+{
+ /* XXX */
+ return -TARGET_EOPNOTSUPP;
+}
+
+/* Compare to sparc64/space64/machdep.c set_mcontext() */
+static inline abi_long set_mcontext(CPUSPARCState *regs,
+ target_mcontext_t *mcp, int srflag)
+{
+ /* XXX */
+ return -TARGET_EOPNOTSUPP;
+}
+
+static inline abi_long get_ucontext_sigreturn(CPUSPARCState *regs,
+ abi_ulong target_sf, abi_ulong *target_uc)
+{
+ /* XXX */
+ *target_uc = 0;
+ return -TARGET_EOPNOTSUPP;
+}
+
+#endif /* !_TARGET_ARCH_SIGNAL_H_ */
diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
index 0996787..bc4a7e4 100644
--- a/bsd-user/syscall.c
+++ b/bsd-user/syscall.c
@@ -39,8 +39,12 @@
#define target_to_host_bitmask(x, tbl) (x)
+/* BSD independent syscall shims */
+#include "bsd-signal.h"
+
/* *BSD dependent syscall shims */
#include "os-time.h"
+#include "os-signal.h"
/* #define DEBUG */
@@ -326,6 +330,61 @@ abi_long do_freebsd_syscall(void *cpu_env, int num,
abi_long arg1,
break;
/*
+ * signal system calls
+ */
+ case TARGET_FREEBSD_NR_sigtimedwait: /* sigtimedwait(2) */
+ ret = do_freebsd_sigtimedwait(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_sigaction: /* sigaction(2) */
+ ret = do_bsd_sigaction(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_sigprocmask: /* sigprocmask(2) */
+ ret = do_bsd_sigprocmask(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_sigpending: /* sigpending(2) */
+ ret = do_bsd_sigpending(arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_sigsuspend: /* sigsuspend(2) */
+ ret = do_bsd_sigsuspend(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_sigreturn: /* sigreturn(2) */
+ ret = do_bsd_sigreturn(cpu_env, arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_sigwait: /* sigwait(2) */
+ ret = do_bsd_sigwait(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_sigwaitinfo: /* sigwaitinfo(2) */
+ ret = do_bsd_sigwaitinfo(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_sigqueue: /* sigqueue(2) */
+ ret = do_bsd_sigqueue(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_sigaltstack: /* sigaltstack(2) */
+ ret = do_bsd_sigaltstack(cpu_env, arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_kill: /* kill(2) */
+ ret = do_bsd_kill(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_killpg: /* killpg(2) */
+ ret = do_bsd_killpg(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_pdkill: /* pdkill(2) */
+ ret = do_freebsd_pdkill(arg1, arg2);
+ break;
+
+ /*
* sys{ctl, arch, call}
*/
case TARGET_FREEBSD_NR___sysctl: /* sysctl(3) */
diff --git a/bsd-user/x86_64/target_arch_signal.h
b/bsd-user/x86_64/target_arch_signal.h
new file mode 100644
index 0000000..1998570
--- /dev/null
+++ b/bsd-user/x86_64/target_arch_signal.h
@@ -0,0 +1,94 @@
+/*
+ * x86_64 signal definitions
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _TARGET_ARCH_SIGNAL_H_
+#define _TARGET_ARCH_SIGNAL_H_
+
+#include "cpu.h"
+
+/* Size of the signal trampolin code placed on the stack. */
+/* #define TARGET_SZSIGCODE (0) */ /* XXX to be added */
+
+/* compare to x86/include/_limits.h */
+#define TARGET_MINSIGSTKSZ (512 * 4) /* min sig stack size */
+#define TARGET_SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended size */
+
+#define TARGET_MC_GET_CLEAR_RET 0x0001
+
+struct target_sigcontext {
+ /* to be added */
+};
+
+typedef struct target_mcontext {
+} target_mcontext_t;
+
+typedef struct target_ucontext {
+ target_sigset_t uc_sigmask;
+ target_mcontext_t uc_mcontext;
+ abi_ulong uc_link;
+ target_stack_t uc_stack;
+ int32_t uc_flags;
+ int32_t __spare__[4];
+} target_ucontext_t;
+
+struct target_sigframe {
+ abi_ulong sf_signum;
+ abi_ulong sf_siginfo; /* code or pointer to sf_si */
+ abi_ulong sf_ucontext; /* points to sf_uc */
+ abi_ulong sf_addr; /* undocumented 4th arg */
+ target_ucontext_t sf_uc; /* = *sf_uncontext */
+ target_siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case)*/
+ uint32_t __spare__[2];
+};
+
+/*
+ * Compare to amd64/amd64/machdep.c sendsig()
+ * Assumes that target stack frame memory is locked.
+ */
+static inline abi_long set_sigtramp_args(CPUX86State *regs,
+ int sig, struct target_sigframe *frame, abi_ulong frame_addr,
+ struct target_sigaction *ka)
+{
+ /* XXX */
+ return -TARGET_EOPNOTSUPP;
+}
+
+/* Compare to amd64/amd64/machdep.c get_mcontext() */
+static inline abi_long get_mcontext(CPUX86State *regs,
+ target_mcontext_t *mcp, int flags)
+{
+ /* XXX */
+ return -TARGET_EOPNOTSUPP;
+}
+
+/* Compare to amd64/amd64/machdep.c set_mcontext() */
+static inline abi_long set_mcontext(CPUX86State *regs,
+ target_mcontext_t *mcp, int srflag)
+{
+ /* XXX */
+ return -TARGET_EOPNOTSUPP;
+}
+
+static inline abi_long get_ucontext_sigreturn(CPUX86State *regs,
+ abi_ulong target_sf, abi_ulong *target_uc)
+{
+ /* XXX */
+ *target_uc = 0;
+ return -TARGET_EOPNOTSUPP;
+}
+
+#endif /* !TARGET_ARCH_SIGNAL_H_ */
--
1.7.8
- [Qemu-devel] [PATCH v2 03/19] bsd-user: move OS/arch dependent code for strace into separate directories, (continued)
- Message not available
- Message not available
- Message not available
- Message not available
- Message not available
- Message not available
Message not available
Message not available
Message not available
- [Qemu-devel] [PATCH v2 07/19] bsd-user: add support for freebsd signal related system calls,
Stacey Son <=
Message not available
Message not available
Message not available
Re: [Qemu-devel] [PATCH v2 00/19] bsd-user: Add system call and mips/arm support., Ed Maste, 2013/11/26