~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to arch/m32r/kernel/signal.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  linux/arch/m32r/kernel/signal.c
 
3
 *
 
4
 *  Copyright (c) 2003  Hitoshi Yamamoto
 
5
 *
 
6
 *  Taken from i386 version.
 
7
 *  Copyright (C) 1991, 1992  Linus Torvalds
 
8
 *
 
9
 *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
 
10
 *  2000-06-20  Pentium III FXSR, SSE support by Gareth Hughes
 
11
 */
 
12
 
 
13
#include <linux/sched.h>
 
14
#include <linux/mm.h>
 
15
#include <linux/smp.h>
 
16
#include <linux/kernel.h>
 
17
#include <linux/signal.h>
 
18
#include <linux/errno.h>
 
19
#include <linux/wait.h>
 
20
#include <linux/unistd.h>
 
21
#include <linux/stddef.h>
 
22
#include <linux/personality.h>
 
23
#include <linux/freezer.h>
 
24
#include <linux/tracehook.h>
 
25
#include <asm/cacheflush.h>
 
26
#include <asm/ucontext.h>
 
27
#include <asm/uaccess.h>
 
28
 
 
29
#define DEBUG_SIG 0
 
30
 
 
31
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
32
 
 
33
asmlinkage int
 
34
sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
 
35
                unsigned long r2, unsigned long r3, unsigned long r4,
 
36
                unsigned long r5, unsigned long r6, struct pt_regs *regs)
 
37
{
 
38
        return do_sigaltstack(uss, uoss, regs->spu);
 
39
}
 
40
 
 
41
 
 
42
/*
 
43
 * Do a signal return; undo the signal stack.
 
44
 */
 
45
 
 
46
struct rt_sigframe
 
47
{
 
48
        int sig;
 
49
        struct siginfo __user *pinfo;
 
50
        void __user *puc;
 
51
        struct siginfo info;
 
52
        struct ucontext uc;
 
53
//      struct _fpstate fpstate;
 
54
};
 
55
 
 
56
static int
 
57
restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
 
58
                   int *r0_p)
 
59
{
 
60
        unsigned int err = 0;
 
61
 
 
62
        /* Always make any pending restarted system calls return -EINTR */
 
63
        current_thread_info()->restart_block.fn = do_no_restart_syscall;
 
64
 
 
65
#define COPY(x)         err |= __get_user(regs->x, &sc->sc_##x)
 
66
        COPY(r4);
 
67
        COPY(r5);
 
68
        COPY(r6);
 
69
        COPY(pt_regs);
 
70
        /* COPY(r0); Skip r0 */
 
71
        COPY(r1);
 
72
        COPY(r2);
 
73
        COPY(r3);
 
74
        COPY(r7);
 
75
        COPY(r8);
 
76
        COPY(r9);
 
77
        COPY(r10);
 
78
        COPY(r11);
 
79
        COPY(r12);
 
80
        COPY(acc0h);
 
81
        COPY(acc0l);
 
82
        COPY(acc1h);            /* ISA_DSP_LEVEL2 only */
 
83
        COPY(acc1l);            /* ISA_DSP_LEVEL2 only */
 
84
        COPY(psw);
 
85
        COPY(bpc);
 
86
        COPY(bbpsw);
 
87
        COPY(bbpc);
 
88
        COPY(spu);
 
89
        COPY(fp);
 
90
        COPY(lr);
 
91
        COPY(spi);
 
92
#undef COPY
 
93
 
 
94
        regs->syscall_nr = -1;  /* disable syscall checks */
 
95
        err |= __get_user(*r0_p, &sc->sc_r0);
 
96
 
 
97
        return err;
 
98
}
 
99
 
 
100
asmlinkage int
 
101
sys_rt_sigreturn(unsigned long r0, unsigned long r1,
 
102
                 unsigned long r2, unsigned long r3, unsigned long r4,
 
103
                 unsigned long r5, unsigned long r6, struct pt_regs *regs)
 
104
{
 
105
        struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs->spu;
 
106
        sigset_t set;
 
107
        int result;
 
108
 
 
109
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 
110
                goto badframe;
 
111
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
 
112
                goto badframe;
 
113
 
 
114
        sigdelsetmask(&set, ~_BLOCKABLE);
 
115
        spin_lock_irq(&current->sighand->siglock);
 
116
        current->blocked = set;
 
117
        recalc_sigpending();
 
118
        spin_unlock_irq(&current->sighand->siglock);
 
119
 
 
120
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &result))
 
121
                goto badframe;
 
122
 
 
123
        if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->spu) == -EFAULT)
 
124
                goto badframe;
 
125
 
 
126
        return result;
 
127
 
 
128
badframe:
 
129
        force_sig(SIGSEGV, current);
 
130
        return 0;
 
131
}
 
132
 
 
133
/*
 
134
 * Set up a signal frame.
 
135
 */
 
136
 
 
137
static int
 
138
setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
 
139
                 unsigned long mask)
 
140
{
 
141
        int err = 0;
 
142
 
 
143
#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x)
 
144
        COPY(r4);
 
145
        COPY(r5);
 
146
        COPY(r6);
 
147
        COPY(pt_regs);
 
148
        COPY(r0);
 
149
        COPY(r1);
 
150
        COPY(r2);
 
151
        COPY(r3);
 
152
        COPY(r7);
 
153
        COPY(r8);
 
154
        COPY(r9);
 
155
        COPY(r10);
 
156
        COPY(r11);
 
157
        COPY(r12);
 
158
        COPY(acc0h);
 
159
        COPY(acc0l);
 
160
        COPY(acc1h);            /* ISA_DSP_LEVEL2 only */
 
161
        COPY(acc1l);            /* ISA_DSP_LEVEL2 only */
 
162
        COPY(psw);
 
163
        COPY(bpc);
 
164
        COPY(bbpsw);
 
165
        COPY(bbpc);
 
166
        COPY(spu);
 
167
        COPY(fp);
 
168
        COPY(lr);
 
169
        COPY(spi);
 
170
#undef COPY
 
171
 
 
172
        err |= __put_user(mask, &sc->oldmask);
 
173
 
 
174
        return err;
 
175
}
 
176
 
 
177
/*
 
178
 * Determine which stack to use..
 
179
 */
 
180
static inline void __user *
 
181
get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
 
182
{
 
183
        /* This is the X/Open sanctioned signal stack switching.  */
 
184
        if (ka->sa.sa_flags & SA_ONSTACK) {
 
185
                if (sas_ss_flags(sp) == 0)
 
186
                        sp = current->sas_ss_sp + current->sas_ss_size;
 
187
        }
 
188
 
 
189
        return (void __user *)((sp - frame_size) & -8ul);
 
190
}
 
191
 
 
192
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 
193
                           sigset_t *set, struct pt_regs *regs)
 
194
{
 
195
        struct rt_sigframe __user *frame;
 
196
        int err = 0;
 
197
        int signal;
 
198
 
 
199
        frame = get_sigframe(ka, regs->spu, sizeof(*frame));
 
200
 
 
201
        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 
202
                goto give_sigsegv;
 
203
 
 
204
        signal = current_thread_info()->exec_domain
 
205
                && current_thread_info()->exec_domain->signal_invmap
 
206
                && sig < 32
 
207
                ? current_thread_info()->exec_domain->signal_invmap[sig]
 
208
                : sig;
 
209
 
 
210
        err |= __put_user(signal, &frame->sig);
 
211
        if (err)
 
212
                goto give_sigsegv;
 
213
 
 
214
        err |= __put_user(&frame->info, &frame->pinfo);
 
215
        err |= __put_user(&frame->uc, &frame->puc);
 
216
        err |= copy_siginfo_to_user(&frame->info, info);
 
217
        if (err)
 
218
                goto give_sigsegv;
 
219
 
 
220
        /* Create the ucontext.  */
 
221
        err |= __put_user(0, &frame->uc.uc_flags);
 
222
        err |= __put_user(0, &frame->uc.uc_link);
 
223
        err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
 
224
        err |= __put_user(sas_ss_flags(regs->spu),
 
225
                          &frame->uc.uc_stack.ss_flags);
 
226
        err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
 
227
        err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]);
 
228
        err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 
229
        if (err)
 
230
                goto give_sigsegv;
 
231
 
 
232
        /* Set up to return from userspace.  */
 
233
        regs->lr = (unsigned long)ka->sa.sa_restorer;
 
234
 
 
235
        /* Set up registers for signal handler */
 
236
        regs->spu = (unsigned long)frame;
 
237
        regs->r0 = signal;      /* Arg for signal handler */
 
238
        regs->r1 = (unsigned long)&frame->info;
 
239
        regs->r2 = (unsigned long)&frame->uc;
 
240
        regs->bpc = (unsigned long)ka->sa.sa_handler;
 
241
 
 
242
        set_fs(USER_DS);
 
243
 
 
244
#if DEBUG_SIG
 
245
        printk("SIG deliver (%s:%d): sp=%p pc=%p\n",
 
246
                current->comm, current->pid, frame, regs->pc);
 
247
#endif
 
248
 
 
249
        return 0;
 
250
 
 
251
give_sigsegv:
 
252
        force_sigsegv(sig, current);
 
253
        return -EFAULT;
 
254
}
 
255
 
 
256
static int prev_insn(struct pt_regs *regs)
 
257
{
 
258
        u16 inst;
 
259
        if (get_user(inst, (u16 __user *)(regs->bpc - 2)))
 
260
                return -EFAULT;
 
261
        if ((inst & 0xfff0) == 0x10f0)  /* trap ? */
 
262
                regs->bpc -= 2;
 
263
        else
 
264
                regs->bpc -= 4;
 
265
        regs->syscall_nr = -1;
 
266
        return 0;
 
267
}
 
268
 
 
269
/*
 
270
 * OK, we're invoking a handler
 
271
 */
 
272
 
 
273
static int
 
274
handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
 
275
              sigset_t *oldset, struct pt_regs *regs)
 
276
{
 
277
        /* Are we from a system call? */
 
278
        if (regs->syscall_nr >= 0) {
 
279
                /* If so, check system call restarting.. */
 
280
                switch (regs->r0) {
 
281
                        case -ERESTART_RESTARTBLOCK:
 
282
                        case -ERESTARTNOHAND:
 
283
                                regs->r0 = -EINTR;
 
284
                                break;
 
285
 
 
286
                        case -ERESTARTSYS:
 
287
                                if (!(ka->sa.sa_flags & SA_RESTART)) {
 
288
                                        regs->r0 = -EINTR;
 
289
                                        break;
 
290
                                }
 
291
                        /* fallthrough */
 
292
                        case -ERESTARTNOINTR:
 
293
                                regs->r0 = regs->orig_r0;
 
294
                                if (prev_insn(regs) < 0)
 
295
                                        return -EFAULT;
 
296
                }
 
297
        }
 
298
 
 
299
        /* Set up the stack frame */
 
300
        if (setup_rt_frame(sig, ka, info, oldset, regs))
 
301
                return -EFAULT;
 
302
 
 
303
        spin_lock_irq(&current->sighand->siglock);
 
304
        sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
 
305
        if (!(ka->sa.sa_flags & SA_NODEFER))
 
306
                sigaddset(&current->blocked,sig);
 
307
        recalc_sigpending();
 
308
        spin_unlock_irq(&current->sighand->siglock);
 
309
        return 0;
 
310
}
 
311
 
 
312
/*
 
313
 * Note that 'init' is a special process: it doesn't get signals it doesn't
 
314
 * want to handle. Thus you cannot kill init even with a SIGKILL even by
 
315
 * mistake.
 
316
 */
 
317
static void do_signal(struct pt_regs *regs)
 
318
{
 
319
        siginfo_t info;
 
320
        int signr;
 
321
        struct k_sigaction ka;
 
322
        sigset_t *oldset;
 
323
 
 
324
        /*
 
325
         * We want the common case to go fast, which
 
326
         * is why we may in certain cases get here from
 
327
         * kernel mode. Just return without doing anything
 
328
         * if so.
 
329
         */
 
330
        if (!user_mode(regs))
 
331
                return;
 
332
 
 
333
        if (try_to_freeze()) 
 
334
                goto no_signal;
 
335
 
 
336
        if (test_thread_flag(TIF_RESTORE_SIGMASK))
 
337
                oldset = &current->saved_sigmask;
 
338
        else
 
339
                oldset = &current->blocked;
 
340
 
 
341
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
342
        if (signr > 0) {
 
343
                /* Re-enable any watchpoints before delivering the
 
344
                 * signal to user space. The processor register will
 
345
                 * have been cleared if the watchpoint triggered
 
346
                 * inside the kernel.
 
347
                 */
 
348
 
 
349
                /* Whee!  Actually deliver the signal.  */
 
350
                if (handle_signal(signr, &ka, &info, oldset, regs) == 0)
 
351
                        clear_thread_flag(TIF_RESTORE_SIGMASK);
 
352
 
 
353
                return;
 
354
        }
 
355
 
 
356
 no_signal:
 
357
        /* Did we come from a system call? */
 
358
        if (regs->syscall_nr >= 0) {
 
359
                /* Restart the system call - no handlers present */
 
360
                if (regs->r0 == -ERESTARTNOHAND ||
 
361
                    regs->r0 == -ERESTARTSYS ||
 
362
                    regs->r0 == -ERESTARTNOINTR) {
 
363
                        regs->r0 = regs->orig_r0;
 
364
                        prev_insn(regs);
 
365
                } else if (regs->r0 == -ERESTART_RESTARTBLOCK){
 
366
                        regs->r0 = regs->orig_r0;
 
367
                        regs->r7 = __NR_restart_syscall;
 
368
                        prev_insn(regs);
 
369
                }
 
370
        }
 
371
        if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
 
372
                clear_thread_flag(TIF_RESTORE_SIGMASK);
 
373
                sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
 
374
        }
 
375
}
 
376
 
 
377
/*
 
378
 * notification of userspace execution resumption
 
379
 * - triggered by current->work.notify_resume
 
380
 */
 
381
void do_notify_resume(struct pt_regs *regs, __u32 thread_info_flags)
 
382
{
 
383
        /* Pending single-step? */
 
384
        if (thread_info_flags & _TIF_SINGLESTEP)
 
385
                clear_thread_flag(TIF_SINGLESTEP);
 
386
 
 
387
        /* deal with pending signal delivery */
 
388
        if (thread_info_flags & _TIF_SIGPENDING)
 
389
                do_signal(regs);
 
390
 
 
391
        if (thread_info_flags & _TIF_NOTIFY_RESUME) {
 
392
                clear_thread_flag(TIF_NOTIFY_RESUME);
 
393
                tracehook_notify_resume(regs);
 
394
                if (current->replacement_session_keyring)
 
395
                        key_replace_session_keyring();
 
396
        }
 
397
 
 
398
        clear_thread_flag(TIF_IRET);
 
399
}