From 0b145562c4c469d56e4cd89c88e2b6dcb7d0dd22 Mon Sep 17 00:00:00 2001 In-Reply-To: <1383928417-38009-1-git-send-email-sson@FreeBSD.org> References: <1383928417-38009-1-git-send-email-sson@FreeBSD.org> From: Stacey Son Date: Mon, 7 Oct 2013 04:03:12 -0500 Subject: [PATCH v3 07/19] bsd-user: add support for freebsd signal related system calls 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). --- 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 | 214 ++++++++ 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, 2830 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 . + */ +#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 . + */ + +#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 . + */ + +#ifndef __FREEBSD_OS_SIGNAL_H_ +#define __FREEBSD_OS_SIGNAL_H_ + +#include + +#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 . + */ +#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 . + */ +#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 . + */ +#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..2f79a24 --- /dev/null +++ b/bsd-user/mips64/target_arch_signal.h @@ -0,0 +1,214 @@ +/* + * 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 . + */ +#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]); + } + + mcp->mc_fpused = 1; + for (i = 0; i < 32; i++) { + mcp->mc_fpregs[i] = tswapal(regs->active_fpu.fpr[i].d); + } + mcp->mc_fpregs[32] = tswapal(regs->active_fpu.fcr0); + mcp->mc_fpc_eir = tswapal(regs->active_fpu.fcr31); + + 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 (mcp->mc_fpused) { + /* restore fpu context if we have used it before */ + for (i = 0; i < 32; i++) { + regs->active_fpu.fpr[i].d = tswapal(mcp->mc_fpregs[i]); + } + regs->active_fpu.fcr0 = tswapal(mcp->mc_fpregs[32]); + regs->active_fpu.fcr31 = tswapal(mcp->mc_fpc_eir); + } + + 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 #include #include +#include +#include +#include #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 + * -. 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 . + */ +#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 . + */ +#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