aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m32r/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m32r/kernel/signal.c')
-rw-r--r--arch/m32r/kernel/signal.c103
1 files changed, 41 insertions, 62 deletions
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c
index 144b0f124fc7..a08697f0886d 100644
--- a/arch/m32r/kernel/signal.c
+++ b/arch/m32r/kernel/signal.c
@@ -30,35 +30,6 @@
30 30
31#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 31#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
32 32
33int do_signal(struct pt_regs *, sigset_t *);
34
35asmlinkage int
36sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize,
37 unsigned long r2, unsigned long r3, unsigned long r4,
38 unsigned long r5, unsigned long r6, struct pt_regs *regs)
39{
40 sigset_t newset;
41
42 /* XXX: Don't preclude handling different sized sigset_t's. */
43 if (sigsetsize != sizeof(sigset_t))
44 return -EINVAL;
45
46 if (copy_from_user(&newset, unewset, sizeof(newset)))
47 return -EFAULT;
48 sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
49
50 spin_lock_irq(&current->sighand->siglock);
51 current->saved_sigmask = current->blocked;
52 current->blocked = newset;
53 recalc_sigpending();
54 spin_unlock_irq(&current->sighand->siglock);
55
56 current->state = TASK_INTERRUPTIBLE;
57 schedule();
58 set_thread_flag(TIF_RESTORE_SIGMASK);
59 return -ERESTARTNOHAND;
60}
61
62asmlinkage int 33asmlinkage int
63sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, 34sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
64 unsigned long r2, unsigned long r3, unsigned long r4, 35 unsigned long r2, unsigned long r3, unsigned long r4,
@@ -218,7 +189,7 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
218 return (void __user *)((sp - frame_size) & -8ul); 189 return (void __user *)((sp - frame_size) & -8ul);
219} 190}
220 191
221static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 192static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
222 sigset_t *set, struct pt_regs *regs) 193 sigset_t *set, struct pt_regs *regs)
223{ 194{
224 struct rt_sigframe __user *frame; 195 struct rt_sigframe __user *frame;
@@ -275,22 +246,34 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
275 current->comm, current->pid, frame, regs->pc); 246 current->comm, current->pid, frame, regs->pc);
276#endif 247#endif
277 248
278 return; 249 return 0;
279 250
280give_sigsegv: 251give_sigsegv:
281 force_sigsegv(sig, current); 252 force_sigsegv(sig, current);
253 return -EFAULT;
254}
255
256static 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;
282} 267}
283 268
284/* 269/*
285 * OK, we're invoking a handler 270 * OK, we're invoking a handler
286 */ 271 */
287 272
288static void 273static int
289handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, 274handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
290 sigset_t *oldset, struct pt_regs *regs) 275 sigset_t *oldset, struct pt_regs *regs)
291{ 276{
292 unsigned short inst;
293
294 /* Are we from a system call? */ 277 /* Are we from a system call? */
295 if (regs->syscall_nr >= 0) { 278 if (regs->syscall_nr >= 0) {
296 /* If so, check system call restarting.. */ 279 /* If so, check system call restarting.. */
@@ -308,16 +291,14 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
308 /* fallthrough */ 291 /* fallthrough */
309 case -ERESTARTNOINTR: 292 case -ERESTARTNOINTR:
310 regs->r0 = regs->orig_r0; 293 regs->r0 = regs->orig_r0;
311 inst = *(unsigned short *)(regs->bpc - 2); 294 if (prev_insn(regs) < 0)
312 if ((inst & 0xfff0) == 0x10f0) /* trap ? */ 295 return -EFAULT;
313 regs->bpc -= 2;
314 else
315 regs->bpc -= 4;
316 } 296 }
317 } 297 }
318 298
319 /* Set up the stack frame */ 299 /* Set up the stack frame */
320 setup_rt_frame(sig, ka, info, oldset, regs); 300 if (setup_rt_frame(sig, ka, info, oldset, regs))
301 return -EFAULT;
321 302
322 spin_lock_irq(&current->sighand->siglock); 303 spin_lock_irq(&current->sighand->siglock);
323 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask); 304 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -325,6 +306,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
325 sigaddset(&current->blocked,sig); 306 sigaddset(&current->blocked,sig);
326 recalc_sigpending(); 307 recalc_sigpending();
327 spin_unlock_irq(&current->sighand->siglock); 308 spin_unlock_irq(&current->sighand->siglock);
309 return 0;
328} 310}
329 311
330/* 312/*
@@ -332,12 +314,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
332 * want to handle. Thus you cannot kill init even with a SIGKILL even by 314 * want to handle. Thus you cannot kill init even with a SIGKILL even by
333 * mistake. 315 * mistake.
334 */ 316 */
335int do_signal(struct pt_regs *regs, sigset_t *oldset) 317static void do_signal(struct pt_regs *regs)
336{ 318{
337 siginfo_t info; 319 siginfo_t info;
338 int signr; 320 int signr;
339 struct k_sigaction ka; 321 struct k_sigaction ka;
340 unsigned short inst; 322 sigset_t *oldset;
341 323
342 /* 324 /*
343 * We want the common case to go fast, which 325 * We want the common case to go fast, which
@@ -346,12 +328,14 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
346 * if so. 328 * if so.
347 */ 329 */
348 if (!user_mode(regs)) 330 if (!user_mode(regs))
349 return 1; 331 return;
350 332
351 if (try_to_freeze()) 333 if (try_to_freeze())
352 goto no_signal; 334 goto no_signal;
353 335
354 if (!oldset) 336 if (test_thread_flag(TIF_RESTORE_SIGMASK))
337 oldset = &current->saved_sigmask;
338 else
355 oldset = &current->blocked; 339 oldset = &current->blocked;
356 340
357 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 341 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
@@ -363,8 +347,10 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
363 */ 347 */
364 348
365 /* Whee! Actually deliver the signal. */ 349 /* Whee! Actually deliver the signal. */
366 handle_signal(signr, &ka, &info, oldset, regs); 350 if (handle_signal(signr, &ka, &info, oldset, regs) == 0)
367 return 1; 351 clear_thread_flag(TIF_RESTORE_SIGMASK);
352
353 return;
368 } 354 }
369 355
370 no_signal: 356 no_signal:
@@ -375,31 +361,24 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
375 regs->r0 == -ERESTARTSYS || 361 regs->r0 == -ERESTARTSYS ||
376 regs->r0 == -ERESTARTNOINTR) { 362 regs->r0 == -ERESTARTNOINTR) {
377 regs->r0 = regs->orig_r0; 363 regs->r0 = regs->orig_r0;
378 inst = *(unsigned short *)(regs->bpc - 2); 364 prev_insn(regs);
379 if ((inst & 0xfff0) == 0x10f0) /* trap ? */ 365 } else if (regs->r0 == -ERESTART_RESTARTBLOCK){
380 regs->bpc -= 2;
381 else
382 regs->bpc -= 4;
383 }
384 if (regs->r0 == -ERESTART_RESTARTBLOCK){
385 regs->r0 = regs->orig_r0; 366 regs->r0 = regs->orig_r0;
386 regs->r7 = __NR_restart_syscall; 367 regs->r7 = __NR_restart_syscall;
387 inst = *(unsigned short *)(regs->bpc - 2); 368 prev_insn(regs);
388 if ((inst & 0xfff0) == 0x10f0) /* trap ? */
389 regs->bpc -= 2;
390 else
391 regs->bpc -= 4;
392 } 369 }
393 } 370 }
394 return 0; 371 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
372 clear_thread_flag(TIF_RESTORE_SIGMASK);
373 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
374 }
395} 375}
396 376
397/* 377/*
398 * notification of userspace execution resumption 378 * notification of userspace execution resumption
399 * - triggered by current->work.notify_resume 379 * - triggered by current->work.notify_resume
400 */ 380 */
401void do_notify_resume(struct pt_regs *regs, sigset_t *oldset, 381void do_notify_resume(struct pt_regs *regs, __u32 thread_info_flags)
402 __u32 thread_info_flags)
403{ 382{
404 /* Pending single-step? */ 383 /* Pending single-step? */
405 if (thread_info_flags & _TIF_SINGLESTEP) 384 if (thread_info_flags & _TIF_SINGLESTEP)
@@ -407,7 +386,7 @@ void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
407 386
408 /* deal with pending signal delivery */ 387 /* deal with pending signal delivery */
409 if (thread_info_flags & _TIF_SIGPENDING) 388 if (thread_info_flags & _TIF_SIGPENDING)
410 do_signal(regs,oldset); 389 do_signal(regs);
411 390
412 if (thread_info_flags & _TIF_NOTIFY_RESUME) { 391 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
413 clear_thread_flag(TIF_NOTIFY_RESUME); 392 clear_thread_flag(TIF_NOTIFY_RESUME);