linux/arch/h8300/kernel/signal.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/h8300/kernel/signal.c
   3 *
   4 *  Copyright (C) 1991, 1992  Linus Torvalds
   5 *
   6 * This file is subject to the terms and conditions of the GNU General Public
   7 * License.  See the file COPYING in the main directory of this archive
   8 * for more details.
   9 */
  10
  11/*
  12 * uClinux H8/300 support by Yoshinori Sato <ysato@users.sourceforge.jp>
  13 *                and David McCullough <davidm@snapgear.com>
  14 *
  15 * Based on
  16 * Linux/m68k by Hamish Macdonald
  17 */
  18
  19/*
  20 * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
  21 * Atari :-) Current limitation: Only one sigstack can be active at one time.
  22 * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
  23 * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
  24 * signal handlers!
  25 */
  26
  27#include <linux/sched.h>
  28#include <linux/mm.h>
  29#include <linux/kernel.h>
  30#include <linux/signal.h>
  31#include <linux/syscalls.h>
  32#include <linux/errno.h>
  33#include <linux/wait.h>
  34#include <linux/ptrace.h>
  35#include <linux/unistd.h>
  36#include <linux/stddef.h>
  37#include <linux/highuid.h>
  38#include <linux/personality.h>
  39#include <linux/tty.h>
  40#include <linux/binfmts.h>
  41#include <linux/tracehook.h>
  42
  43#include <asm/setup.h>
  44#include <asm/uaccess.h>
  45#include <asm/pgtable.h>
  46#include <asm/traps.h>
  47#include <asm/ucontext.h>
  48
  49/*
  50 * Do a signal return; undo the signal stack.
  51 *
  52 * Keep the return code on the stack quadword aligned!
  53 * That makes the cache flush below easier.
  54 */
  55
  56struct rt_sigframe {
  57        long dummy_er0;
  58        long dummy_vector;
  59#if defined(CONFIG_CPU_H8S)
  60        short dummy_exr;
  61#endif
  62        long dummy_pc;
  63        char *pretcode;
  64        struct siginfo *pinfo;
  65        void *puc;
  66        unsigned char retcode[8];
  67        struct siginfo info;
  68        struct ucontext uc;
  69        int sig;
  70} __packed __aligned(2);
  71
  72static inline int
  73restore_sigcontext(struct sigcontext *usc, int *pd0)
  74{
  75        struct pt_regs *regs = current_pt_regs();
  76        int err = 0;
  77        unsigned int ccr;
  78        unsigned int usp;
  79        unsigned int er0;
  80
  81        /* Always make any pending restarted system calls return -EINTR */
  82        current_thread_info()->restart_block.fn = do_no_restart_syscall;
  83
  84        /* restore passed registers */
  85#define COPY(r)  do { err |= get_user(regs->r, &usc->sc_##r); } while (0)
  86        COPY(er1);
  87        COPY(er2);
  88        COPY(er3);
  89        COPY(er5);
  90        COPY(pc);
  91        ccr = regs->ccr & 0x10;
  92        COPY(ccr);
  93#undef COPY
  94        regs->ccr &= 0xef;
  95        regs->ccr |= ccr;
  96        regs->orig_er0 = -1;            /* disable syscall checks */
  97        err |= __get_user(usp, &usc->sc_usp);
  98        regs->sp = usp;
  99
 100        err |= __get_user(er0, &usc->sc_er0);
 101        *pd0 = er0;
 102        return err;
 103}
 104
 105asmlinkage int sys_rt_sigreturn(void)
 106{
 107        unsigned long usp = rdusp();
 108        struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4);
 109        sigset_t set;
 110        int er0;
 111
 112        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 113                goto badframe;
 114        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
 115                goto badframe;
 116
 117        set_current_blocked(&set);
 118
 119        if (restore_sigcontext(&frame->uc.uc_mcontext, &er0))
 120                goto badframe;
 121
 122        if (restore_altstack(&frame->uc.uc_stack))
 123                goto badframe;
 124
 125        return er0;
 126
 127badframe:
 128        force_sig(SIGSEGV, current);
 129        return 0;
 130}
 131
 132static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
 133                             unsigned long mask)
 134{
 135        int err = 0;
 136
 137        err |= __put_user(regs->er0, &sc->sc_er0);
 138        err |= __put_user(regs->er1, &sc->sc_er1);
 139        err |= __put_user(regs->er2, &sc->sc_er2);
 140        err |= __put_user(regs->er3, &sc->sc_er3);
 141        err |= __put_user(regs->er4, &sc->sc_er4);
 142        err |= __put_user(regs->er5, &sc->sc_er5);
 143        err |= __put_user(regs->er6, &sc->sc_er6);
 144        err |= __put_user(rdusp(),   &sc->sc_usp);
 145        err |= __put_user(regs->pc,  &sc->sc_pc);
 146        err |= __put_user(regs->ccr, &sc->sc_ccr);
 147        err |= __put_user(mask,      &sc->sc_mask);
 148
 149        return err;
 150}
 151
 152static inline void __user *
 153get_sigframe(struct ksignal *ksig, struct pt_regs *regs, size_t frame_size)
 154{
 155        return (void __user *)((sigsp(rdusp(), ksig) - frame_size) & -8UL);
 156}
 157
 158static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
 159                          struct pt_regs *regs)
 160{
 161        struct rt_sigframe *frame;
 162        int err = 0;
 163        unsigned char *ret;
 164
 165        frame = get_sigframe(ksig, regs, sizeof(*frame));
 166
 167        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 168                return -EFAULT;
 169
 170        if (ksig->ka.sa.sa_flags & SA_SIGINFO)
 171                err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 172
 173        /* Create the ucontext.  */
 174        err |= __put_user(0, &frame->uc.uc_flags);
 175        err |= __put_user(0, &frame->uc.uc_link);
 176        err |= __save_altstack(&frame->uc.uc_stack, rdusp());
 177        err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]);
 178        err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 179        if (err)
 180                return -EFAULT;
 181
 182        /* Set up to return from userspace.  */
 183        ret = (unsigned char *)&frame->retcode;
 184        if (ksig->ka.sa.sa_flags & SA_RESTORER)
 185                ret = (unsigned char *)(ksig->ka.sa.sa_restorer);
 186        else {
 187                /* sub.l er0,er0; mov.b #__NR_rt_sigreturn,r0l; trapa #0 */
 188                err |= __put_user(0x1a80f800 + (__NR_rt_sigreturn & 0xff),
 189                                  (unsigned long *)(frame->retcode + 0));
 190                err |= __put_user(0x5700,
 191                                  (unsigned short *)(frame->retcode + 4));
 192        }
 193        err |= __put_user(ret, &frame->pretcode);
 194
 195        if (err)
 196                return -EFAULT;
 197
 198        /* Set up registers for signal handler */
 199        regs->sp  = (unsigned long)frame;
 200        regs->pc  = (unsigned long)ksig->ka.sa.sa_handler;
 201        regs->er0 = ksig->sig;
 202        regs->er1 = (unsigned long)&(frame->info);
 203        regs->er2 = (unsigned long)&frame->uc;
 204        regs->er5 = current->mm->start_data;    /* GOT base */
 205
 206        return 0;
 207}
 208
 209static void
 210handle_restart(struct pt_regs *regs, struct k_sigaction *ka)
 211{
 212        switch (regs->er0) {
 213        case -ERESTARTNOHAND:
 214                if (!ka)
 215                        goto do_restart;
 216                regs->er0 = -EINTR;
 217                break;
 218        case -ERESTART_RESTARTBLOCK:
 219                if (!ka) {
 220                        regs->er0 = __NR_restart_syscall;
 221                        regs->pc -= 2;
 222                } else
 223                        regs->er0 = -EINTR;
 224                break;
 225        case -ERESTARTSYS:
 226                if (!(ka->sa.sa_flags & SA_RESTART)) {
 227                        regs->er0 = -EINTR;
 228                        break;
 229                }
 230                /* fallthrough */
 231        case -ERESTARTNOINTR:
 232do_restart:
 233                regs->er0 = regs->orig_er0;
 234                regs->pc -= 2;
 235                break;
 236        }
 237}
 238
 239/*
 240 * OK, we're invoking a handler
 241 */
 242static void
 243handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 244{
 245        sigset_t *oldset = sigmask_to_save();
 246        int ret;
 247        /* are we from a system call? */
 248        if (regs->orig_er0 >= 0)
 249                handle_restart(regs, &ksig->ka);
 250
 251        ret = setup_rt_frame(ksig, oldset, regs);
 252
 253        signal_setup_done(ret, ksig, 0);
 254}
 255
 256/*
 257 * Note that 'init' is a special process: it doesn't get signals it doesn't
 258 * want to handle. Thus you cannot kill init even with a SIGKILL even by
 259 * mistake.
 260 */
 261static void do_signal(struct pt_regs *regs)
 262{
 263        struct ksignal ksig;
 264
 265        current->thread.esp0 = (unsigned long) regs;
 266
 267        if (get_signal(&ksig)) {
 268                /* Whee!  Actually deliver the signal.  */
 269                handle_signal(&ksig, regs);
 270                return;
 271        }
 272        /* Did we come from a system call? */
 273        if (regs->orig_er0 >= 0)
 274                handle_restart(regs, NULL);
 275
 276        /* If there's no signal to deliver, we just restore the saved mask.  */
 277        restore_saved_sigmask();
 278}
 279
 280asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
 281{
 282        if (thread_info_flags & _TIF_SIGPENDING)
 283                do_signal(regs);
 284
 285        if (thread_info_flags & _TIF_NOTIFY_RESUME) {
 286                clear_thread_flag(TIF_NOTIFY_RESUME);
 287                tracehook_notify_resume(regs);
 288        }
 289}
 290