diff options
| -rw-r--r-- | arch/m68k/include/asm/sun3_pgtable.h | 5 | ||||
| -rw-r--r-- | arch/m68k/include/asm/thread_info.h | 1 | ||||
| -rw-r--r-- | arch/m68k/include/asm/unistd.h | 1 | ||||
| -rw-r--r-- | arch/m68k/kernel/entry.S | 30 | ||||
| -rw-r--r-- | arch/m68k/kernel/signal.c | 314 | ||||
| -rw-r--r-- | arch/m68knommu/kernel/entry.S | 16 | ||||
| -rw-r--r-- | arch/m68knommu/kernel/signal.c | 188 | ||||
| -rw-r--r-- | arch/m68knommu/platform/68328/entry.S | 7 | ||||
| -rw-r--r-- | arch/m68knommu/platform/68360/entry.S | 7 | ||||
| -rw-r--r-- | arch/m68knommu/platform/coldfire/entry.S | 5 |
10 files changed, 231 insertions, 343 deletions
diff --git a/arch/m68k/include/asm/sun3_pgtable.h b/arch/m68k/include/asm/sun3_pgtable.h index cf5fad9b5250..f55aa04161e8 100644 --- a/arch/m68k/include/asm/sun3_pgtable.h +++ b/arch/m68k/include/asm/sun3_pgtable.h | |||
| @@ -217,9 +217,8 @@ static inline pte_t pgoff_to_pte(unsigned off) | |||
| 217 | /* Find an entry in the third-level pagetable. */ | 217 | /* Find an entry in the third-level pagetable. */ |
| 218 | #define pte_index(address) ((address >> PAGE_SHIFT) & (PTRS_PER_PTE-1)) | 218 | #define pte_index(address) ((address >> PAGE_SHIFT) & (PTRS_PER_PTE-1)) |
| 219 | #define pte_offset_kernel(pmd, address) ((pte_t *) __pmd_page(*pmd) + pte_index(address)) | 219 | #define pte_offset_kernel(pmd, address) ((pte_t *) __pmd_page(*pmd) + pte_index(address)) |
| 220 | /* FIXME: should we bother with kmap() here? */ | 220 | #define pte_offset_map(pmd, address) ((pte_t *)page_address(pmd_page(*pmd)) + pte_index(address)) |
| 221 | #define pte_offset_map(pmd, address) ((pte_t *)kmap(pmd_page(*pmd)) + pte_index(address)) | 221 | #define pte_unmap(pte) do { } while (0) |
| 222 | #define pte_unmap(pte) kunmap(pte) | ||
| 223 | 222 | ||
| 224 | /* Macros to (de)construct the fake PTEs representing swap pages. */ | 223 | /* Macros to (de)construct the fake PTEs representing swap pages. */ |
| 225 | #define __swp_type(x) ((x).val & 0x7F) | 224 | #define __swp_type(x) ((x).val & 0x7F) |
diff --git a/arch/m68k/include/asm/thread_info.h b/arch/m68k/include/asm/thread_info.h index 1da5d53a00eb..790988967ba7 100644 --- a/arch/m68k/include/asm/thread_info.h +++ b/arch/m68k/include/asm/thread_info.h | |||
| @@ -104,5 +104,6 @@ static inline struct thread_info *current_thread_info(void) | |||
| 104 | #define TIF_SYSCALL_TRACE 15 /* syscall trace active */ | 104 | #define TIF_SYSCALL_TRACE 15 /* syscall trace active */ |
| 105 | #define TIF_MEMDIE 16 /* is terminating due to OOM killer */ | 105 | #define TIF_MEMDIE 16 /* is terminating due to OOM killer */ |
| 106 | #define TIF_FREEZE 17 /* thread is freezing for suspend */ | 106 | #define TIF_FREEZE 17 /* thread is freezing for suspend */ |
| 107 | #define TIF_RESTORE_SIGMASK 18 /* restore signal mask in do_signal */ | ||
| 107 | 108 | ||
| 108 | #endif /* _ASM_M68K_THREAD_INFO_H */ | 109 | #endif /* _ASM_M68K_THREAD_INFO_H */ |
diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h index b43b36beafe3..26d851d385bb 100644 --- a/arch/m68k/include/asm/unistd.h +++ b/arch/m68k/include/asm/unistd.h | |||
| @@ -373,6 +373,7 @@ | |||
| 373 | #define __ARCH_WANT_SYS_SIGPENDING | 373 | #define __ARCH_WANT_SYS_SIGPENDING |
| 374 | #define __ARCH_WANT_SYS_SIGPROCMASK | 374 | #define __ARCH_WANT_SYS_SIGPROCMASK |
| 375 | #define __ARCH_WANT_SYS_RT_SIGACTION | 375 | #define __ARCH_WANT_SYS_RT_SIGACTION |
| 376 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND | ||
| 376 | 377 | ||
| 377 | /* | 378 | /* |
| 378 | * "Conditional" syscalls | 379 | * "Conditional" syscalls |
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index 6360c437dcf5..1559dea36e55 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S | |||
| @@ -99,7 +99,10 @@ do_trace_exit: | |||
| 99 | jra .Lret_from_exception | 99 | jra .Lret_from_exception |
| 100 | 100 | ||
| 101 | ENTRY(ret_from_signal) | 101 | ENTRY(ret_from_signal) |
| 102 | RESTORE_SWITCH_STACK | 102 | tstb %curptr@(TASK_INFO+TINFO_FLAGS+2) |
| 103 | jge 1f | ||
| 104 | jbsr syscall_trace | ||
| 105 | 1: RESTORE_SWITCH_STACK | ||
| 103 | addql #4,%sp | 106 | addql #4,%sp |
| 104 | /* on 68040 complete pending writebacks if any */ | 107 | /* on 68040 complete pending writebacks if any */ |
| 105 | #ifdef CONFIG_M68040 | 108 | #ifdef CONFIG_M68040 |
| @@ -174,16 +177,11 @@ do_signal_return: | |||
| 174 | subql #4,%sp | dummy return address | 177 | subql #4,%sp | dummy return address |
| 175 | SAVE_SWITCH_STACK | 178 | SAVE_SWITCH_STACK |
| 176 | pea %sp@(SWITCH_STACK_SIZE) | 179 | pea %sp@(SWITCH_STACK_SIZE) |
| 177 | clrl %sp@- | ||
| 178 | bsrl do_signal | 180 | bsrl do_signal |
| 179 | addql #8,%sp | 181 | addql #4,%sp |
| 180 | RESTORE_SWITCH_STACK | 182 | RESTORE_SWITCH_STACK |
| 181 | addql #4,%sp | 183 | addql #4,%sp |
| 182 | tstl %d0 | 184 | jbra resume_userspace |
| 183 | jeq resume_userspace | ||
| 184 | | when single stepping into handler stop at the first insn | ||
| 185 | btst #6,%curptr@(TASK_INFO+TINFO_FLAGS+2) | ||
| 186 | jeq resume_userspace | ||
| 187 | 185 | ||
| 188 | do_delayed_trace: | 186 | do_delayed_trace: |
| 189 | bclr #7,%sp@(PT_OFF_SR) | clear trace bit in SR | 187 | bclr #7,%sp@(PT_OFF_SR) | clear trace bit in SR |
| @@ -290,22 +288,6 @@ ENTRY(sys_vfork) | |||
| 290 | RESTORE_SWITCH_STACK | 288 | RESTORE_SWITCH_STACK |
| 291 | rts | 289 | rts |
| 292 | 290 | ||
| 293 | ENTRY(sys_sigsuspend) | ||
| 294 | SAVE_SWITCH_STACK | ||
| 295 | pea %sp@(SWITCH_STACK_SIZE) | ||
| 296 | jbsr do_sigsuspend | ||
| 297 | addql #4,%sp | ||
| 298 | RESTORE_SWITCH_STACK | ||
| 299 | rts | ||
| 300 | |||
| 301 | ENTRY(sys_rt_sigsuspend) | ||
| 302 | SAVE_SWITCH_STACK | ||
| 303 | pea %sp@(SWITCH_STACK_SIZE) | ||
| 304 | jbsr do_rt_sigsuspend | ||
| 305 | addql #4,%sp | ||
| 306 | RESTORE_SWITCH_STACK | ||
| 307 | rts | ||
| 308 | |||
| 309 | ENTRY(sys_sigreturn) | 291 | ENTRY(sys_sigreturn) |
| 310 | SAVE_SWITCH_STACK | 292 | SAVE_SWITCH_STACK |
| 311 | jbsr do_sigreturn | 293 | jbsr do_sigreturn |
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c index 4b387538706f..d12c3b0d9e4f 100644 --- a/arch/m68k/kernel/signal.c +++ b/arch/m68k/kernel/signal.c | |||
| @@ -51,8 +51,6 @@ | |||
| 51 | 51 | ||
| 52 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 52 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
| 53 | 53 | ||
| 54 | asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); | ||
| 55 | |||
| 56 | const int frame_extra_sizes[16] = { | 54 | const int frame_extra_sizes[16] = { |
| 57 | [1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */ | 55 | [1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */ |
| 58 | [2] = sizeof(((struct frame *)0)->un.fmt2), | 56 | [2] = sizeof(((struct frame *)0)->un.fmt2), |
| @@ -74,51 +72,21 @@ const int frame_extra_sizes[16] = { | |||
| 74 | /* | 72 | /* |
| 75 | * Atomically swap in the new signal mask, and wait for a signal. | 73 | * Atomically swap in the new signal mask, and wait for a signal. |
| 76 | */ | 74 | */ |
| 77 | asmlinkage int do_sigsuspend(struct pt_regs *regs) | 75 | asmlinkage int |
| 76 | sys_sigsuspend(int unused0, int unused1, old_sigset_t mask) | ||
| 78 | { | 77 | { |
| 79 | old_sigset_t mask = regs->d3; | ||
| 80 | sigset_t saveset; | ||
| 81 | |||
| 82 | mask &= _BLOCKABLE; | 78 | mask &= _BLOCKABLE; |
| 83 | saveset = current->blocked; | 79 | spin_lock_irq(¤t->sighand->siglock); |
| 80 | current->saved_sigmask = current->blocked; | ||
| 84 | siginitset(¤t->blocked, mask); | 81 | siginitset(¤t->blocked, mask); |
| 85 | recalc_sigpending(); | 82 | recalc_sigpending(); |
| 83 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 86 | 84 | ||
| 87 | regs->d0 = -EINTR; | 85 | current->state = TASK_INTERRUPTIBLE; |
| 88 | while (1) { | 86 | schedule(); |
| 89 | current->state = TASK_INTERRUPTIBLE; | 87 | set_restore_sigmask(); |
| 90 | schedule(); | ||
| 91 | if (do_signal(&saveset, regs)) | ||
| 92 | return -EINTR; | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | asmlinkage int | ||
| 97 | do_rt_sigsuspend(struct pt_regs *regs) | ||
| 98 | { | ||
| 99 | sigset_t __user *unewset = (sigset_t __user *)regs->d1; | ||
| 100 | size_t sigsetsize = (size_t)regs->d2; | ||
| 101 | sigset_t saveset, newset; | ||
| 102 | |||
| 103 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
| 104 | if (sigsetsize != sizeof(sigset_t)) | ||
| 105 | return -EINVAL; | ||
| 106 | 88 | ||
| 107 | if (copy_from_user(&newset, unewset, sizeof(newset))) | 89 | return -ERESTARTNOHAND; |
| 108 | return -EFAULT; | ||
| 109 | sigdelsetmask(&newset, ~_BLOCKABLE); | ||
| 110 | |||
| 111 | saveset = current->blocked; | ||
| 112 | current->blocked = newset; | ||
| 113 | recalc_sigpending(); | ||
| 114 | |||
| 115 | regs->d0 = -EINTR; | ||
| 116 | while (1) { | ||
| 117 | current->state = TASK_INTERRUPTIBLE; | ||
| 118 | schedule(); | ||
| 119 | if (do_signal(&saveset, regs)) | ||
| 120 | return -EINTR; | ||
| 121 | } | ||
| 122 | } | 90 | } |
| 123 | 91 | ||
| 124 | asmlinkage int | 92 | asmlinkage int |
| @@ -132,10 +100,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, | |||
| 132 | old_sigset_t mask; | 100 | old_sigset_t mask; |
| 133 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || | 101 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || |
| 134 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || | 102 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || |
| 135 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) | 103 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) || |
| 104 | __get_user(new_ka.sa.sa_flags, &act->sa_flags) || | ||
| 105 | __get_user(mask, &act->sa_mask)) | ||
| 136 | return -EFAULT; | 106 | return -EFAULT; |
| 137 | __get_user(new_ka.sa.sa_flags, &act->sa_flags); | ||
| 138 | __get_user(mask, &act->sa_mask); | ||
| 139 | siginitset(&new_ka.sa.sa_mask, mask); | 107 | siginitset(&new_ka.sa.sa_mask, mask); |
| 140 | } | 108 | } |
| 141 | 109 | ||
| @@ -144,10 +112,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, | |||
| 144 | if (!ret && oact) { | 112 | if (!ret && oact) { |
| 145 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || | 113 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || |
| 146 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || | 114 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || |
| 147 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) | 115 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) || |
| 116 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || | ||
| 117 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) | ||
| 148 | return -EFAULT; | 118 | return -EFAULT; |
| 149 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags); | ||
| 150 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); | ||
| 151 | } | 119 | } |
| 152 | 120 | ||
| 153 | return ret; | 121 | return ret; |
| @@ -318,36 +286,10 @@ out: | |||
| 318 | return err; | 286 | return err; |
| 319 | } | 287 | } |
| 320 | 288 | ||
| 321 | static inline int | 289 | static int mangle_kernel_stack(struct pt_regs *regs, int formatvec, |
| 322 | restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp, | 290 | void __user *fp) |
| 323 | int *pd0) | ||
| 324 | { | 291 | { |
| 325 | int fsize, formatvec; | 292 | int fsize = frame_extra_sizes[formatvec >> 12]; |
| 326 | struct sigcontext context; | ||
| 327 | int err; | ||
| 328 | |||
| 329 | /* Always make any pending restarted system calls return -EINTR */ | ||
| 330 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
| 331 | |||
| 332 | /* get previous context */ | ||
| 333 | if (copy_from_user(&context, usc, sizeof(context))) | ||
| 334 | goto badframe; | ||
| 335 | |||
| 336 | /* restore passed registers */ | ||
| 337 | regs->d1 = context.sc_d1; | ||
| 338 | regs->a0 = context.sc_a0; | ||
| 339 | regs->a1 = context.sc_a1; | ||
| 340 | regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff); | ||
| 341 | regs->pc = context.sc_pc; | ||
| 342 | regs->orig_d0 = -1; /* disable syscall checks */ | ||
| 343 | wrusp(context.sc_usp); | ||
| 344 | formatvec = context.sc_formatvec; | ||
| 345 | regs->format = formatvec >> 12; | ||
| 346 | regs->vector = formatvec & 0xfff; | ||
| 347 | |||
| 348 | err = restore_fpu_state(&context); | ||
| 349 | |||
| 350 | fsize = frame_extra_sizes[regs->format]; | ||
| 351 | if (fsize < 0) { | 293 | if (fsize < 0) { |
| 352 | /* | 294 | /* |
| 353 | * user process trying to return with weird frame format | 295 | * user process trying to return with weird frame format |
| @@ -355,16 +297,22 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u | |||
| 355 | #ifdef DEBUG | 297 | #ifdef DEBUG |
| 356 | printk("user process returning with weird frame format\n"); | 298 | printk("user process returning with weird frame format\n"); |
| 357 | #endif | 299 | #endif |
| 358 | goto badframe; | 300 | return 1; |
| 359 | } | 301 | } |
| 302 | if (!fsize) { | ||
| 303 | regs->format = formatvec >> 12; | ||
| 304 | regs->vector = formatvec & 0xfff; | ||
| 305 | } else { | ||
| 306 | struct switch_stack *sw = (struct switch_stack *)regs - 1; | ||
| 307 | unsigned long buf[fsize / 2]; /* yes, twice as much */ | ||
| 360 | 308 | ||
| 361 | /* OK. Make room on the supervisor stack for the extra junk, | 309 | /* that'll make sure that expansion won't crap over data */ |
| 362 | * if necessary. | 310 | if (copy_from_user(buf + fsize / 4, fp, fsize)) |
| 363 | */ | 311 | return 1; |
| 364 | 312 | ||
| 365 | if (fsize) { | 313 | /* point of no return */ |
| 366 | struct switch_stack *sw = (struct switch_stack *)regs - 1; | 314 | regs->format = formatvec >> 12; |
| 367 | regs->d0 = context.sc_d0; | 315 | regs->vector = formatvec & 0xfff; |
| 368 | #define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack)) | 316 | #define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack)) |
| 369 | __asm__ __volatile__ | 317 | __asm__ __volatile__ |
| 370 | (" movel %0,%/a0\n\t" | 318 | (" movel %0,%/a0\n\t" |
| @@ -376,30 +324,50 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u | |||
| 376 | " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */ | 324 | " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */ |
| 377 | " lsrl #2,%1\n\t" | 325 | " lsrl #2,%1\n\t" |
| 378 | " subql #1,%1\n\t" | 326 | " subql #1,%1\n\t" |
| 379 | "2: movesl %4@+,%2\n\t" | 327 | /* copy to the gap we'd made */ |
| 380 | "3: movel %2,%/a0@+\n\t" | 328 | "2: movel %4@+,%/a0@+\n\t" |
| 381 | " dbra %1,2b\n\t" | 329 | " dbra %1,2b\n\t" |
| 382 | " bral ret_from_signal\n" | 330 | " bral ret_from_signal\n" |
| 383 | "4:\n" | ||
| 384 | ".section __ex_table,\"a\"\n" | ||
| 385 | " .align 4\n" | ||
| 386 | " .long 2b,4b\n" | ||
| 387 | " .long 3b,4b\n" | ||
| 388 | ".previous" | ||
| 389 | : /* no outputs, it doesn't ever return */ | 331 | : /* no outputs, it doesn't ever return */ |
| 390 | : "a" (sw), "d" (fsize), "d" (frame_offset/4-1), | 332 | : "a" (sw), "d" (fsize), "d" (frame_offset/4-1), |
| 391 | "n" (frame_offset), "a" (fp) | 333 | "n" (frame_offset), "a" (buf + fsize/4) |
| 392 | : "a0"); | 334 | : "a0"); |
| 393 | #undef frame_offset | 335 | #undef frame_offset |
| 394 | /* | ||
| 395 | * If we ever get here an exception occurred while | ||
| 396 | * building the above stack-frame. | ||
| 397 | */ | ||
| 398 | goto badframe; | ||
| 399 | } | 336 | } |
| 337 | return 0; | ||
| 338 | } | ||
| 400 | 339 | ||
| 401 | *pd0 = context.sc_d0; | 340 | static inline int |
| 402 | return err; | 341 | restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp) |
| 342 | { | ||
| 343 | int formatvec; | ||
| 344 | struct sigcontext context; | ||
| 345 | int err; | ||
| 346 | |||
| 347 | /* Always make any pending restarted system calls return -EINTR */ | ||
| 348 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
| 349 | |||
| 350 | /* get previous context */ | ||
| 351 | if (copy_from_user(&context, usc, sizeof(context))) | ||
| 352 | goto badframe; | ||
| 353 | |||
| 354 | /* restore passed registers */ | ||
| 355 | regs->d0 = context.sc_d0; | ||
| 356 | regs->d1 = context.sc_d1; | ||
| 357 | regs->a0 = context.sc_a0; | ||
| 358 | regs->a1 = context.sc_a1; | ||
| 359 | regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff); | ||
| 360 | regs->pc = context.sc_pc; | ||
| 361 | regs->orig_d0 = -1; /* disable syscall checks */ | ||
| 362 | wrusp(context.sc_usp); | ||
| 363 | formatvec = context.sc_formatvec; | ||
| 364 | |||
| 365 | err = restore_fpu_state(&context); | ||
| 366 | |||
| 367 | if (err || mangle_kernel_stack(regs, formatvec, fp)) | ||
| 368 | goto badframe; | ||
| 369 | |||
| 370 | return 0; | ||
| 403 | 371 | ||
| 404 | badframe: | 372 | badframe: |
| 405 | return 1; | 373 | return 1; |
| @@ -407,9 +375,9 @@ badframe: | |||
| 407 | 375 | ||
| 408 | static inline int | 376 | static inline int |
| 409 | rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw, | 377 | rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw, |
| 410 | struct ucontext __user *uc, int *pd0) | 378 | struct ucontext __user *uc) |
| 411 | { | 379 | { |
| 412 | int fsize, temp; | 380 | int temp; |
| 413 | greg_t __user *gregs = uc->uc_mcontext.gregs; | 381 | greg_t __user *gregs = uc->uc_mcontext.gregs; |
| 414 | unsigned long usp; | 382 | unsigned long usp; |
| 415 | int err; | 383 | int err; |
| @@ -443,65 +411,16 @@ rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw, | |||
| 443 | regs->sr = (regs->sr & 0xff00) | (temp & 0xff); | 411 | regs->sr = (regs->sr & 0xff00) | (temp & 0xff); |
| 444 | regs->orig_d0 = -1; /* disable syscall checks */ | 412 | regs->orig_d0 = -1; /* disable syscall checks */ |
| 445 | err |= __get_user(temp, &uc->uc_formatvec); | 413 | err |= __get_user(temp, &uc->uc_formatvec); |
| 446 | regs->format = temp >> 12; | ||
| 447 | regs->vector = temp & 0xfff; | ||
| 448 | 414 | ||
| 449 | err |= rt_restore_fpu_state(uc); | 415 | err |= rt_restore_fpu_state(uc); |
| 450 | 416 | ||
| 451 | if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT) | 417 | if (err || do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT) |
| 452 | goto badframe; | 418 | goto badframe; |
| 453 | 419 | ||
| 454 | fsize = frame_extra_sizes[regs->format]; | 420 | if (mangle_kernel_stack(regs, temp, &uc->uc_extra)) |
| 455 | if (fsize < 0) { | ||
| 456 | /* | ||
| 457 | * user process trying to return with weird frame format | ||
| 458 | */ | ||
| 459 | #ifdef DEBUG | ||
| 460 | printk("user process returning with weird frame format\n"); | ||
| 461 | #endif | ||
| 462 | goto badframe; | 421 | goto badframe; |
| 463 | } | ||
| 464 | |||
| 465 | /* OK. Make room on the supervisor stack for the extra junk, | ||
| 466 | * if necessary. | ||
| 467 | */ | ||
| 468 | 422 | ||
| 469 | if (fsize) { | 423 | return 0; |
| 470 | #define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack)) | ||
| 471 | __asm__ __volatile__ | ||
| 472 | (" movel %0,%/a0\n\t" | ||
| 473 | " subl %1,%/a0\n\t" /* make room on stack */ | ||
| 474 | " movel %/a0,%/sp\n\t" /* set stack pointer */ | ||
| 475 | /* move switch_stack and pt_regs */ | ||
| 476 | "1: movel %0@+,%/a0@+\n\t" | ||
| 477 | " dbra %2,1b\n\t" | ||
| 478 | " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */ | ||
| 479 | " lsrl #2,%1\n\t" | ||
| 480 | " subql #1,%1\n\t" | ||
| 481 | "2: movesl %4@+,%2\n\t" | ||
| 482 | "3: movel %2,%/a0@+\n\t" | ||
| 483 | " dbra %1,2b\n\t" | ||
| 484 | " bral ret_from_signal\n" | ||
| 485 | "4:\n" | ||
| 486 | ".section __ex_table,\"a\"\n" | ||
| 487 | " .align 4\n" | ||
| 488 | " .long 2b,4b\n" | ||
| 489 | " .long 3b,4b\n" | ||
| 490 | ".previous" | ||
| 491 | : /* no outputs, it doesn't ever return */ | ||
| 492 | : "a" (sw), "d" (fsize), "d" (frame_offset/4-1), | ||
| 493 | "n" (frame_offset), "a" (&uc->uc_extra) | ||
| 494 | : "a0"); | ||
| 495 | #undef frame_offset | ||
| 496 | /* | ||
| 497 | * If we ever get here an exception occurred while | ||
| 498 | * building the above stack-frame. | ||
| 499 | */ | ||
| 500 | goto badframe; | ||
| 501 | } | ||
| 502 | |||
| 503 | *pd0 = regs->d0; | ||
| 504 | return err; | ||
| 505 | 424 | ||
| 506 | badframe: | 425 | badframe: |
| 507 | return 1; | 426 | return 1; |
| @@ -514,7 +433,6 @@ asmlinkage int do_sigreturn(unsigned long __unused) | |||
| 514 | unsigned long usp = rdusp(); | 433 | unsigned long usp = rdusp(); |
| 515 | struct sigframe __user *frame = (struct sigframe __user *)(usp - 4); | 434 | struct sigframe __user *frame = (struct sigframe __user *)(usp - 4); |
| 516 | sigset_t set; | 435 | sigset_t set; |
| 517 | int d0; | ||
| 518 | 436 | ||
| 519 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 437 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
| 520 | goto badframe; | 438 | goto badframe; |
| @@ -528,9 +446,9 @@ asmlinkage int do_sigreturn(unsigned long __unused) | |||
| 528 | current->blocked = set; | 446 | current->blocked = set; |
| 529 | recalc_sigpending(); | 447 | recalc_sigpending(); |
| 530 | 448 | ||
| 531 | if (restore_sigcontext(regs, &frame->sc, frame + 1, &d0)) | 449 | if (restore_sigcontext(regs, &frame->sc, frame + 1)) |
| 532 | goto badframe; | 450 | goto badframe; |
| 533 | return d0; | 451 | return regs->d0; |
| 534 | 452 | ||
| 535 | badframe: | 453 | badframe: |
| 536 | force_sig(SIGSEGV, current); | 454 | force_sig(SIGSEGV, current); |
| @@ -544,7 +462,6 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused) | |||
| 544 | unsigned long usp = rdusp(); | 462 | unsigned long usp = rdusp(); |
| 545 | struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4); | 463 | struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4); |
| 546 | sigset_t set; | 464 | sigset_t set; |
| 547 | int d0; | ||
| 548 | 465 | ||
| 549 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 466 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
| 550 | goto badframe; | 467 | goto badframe; |
| @@ -555,9 +472,9 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused) | |||
| 555 | current->blocked = set; | 472 | current->blocked = set; |
| 556 | recalc_sigpending(); | 473 | recalc_sigpending(); |
| 557 | 474 | ||
| 558 | if (rt_restore_ucontext(regs, sw, &frame->uc, &d0)) | 475 | if (rt_restore_ucontext(regs, sw, &frame->uc)) |
| 559 | goto badframe; | 476 | goto badframe; |
| 560 | return d0; | 477 | return regs->d0; |
| 561 | 478 | ||
| 562 | badframe: | 479 | badframe: |
| 563 | force_sig(SIGSEGV, current); | 480 | force_sig(SIGSEGV, current); |
| @@ -775,7 +692,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) | |||
| 775 | return (void __user *)((usp - frame_size) & -8UL); | 692 | return (void __user *)((usp - frame_size) & -8UL); |
| 776 | } | 693 | } |
| 777 | 694 | ||
| 778 | static void setup_frame (int sig, struct k_sigaction *ka, | 695 | static int setup_frame (int sig, struct k_sigaction *ka, |
| 779 | sigset_t *set, struct pt_regs *regs) | 696 | sigset_t *set, struct pt_regs *regs) |
| 780 | { | 697 | { |
| 781 | struct sigframe __user *frame; | 698 | struct sigframe __user *frame; |
| @@ -793,10 +710,8 @@ static void setup_frame (int sig, struct k_sigaction *ka, | |||
| 793 | 710 | ||
| 794 | frame = get_sigframe(ka, regs, sizeof(*frame) + fsize); | 711 | frame = get_sigframe(ka, regs, sizeof(*frame) + fsize); |
| 795 | 712 | ||
| 796 | if (fsize) { | 713 | if (fsize) |
| 797 | err |= copy_to_user (frame + 1, regs + 1, fsize); | 714 | err |= copy_to_user (frame + 1, regs + 1, fsize); |
| 798 | regs->stkadj = fsize; | ||
| 799 | } | ||
| 800 | 715 | ||
| 801 | err |= __put_user((current_thread_info()->exec_domain | 716 | err |= __put_user((current_thread_info()->exec_domain |
| 802 | && current_thread_info()->exec_domain->signal_invmap | 717 | && current_thread_info()->exec_domain->signal_invmap |
| @@ -826,11 +741,21 @@ static void setup_frame (int sig, struct k_sigaction *ka, | |||
| 826 | 741 | ||
| 827 | push_cache ((unsigned long) &frame->retcode); | 742 | push_cache ((unsigned long) &frame->retcode); |
| 828 | 743 | ||
| 829 | /* Set up registers for signal handler */ | 744 | /* |
| 745 | * Set up registers for signal handler. All the state we are about | ||
| 746 | * to destroy is successfully copied to sigframe. | ||
| 747 | */ | ||
| 830 | wrusp ((unsigned long) frame); | 748 | wrusp ((unsigned long) frame); |
| 831 | regs->pc = (unsigned long) ka->sa.sa_handler; | 749 | regs->pc = (unsigned long) ka->sa.sa_handler; |
| 832 | 750 | ||
| 833 | adjust_stack: | 751 | /* |
| 752 | * This is subtle; if we build more than one sigframe, all but the | ||
| 753 | * first one will see frame format 0 and have fsize == 0, so we won't | ||
| 754 | * screw stkadj. | ||
| 755 | */ | ||
| 756 | if (fsize) | ||
| 757 | regs->stkadj = fsize; | ||
| 758 | |||
| 834 | /* Prepare to skip over the extra stuff in the exception frame. */ | 759 | /* Prepare to skip over the extra stuff in the exception frame. */ |
| 835 | if (regs->stkadj) { | 760 | if (regs->stkadj) { |
| 836 | struct pt_regs *tregs = | 761 | struct pt_regs *tregs = |
| @@ -845,14 +770,14 @@ adjust_stack: | |||
| 845 | tregs->pc = regs->pc; | 770 | tregs->pc = regs->pc; |
| 846 | tregs->sr = regs->sr; | 771 | tregs->sr = regs->sr; |
| 847 | } | 772 | } |
| 848 | return; | 773 | return 0; |
| 849 | 774 | ||
| 850 | give_sigsegv: | 775 | give_sigsegv: |
| 851 | force_sigsegv(sig, current); | 776 | force_sigsegv(sig, current); |
| 852 | goto adjust_stack; | 777 | return err; |
| 853 | } | 778 | } |
| 854 | 779 | ||
| 855 | static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, | 780 | static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, |
| 856 | sigset_t *set, struct pt_regs *regs) | 781 | sigset_t *set, struct pt_regs *regs) |
| 857 | { | 782 | { |
| 858 | struct rt_sigframe __user *frame; | 783 | struct rt_sigframe __user *frame; |
| @@ -869,10 +794,8 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 869 | 794 | ||
| 870 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 795 | frame = get_sigframe(ka, regs, sizeof(*frame)); |
| 871 | 796 | ||
| 872 | if (fsize) { | 797 | if (fsize) |
| 873 | err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize); | 798 | err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize); |
| 874 | regs->stkadj = fsize; | ||
| 875 | } | ||
| 876 | 799 | ||
| 877 | err |= __put_user((current_thread_info()->exec_domain | 800 | err |= __put_user((current_thread_info()->exec_domain |
| 878 | && current_thread_info()->exec_domain->signal_invmap | 801 | && current_thread_info()->exec_domain->signal_invmap |
| @@ -914,11 +837,21 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 914 | 837 | ||
| 915 | push_cache ((unsigned long) &frame->retcode); | 838 | push_cache ((unsigned long) &frame->retcode); |
| 916 | 839 | ||
| 917 | /* Set up registers for signal handler */ | 840 | /* |
| 841 | * Set up registers for signal handler. All the state we are about | ||
| 842 | * to destroy is successfully copied to sigframe. | ||
| 843 | */ | ||
| 918 | wrusp ((unsigned long) frame); | 844 | wrusp ((unsigned long) frame); |
| 919 | regs->pc = (unsigned long) ka->sa.sa_handler; | 845 | regs->pc = (unsigned long) ka->sa.sa_handler; |
| 920 | 846 | ||
| 921 | adjust_stack: | 847 | /* |
| 848 | * This is subtle; if we build more than one sigframe, all but the | ||
| 849 | * first one will see frame format 0 and have fsize == 0, so we won't | ||
| 850 | * screw stkadj. | ||
| 851 | */ | ||
| 852 | if (fsize) | ||
| 853 | regs->stkadj = fsize; | ||
| 854 | |||
| 922 | /* Prepare to skip over the extra stuff in the exception frame. */ | 855 | /* Prepare to skip over the extra stuff in the exception frame. */ |
| 923 | if (regs->stkadj) { | 856 | if (regs->stkadj) { |
| 924 | struct pt_regs *tregs = | 857 | struct pt_regs *tregs = |
| @@ -933,11 +866,11 @@ adjust_stack: | |||
| 933 | tregs->pc = regs->pc; | 866 | tregs->pc = regs->pc; |
| 934 | tregs->sr = regs->sr; | 867 | tregs->sr = regs->sr; |
| 935 | } | 868 | } |
| 936 | return; | 869 | return 0; |
| 937 | 870 | ||
| 938 | give_sigsegv: | 871 | give_sigsegv: |
| 939 | force_sigsegv(sig, current); | 872 | force_sigsegv(sig, current); |
| 940 | goto adjust_stack; | 873 | return err; |
| 941 | } | 874 | } |
| 942 | 875 | ||
| 943 | static inline void | 876 | static inline void |
| @@ -995,6 +928,7 @@ static void | |||
| 995 | handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, | 928 | handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, |
| 996 | sigset_t *oldset, struct pt_regs *regs) | 929 | sigset_t *oldset, struct pt_regs *regs) |
| 997 | { | 930 | { |
| 931 | int err; | ||
| 998 | /* are we from a system call? */ | 932 | /* are we from a system call? */ |
| 999 | if (regs->orig_d0 >= 0) | 933 | if (regs->orig_d0 >= 0) |
| 1000 | /* If so, check system call restarting.. */ | 934 | /* If so, check system call restarting.. */ |
| @@ -1002,17 +936,24 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 1002 | 936 | ||
| 1003 | /* set up the stack frame */ | 937 | /* set up the stack frame */ |
| 1004 | if (ka->sa.sa_flags & SA_SIGINFO) | 938 | if (ka->sa.sa_flags & SA_SIGINFO) |
| 1005 | setup_rt_frame(sig, ka, info, oldset, regs); | 939 | err = setup_rt_frame(sig, ka, info, oldset, regs); |
| 1006 | else | 940 | else |
| 1007 | setup_frame(sig, ka, oldset, regs); | 941 | err = setup_frame(sig, ka, oldset, regs); |
| 1008 | 942 | ||
| 1009 | if (ka->sa.sa_flags & SA_ONESHOT) | 943 | if (err) |
| 1010 | ka->sa.sa_handler = SIG_DFL; | 944 | return; |
| 1011 | 945 | ||
| 1012 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | 946 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); |
| 1013 | if (!(ka->sa.sa_flags & SA_NODEFER)) | 947 | if (!(ka->sa.sa_flags & SA_NODEFER)) |
| 1014 | sigaddset(¤t->blocked,sig); | 948 | sigaddset(¤t->blocked,sig); |
| 1015 | recalc_sigpending(); | 949 | recalc_sigpending(); |
| 950 | |||
| 951 | if (test_thread_flag(TIF_DELAYED_TRACE)) { | ||
| 952 | regs->sr &= ~0x8000; | ||
| 953 | send_sig(SIGTRAP, current, 1); | ||
| 954 | } | ||
| 955 | |||
| 956 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
| 1016 | } | 957 | } |
| 1017 | 958 | ||
| 1018 | /* | 959 | /* |
| @@ -1020,22 +961,25 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 1020 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | 961 | * want to handle. Thus you cannot kill init even with a SIGKILL even by |
| 1021 | * mistake. | 962 | * mistake. |
| 1022 | */ | 963 | */ |
| 1023 | asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) | 964 | asmlinkage void do_signal(struct pt_regs *regs) |
| 1024 | { | 965 | { |
| 1025 | siginfo_t info; | 966 | siginfo_t info; |
| 1026 | struct k_sigaction ka; | 967 | struct k_sigaction ka; |
| 1027 | int signr; | 968 | int signr; |
| 969 | sigset_t *oldset; | ||
| 1028 | 970 | ||
| 1029 | current->thread.esp0 = (unsigned long) regs; | 971 | current->thread.esp0 = (unsigned long) regs; |
| 1030 | 972 | ||
| 1031 | if (!oldset) | 973 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
| 974 | oldset = ¤t->saved_sigmask; | ||
| 975 | else | ||
| 1032 | oldset = ¤t->blocked; | 976 | oldset = ¤t->blocked; |
| 1033 | 977 | ||
| 1034 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 978 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
| 1035 | if (signr > 0) { | 979 | if (signr > 0) { |
| 1036 | /* Whee! Actually deliver the signal. */ | 980 | /* Whee! Actually deliver the signal. */ |
| 1037 | handle_signal(signr, &ka, &info, oldset, regs); | 981 | handle_signal(signr, &ka, &info, oldset, regs); |
| 1038 | return 1; | 982 | return; |
| 1039 | } | 983 | } |
| 1040 | 984 | ||
| 1041 | /* Did we come from a system call? */ | 985 | /* Did we come from a system call? */ |
| @@ -1043,5 +987,9 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) | |||
| 1043 | /* Restart the system call - no handlers present */ | 987 | /* Restart the system call - no handlers present */ |
| 1044 | handle_restart(regs, NULL, 0); | 988 | handle_restart(regs, NULL, 0); |
| 1045 | 989 | ||
| 1046 | return 0; | 990 | /* If there's no signal to deliver, we just restore the saved mask. */ |
| 991 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
| 992 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
| 993 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
| 994 | } | ||
| 1047 | } | 995 | } |
diff --git a/arch/m68knommu/kernel/entry.S b/arch/m68knommu/kernel/entry.S index aff6f57ef8b5..2783f25e38bd 100644 --- a/arch/m68knommu/kernel/entry.S +++ b/arch/m68knommu/kernel/entry.S | |||
| @@ -112,22 +112,6 @@ ENTRY(sys_clone) | |||
| 112 | RESTORE_SWITCH_STACK | 112 | RESTORE_SWITCH_STACK |
| 113 | rts | 113 | rts |
| 114 | 114 | ||
| 115 | ENTRY(sys_sigsuspend) | ||
| 116 | SAVE_SWITCH_STACK | ||
| 117 | pea %sp@(SWITCH_STACK_SIZE) | ||
| 118 | jbsr do_sigsuspend | ||
| 119 | addql #4,%sp | ||
| 120 | RESTORE_SWITCH_STACK | ||
| 121 | rts | ||
| 122 | |||
| 123 | ENTRY(sys_rt_sigsuspend) | ||
| 124 | SAVE_SWITCH_STACK | ||
| 125 | pea %sp@(SWITCH_STACK_SIZE) | ||
| 126 | jbsr do_rt_sigsuspend | ||
| 127 | addql #4,%sp | ||
| 128 | RESTORE_SWITCH_STACK | ||
| 129 | rts | ||
| 130 | |||
| 131 | ENTRY(sys_sigreturn) | 115 | ENTRY(sys_sigreturn) |
| 132 | SAVE_SWITCH_STACK | 116 | SAVE_SWITCH_STACK |
| 133 | jbsr do_sigreturn | 117 | jbsr do_sigreturn |
diff --git a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c index 5ab6a04af14e..36a81bb6835a 100644 --- a/arch/m68knommu/kernel/signal.c +++ b/arch/m68knommu/kernel/signal.c | |||
| @@ -53,65 +53,30 @@ | |||
| 53 | 53 | ||
| 54 | void ret_from_user_signal(void); | 54 | void ret_from_user_signal(void); |
| 55 | void ret_from_user_rt_signal(void); | 55 | void ret_from_user_rt_signal(void); |
| 56 | asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); | ||
| 57 | 56 | ||
| 58 | /* | 57 | /* |
| 59 | * Atomically swap in the new signal mask, and wait for a signal. | 58 | * Atomically swap in the new signal mask, and wait for a signal. |
| 60 | */ | 59 | */ |
| 61 | asmlinkage int do_sigsuspend(struct pt_regs *regs) | 60 | asmlinkage int |
| 61 | sys_sigsuspend(int unused0, int unused1, old_sigset_t mask) | ||
| 62 | { | 62 | { |
| 63 | old_sigset_t mask = regs->d3; | ||
| 64 | sigset_t saveset; | ||
| 65 | |||
| 66 | mask &= _BLOCKABLE; | 63 | mask &= _BLOCKABLE; |
| 67 | spin_lock_irq(¤t->sighand->siglock); | 64 | spin_lock_irq(¤t->sighand->siglock); |
| 68 | saveset = current->blocked; | 65 | current->saved_sigmask = current->blocked; |
| 69 | siginitset(¤t->blocked, mask); | 66 | siginitset(¤t->blocked, mask); |
| 70 | recalc_sigpending(); | 67 | recalc_sigpending(); |
| 71 | spin_unlock_irq(¤t->sighand->siglock); | 68 | spin_unlock_irq(¤t->sighand->siglock); |
| 72 | 69 | ||
| 73 | regs->d0 = -EINTR; | 70 | current->state = TASK_INTERRUPTIBLE; |
| 74 | while (1) { | 71 | schedule(); |
| 75 | current->state = TASK_INTERRUPTIBLE; | 72 | set_restore_sigmask(); |
| 76 | schedule(); | ||
| 77 | if (do_signal(&saveset, regs)) | ||
| 78 | return -EINTR; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | asmlinkage int | ||
| 83 | do_rt_sigsuspend(struct pt_regs *regs) | ||
| 84 | { | ||
| 85 | sigset_t *unewset = (sigset_t *)regs->d1; | ||
| 86 | size_t sigsetsize = (size_t)regs->d2; | ||
| 87 | sigset_t saveset, newset; | ||
| 88 | |||
| 89 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
| 90 | if (sigsetsize != sizeof(sigset_t)) | ||
| 91 | return -EINVAL; | ||
| 92 | 73 | ||
| 93 | if (copy_from_user(&newset, unewset, sizeof(newset))) | 74 | return -ERESTARTNOHAND; |
| 94 | return -EFAULT; | ||
| 95 | sigdelsetmask(&newset, ~_BLOCKABLE); | ||
| 96 | |||
| 97 | spin_lock_irq(¤t->sighand->siglock); | ||
| 98 | saveset = current->blocked; | ||
| 99 | current->blocked = newset; | ||
| 100 | recalc_sigpending(); | ||
| 101 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 102 | |||
| 103 | regs->d0 = -EINTR; | ||
| 104 | while (1) { | ||
| 105 | current->state = TASK_INTERRUPTIBLE; | ||
| 106 | schedule(); | ||
| 107 | if (do_signal(&saveset, regs)) | ||
| 108 | return -EINTR; | ||
| 109 | } | ||
| 110 | } | 75 | } |
| 111 | 76 | ||
| 112 | asmlinkage int | 77 | asmlinkage int |
| 113 | sys_sigaction(int sig, const struct old_sigaction *act, | 78 | sys_sigaction(int sig, const struct old_sigaction __user *act, |
| 114 | struct old_sigaction *oact) | 79 | struct old_sigaction __user *oact) |
| 115 | { | 80 | { |
| 116 | struct k_sigaction new_ka, old_ka; | 81 | struct k_sigaction new_ka, old_ka; |
| 117 | int ret; | 82 | int ret; |
| @@ -120,10 +85,10 @@ sys_sigaction(int sig, const struct old_sigaction *act, | |||
| 120 | old_sigset_t mask; | 85 | old_sigset_t mask; |
| 121 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || | 86 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || |
| 122 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || | 87 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || |
| 123 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) | 88 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) || |
| 89 | __get_user(new_ka.sa.sa_flags, &act->sa_flags) || | ||
| 90 | __get_user(mask, &act->sa_mask)) | ||
| 124 | return -EFAULT; | 91 | return -EFAULT; |
| 125 | __get_user(new_ka.sa.sa_flags, &act->sa_flags); | ||
| 126 | __get_user(mask, &act->sa_mask); | ||
| 127 | siginitset(&new_ka.sa.sa_mask, mask); | 92 | siginitset(&new_ka.sa.sa_mask, mask); |
| 128 | } | 93 | } |
| 129 | 94 | ||
| @@ -132,17 +97,17 @@ sys_sigaction(int sig, const struct old_sigaction *act, | |||
| 132 | if (!ret && oact) { | 97 | if (!ret && oact) { |
| 133 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || | 98 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || |
| 134 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || | 99 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || |
| 135 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) | 100 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) || |
| 101 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || | ||
| 102 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) | ||
| 136 | return -EFAULT; | 103 | return -EFAULT; |
| 137 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags); | ||
| 138 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); | ||
| 139 | } | 104 | } |
| 140 | 105 | ||
| 141 | return ret; | 106 | return ret; |
| 142 | } | 107 | } |
| 143 | 108 | ||
| 144 | asmlinkage int | 109 | asmlinkage int |
| 145 | sys_sigaltstack(const stack_t *uss, stack_t *uoss) | 110 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) |
| 146 | { | 111 | { |
| 147 | return do_sigaltstack(uss, uoss, rdusp()); | 112 | return do_sigaltstack(uss, uoss, rdusp()); |
| 148 | } | 113 | } |
| @@ -157,10 +122,10 @@ sys_sigaltstack(const stack_t *uss, stack_t *uoss) | |||
| 157 | 122 | ||
| 158 | struct sigframe | 123 | struct sigframe |
| 159 | { | 124 | { |
| 160 | char *pretcode; | 125 | char __user *pretcode; |
| 161 | int sig; | 126 | int sig; |
| 162 | int code; | 127 | int code; |
| 163 | struct sigcontext *psc; | 128 | struct sigcontext __user *psc; |
| 164 | char retcode[8]; | 129 | char retcode[8]; |
| 165 | unsigned long extramask[_NSIG_WORDS-1]; | 130 | unsigned long extramask[_NSIG_WORDS-1]; |
| 166 | struct sigcontext sc; | 131 | struct sigcontext sc; |
| @@ -168,10 +133,10 @@ struct sigframe | |||
| 168 | 133 | ||
| 169 | struct rt_sigframe | 134 | struct rt_sigframe |
| 170 | { | 135 | { |
| 171 | char *pretcode; | 136 | char __user *pretcode; |
| 172 | int sig; | 137 | int sig; |
| 173 | struct siginfo *pinfo; | 138 | struct siginfo __user *pinfo; |
| 174 | void *puc; | 139 | void __user *puc; |
| 175 | char retcode[8]; | 140 | char retcode[8]; |
| 176 | struct siginfo info; | 141 | struct siginfo info; |
| 177 | struct ucontext uc; | 142 | struct ucontext uc; |
| @@ -198,8 +163,8 @@ static inline int restore_fpu_state(struct sigcontext *sc) | |||
| 198 | goto out; | 163 | goto out; |
| 199 | 164 | ||
| 200 | __asm__ volatile (".chip 68k/68881\n\t" | 165 | __asm__ volatile (".chip 68k/68881\n\t" |
| 201 | "fmovemx %0,%/fp0-%/fp1\n\t" | 166 | "fmovemx %0,%%fp0-%%fp1\n\t" |
| 202 | "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t" | 167 | "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t" |
| 203 | ".chip 68k" | 168 | ".chip 68k" |
| 204 | : /* no outputs */ | 169 | : /* no outputs */ |
| 205 | : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl)); | 170 | : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl)); |
| @@ -218,7 +183,7 @@ out: | |||
| 218 | #define uc_formatvec uc_filler[FPCONTEXT_SIZE/4] | 183 | #define uc_formatvec uc_filler[FPCONTEXT_SIZE/4] |
| 219 | #define uc_extra uc_filler[FPCONTEXT_SIZE/4+1] | 184 | #define uc_extra uc_filler[FPCONTEXT_SIZE/4+1] |
| 220 | 185 | ||
| 221 | static inline int rt_restore_fpu_state(struct ucontext *uc) | 186 | static inline int rt_restore_fpu_state(struct ucontext __user *uc) |
| 222 | { | 187 | { |
| 223 | unsigned char fpstate[FPCONTEXT_SIZE]; | 188 | unsigned char fpstate[FPCONTEXT_SIZE]; |
| 224 | int context_size = 0; | 189 | int context_size = 0; |
| @@ -228,7 +193,7 @@ static inline int rt_restore_fpu_state(struct ucontext *uc) | |||
| 228 | if (FPU_IS_EMU) { | 193 | if (FPU_IS_EMU) { |
| 229 | /* restore fpu control register */ | 194 | /* restore fpu control register */ |
| 230 | if (__copy_from_user(current->thread.fpcntl, | 195 | if (__copy_from_user(current->thread.fpcntl, |
| 231 | &uc->uc_mcontext.fpregs.f_pcr, 12)) | 196 | uc->uc_mcontext.fpregs.f_fpcntl, 12)) |
| 232 | goto out; | 197 | goto out; |
| 233 | /* restore all other fpu register */ | 198 | /* restore all other fpu register */ |
| 234 | if (__copy_from_user(current->thread.fp, | 199 | if (__copy_from_user(current->thread.fp, |
| @@ -237,7 +202,7 @@ static inline int rt_restore_fpu_state(struct ucontext *uc) | |||
| 237 | return 0; | 202 | return 0; |
| 238 | } | 203 | } |
| 239 | 204 | ||
| 240 | if (__get_user(*(long *)fpstate, (long *)&uc->uc_fpstate)) | 205 | if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate)) |
| 241 | goto out; | 206 | goto out; |
| 242 | if (fpstate[0]) { | 207 | if (fpstate[0]) { |
| 243 | context_size = fpstate[1]; | 208 | context_size = fpstate[1]; |
| @@ -249,15 +214,15 @@ static inline int rt_restore_fpu_state(struct ucontext *uc) | |||
| 249 | sizeof(fpregs))) | 214 | sizeof(fpregs))) |
| 250 | goto out; | 215 | goto out; |
| 251 | __asm__ volatile (".chip 68k/68881\n\t" | 216 | __asm__ volatile (".chip 68k/68881\n\t" |
| 252 | "fmovemx %0,%/fp0-%/fp7\n\t" | 217 | "fmovemx %0,%%fp0-%%fp7\n\t" |
| 253 | "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t" | 218 | "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t" |
| 254 | ".chip 68k" | 219 | ".chip 68k" |
| 255 | : /* no outputs */ | 220 | : /* no outputs */ |
| 256 | : "m" (*fpregs.f_fpregs), | 221 | : "m" (*fpregs.f_fpregs), |
| 257 | "m" (fpregs.f_pcr)); | 222 | "m" (*fpregs.f_fpcntl)); |
| 258 | } | 223 | } |
| 259 | if (context_size && | 224 | if (context_size && |
| 260 | __copy_from_user(fpstate + 4, (long *)&uc->uc_fpstate + 1, | 225 | __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1, |
| 261 | context_size)) | 226 | context_size)) |
| 262 | goto out; | 227 | goto out; |
| 263 | __asm__ volatile (".chip 68k/68881\n\t" | 228 | __asm__ volatile (".chip 68k/68881\n\t" |
| @@ -272,7 +237,7 @@ out: | |||
| 272 | #endif | 237 | #endif |
| 273 | 238 | ||
| 274 | static inline int | 239 | static inline int |
| 275 | restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp, | 240 | restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp, |
| 276 | int *pd0) | 241 | int *pd0) |
| 277 | { | 242 | { |
| 278 | int formatvec; | 243 | int formatvec; |
| @@ -312,10 +277,10 @@ badframe: | |||
| 312 | 277 | ||
| 313 | static inline int | 278 | static inline int |
| 314 | rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw, | 279 | rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw, |
| 315 | struct ucontext *uc, int *pd0) | 280 | struct ucontext __user *uc, int *pd0) |
| 316 | { | 281 | { |
| 317 | int temp; | 282 | int temp; |
| 318 | greg_t *gregs = uc->uc_mcontext.gregs; | 283 | greg_t __user *gregs = uc->uc_mcontext.gregs; |
| 319 | unsigned long usp; | 284 | unsigned long usp; |
| 320 | int err; | 285 | int err; |
| 321 | 286 | ||
| @@ -365,7 +330,7 @@ asmlinkage int do_sigreturn(unsigned long __unused) | |||
| 365 | struct switch_stack *sw = (struct switch_stack *) &__unused; | 330 | struct switch_stack *sw = (struct switch_stack *) &__unused; |
| 366 | struct pt_regs *regs = (struct pt_regs *) (sw + 1); | 331 | struct pt_regs *regs = (struct pt_regs *) (sw + 1); |
| 367 | unsigned long usp = rdusp(); | 332 | unsigned long usp = rdusp(); |
| 368 | struct sigframe *frame = (struct sigframe *)(usp - 4); | 333 | struct sigframe __user *frame = (struct sigframe __user *)(usp - 4); |
| 369 | sigset_t set; | 334 | sigset_t set; |
| 370 | int d0; | 335 | int d0; |
| 371 | 336 | ||
| @@ -397,7 +362,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused) | |||
| 397 | struct switch_stack *sw = (struct switch_stack *) &__unused; | 362 | struct switch_stack *sw = (struct switch_stack *) &__unused; |
| 398 | struct pt_regs *regs = (struct pt_regs *) (sw + 1); | 363 | struct pt_regs *regs = (struct pt_regs *) (sw + 1); |
| 399 | unsigned long usp = rdusp(); | 364 | unsigned long usp = rdusp(); |
| 400 | struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4); | 365 | struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4); |
| 401 | sigset_t set; | 366 | sigset_t set; |
| 402 | int d0; | 367 | int d0; |
| 403 | 368 | ||
| @@ -443,17 +408,17 @@ static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs) | |||
| 443 | if (sc->sc_fpstate[0]) { | 408 | if (sc->sc_fpstate[0]) { |
| 444 | fpu_version = sc->sc_fpstate[0]; | 409 | fpu_version = sc->sc_fpstate[0]; |
| 445 | __asm__ volatile (".chip 68k/68881\n\t" | 410 | __asm__ volatile (".chip 68k/68881\n\t" |
| 446 | "fmovemx %/fp0-%/fp1,%0\n\t" | 411 | "fmovemx %%fp0-%%fp1,%0\n\t" |
| 447 | "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t" | 412 | "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t" |
| 448 | ".chip 68k" | 413 | ".chip 68k" |
| 449 | : /* no outputs */ | 414 | : "=m" (*sc->sc_fpregs), |
| 450 | : "m" (*sc->sc_fpregs), | 415 | "=m" (*sc->sc_fpcntl) |
| 451 | "m" (*sc->sc_fpcntl) | 416 | : /* no inputs */ |
| 452 | : "memory"); | 417 | : "memory"); |
| 453 | } | 418 | } |
| 454 | } | 419 | } |
| 455 | 420 | ||
| 456 | static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs) | 421 | static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs) |
| 457 | { | 422 | { |
| 458 | unsigned char fpstate[FPCONTEXT_SIZE]; | 423 | unsigned char fpstate[FPCONTEXT_SIZE]; |
| 459 | int context_size = 0; | 424 | int context_size = 0; |
| @@ -461,7 +426,7 @@ static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs) | |||
| 461 | 426 | ||
| 462 | if (FPU_IS_EMU) { | 427 | if (FPU_IS_EMU) { |
| 463 | /* save fpu control register */ | 428 | /* save fpu control register */ |
| 464 | err |= copy_to_user(&uc->uc_mcontext.fpregs.f_pcr, | 429 | err |= copy_to_user(uc->uc_mcontext.fpregs.f_pcntl, |
| 465 | current->thread.fpcntl, 12); | 430 | current->thread.fpcntl, 12); |
| 466 | /* save all other fpu register */ | 431 | /* save all other fpu register */ |
| 467 | err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs, | 432 | err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs, |
| @@ -474,24 +439,24 @@ static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs) | |||
| 474 | ".chip 68k" | 439 | ".chip 68k" |
| 475 | : : "m" (*fpstate) : "memory"); | 440 | : : "m" (*fpstate) : "memory"); |
| 476 | 441 | ||
| 477 | err |= __put_user(*(long *)fpstate, (long *)&uc->uc_fpstate); | 442 | err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate); |
| 478 | if (fpstate[0]) { | 443 | if (fpstate[0]) { |
| 479 | fpregset_t fpregs; | 444 | fpregset_t fpregs; |
| 480 | context_size = fpstate[1]; | 445 | context_size = fpstate[1]; |
| 481 | fpu_version = fpstate[0]; | 446 | fpu_version = fpstate[0]; |
| 482 | __asm__ volatile (".chip 68k/68881\n\t" | 447 | __asm__ volatile (".chip 68k/68881\n\t" |
| 483 | "fmovemx %/fp0-%/fp7,%0\n\t" | 448 | "fmovemx %%fp0-%%fp7,%0\n\t" |
| 484 | "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t" | 449 | "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t" |
| 485 | ".chip 68k" | 450 | ".chip 68k" |
| 486 | : /* no outputs */ | 451 | : "=m" (*fpregs.f_fpregs), |
| 487 | : "m" (*fpregs.f_fpregs), | 452 | "=m" (*fpregs.f_fpcntl) |
| 488 | "m" (fpregs.f_pcr) | 453 | : /* no inputs */ |
| 489 | : "memory"); | 454 | : "memory"); |
| 490 | err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs, | 455 | err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs, |
| 491 | sizeof(fpregs)); | 456 | sizeof(fpregs)); |
| 492 | } | 457 | } |
| 493 | if (context_size) | 458 | if (context_size) |
| 494 | err |= copy_to_user((long *)&uc->uc_fpstate + 1, fpstate + 4, | 459 | err |= copy_to_user((long __user *)&uc->uc_fpstate + 1, fpstate + 4, |
| 495 | context_size); | 460 | context_size); |
| 496 | return err; | 461 | return err; |
| 497 | } | 462 | } |
| @@ -516,10 +481,10 @@ static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, | |||
| 516 | #endif | 481 | #endif |
| 517 | } | 482 | } |
| 518 | 483 | ||
| 519 | static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs) | 484 | static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs) |
| 520 | { | 485 | { |
| 521 | struct switch_stack *sw = (struct switch_stack *)regs - 1; | 486 | struct switch_stack *sw = (struct switch_stack *)regs - 1; |
| 522 | greg_t *gregs = uc->uc_mcontext.gregs; | 487 | greg_t __user *gregs = uc->uc_mcontext.gregs; |
| 523 | int err = 0; | 488 | int err = 0; |
| 524 | 489 | ||
| 525 | err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version); | 490 | err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version); |
| @@ -547,7 +512,7 @@ static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs) | |||
| 547 | return err; | 512 | return err; |
| 548 | } | 513 | } |
| 549 | 514 | ||
| 550 | static inline void * | 515 | static inline void __user * |
| 551 | get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) | 516 | get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) |
| 552 | { | 517 | { |
| 553 | unsigned long usp; | 518 | unsigned long usp; |
| @@ -560,13 +525,13 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) | |||
| 560 | if (!sas_ss_flags(usp)) | 525 | if (!sas_ss_flags(usp)) |
| 561 | usp = current->sas_ss_sp + current->sas_ss_size; | 526 | usp = current->sas_ss_sp + current->sas_ss_size; |
| 562 | } | 527 | } |
| 563 | return (void *)((usp - frame_size) & -8UL); | 528 | return (void __user *)((usp - frame_size) & -8UL); |
| 564 | } | 529 | } |
| 565 | 530 | ||
| 566 | static void setup_frame (int sig, struct k_sigaction *ka, | 531 | static int setup_frame (int sig, struct k_sigaction *ka, |
| 567 | sigset_t *set, struct pt_regs *regs) | 532 | sigset_t *set, struct pt_regs *regs) |
| 568 | { | 533 | { |
| 569 | struct sigframe *frame; | 534 | struct sigframe __user *frame; |
| 570 | struct sigcontext context; | 535 | struct sigcontext context; |
| 571 | int err = 0; | 536 | int err = 0; |
| 572 | 537 | ||
| @@ -617,17 +582,17 @@ adjust_stack: | |||
| 617 | tregs->pc = regs->pc; | 582 | tregs->pc = regs->pc; |
| 618 | tregs->sr = regs->sr; | 583 | tregs->sr = regs->sr; |
| 619 | } | 584 | } |
| 620 | return; | 585 | return err; |
| 621 | 586 | ||
| 622 | give_sigsegv: | 587 | give_sigsegv: |
| 623 | force_sigsegv(sig, current); | 588 | force_sigsegv(sig, current); |
| 624 | goto adjust_stack; | 589 | goto adjust_stack; |
| 625 | } | 590 | } |
| 626 | 591 | ||
| 627 | static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, | 592 | static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, |
| 628 | sigset_t *set, struct pt_regs *regs) | 593 | sigset_t *set, struct pt_regs *regs) |
| 629 | { | 594 | { |
| 630 | struct rt_sigframe *frame; | 595 | struct rt_sigframe __user *frame; |
| 631 | int err = 0; | 596 | int err = 0; |
| 632 | 597 | ||
| 633 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 598 | frame = get_sigframe(ka, regs, sizeof(*frame)); |
| @@ -644,8 +609,8 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 644 | 609 | ||
| 645 | /* Create the ucontext. */ | 610 | /* Create the ucontext. */ |
| 646 | err |= __put_user(0, &frame->uc.uc_flags); | 611 | err |= __put_user(0, &frame->uc.uc_flags); |
| 647 | err |= __put_user(0, &frame->uc.uc_link); | 612 | err |= __put_user(NULL, &frame->uc.uc_link); |
| 648 | err |= __put_user((void *)current->sas_ss_sp, | 613 | err |= __put_user((void __user *)current->sas_ss_sp, |
| 649 | &frame->uc.uc_stack.ss_sp); | 614 | &frame->uc.uc_stack.ss_sp); |
| 650 | err |= __put_user(sas_ss_flags(rdusp()), | 615 | err |= __put_user(sas_ss_flags(rdusp()), |
| 651 | &frame->uc.uc_stack.ss_flags); | 616 | &frame->uc.uc_stack.ss_flags); |
| @@ -681,7 +646,7 @@ adjust_stack: | |||
| 681 | tregs->pc = regs->pc; | 646 | tregs->pc = regs->pc; |
| 682 | tregs->sr = regs->sr; | 647 | tregs->sr = regs->sr; |
| 683 | } | 648 | } |
| 684 | return; | 649 | return err; |
| 685 | 650 | ||
| 686 | give_sigsegv: | 651 | give_sigsegv: |
| 687 | force_sigsegv(sig, current); | 652 | force_sigsegv(sig, current); |
| @@ -728,6 +693,7 @@ static void | |||
| 728 | handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, | 693 | handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, |
| 729 | sigset_t *oldset, struct pt_regs *regs) | 694 | sigset_t *oldset, struct pt_regs *regs) |
| 730 | { | 695 | { |
| 696 | int err; | ||
| 731 | /* are we from a system call? */ | 697 | /* are we from a system call? */ |
| 732 | if (regs->orig_d0 >= 0) | 698 | if (regs->orig_d0 >= 0) |
| 733 | /* If so, check system call restarting.. */ | 699 | /* If so, check system call restarting.. */ |
| @@ -735,12 +701,12 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 735 | 701 | ||
| 736 | /* set up the stack frame */ | 702 | /* set up the stack frame */ |
| 737 | if (ka->sa.sa_flags & SA_SIGINFO) | 703 | if (ka->sa.sa_flags & SA_SIGINFO) |
| 738 | setup_rt_frame(sig, ka, info, oldset, regs); | 704 | err = setup_rt_frame(sig, ka, info, oldset, regs); |
| 739 | else | 705 | else |
| 740 | setup_frame(sig, ka, oldset, regs); | 706 | err = setup_frame(sig, ka, oldset, regs); |
| 741 | 707 | ||
| 742 | if (ka->sa.sa_flags & SA_ONESHOT) | 708 | if (err) |
| 743 | ka->sa.sa_handler = SIG_DFL; | 709 | return; |
| 744 | 710 | ||
| 745 | spin_lock_irq(¤t->sighand->siglock); | 711 | spin_lock_irq(¤t->sighand->siglock); |
| 746 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | 712 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); |
| @@ -748,6 +714,8 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 748 | sigaddset(¤t->blocked,sig); | 714 | sigaddset(¤t->blocked,sig); |
| 749 | recalc_sigpending(); | 715 | recalc_sigpending(); |
| 750 | spin_unlock_irq(¤t->sighand->siglock); | 716 | spin_unlock_irq(¤t->sighand->siglock); |
| 717 | |||
| 718 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
| 751 | } | 719 | } |
| 752 | 720 | ||
| 753 | /* | 721 | /* |
| @@ -755,11 +723,12 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 755 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | 723 | * want to handle. Thus you cannot kill init even with a SIGKILL even by |
| 756 | * mistake. | 724 | * mistake. |
| 757 | */ | 725 | */ |
| 758 | asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) | 726 | asmlinkage void do_signal(struct pt_regs *regs) |
| 759 | { | 727 | { |
| 760 | struct k_sigaction ka; | 728 | struct k_sigaction ka; |
| 761 | siginfo_t info; | 729 | siginfo_t info; |
| 762 | int signr; | 730 | int signr; |
| 731 | sigset_t *oldset; | ||
| 763 | 732 | ||
| 764 | /* | 733 | /* |
| 765 | * We want the common case to go fast, which | 734 | * We want the common case to go fast, which |
| @@ -768,16 +737,18 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) | |||
| 768 | * if so. | 737 | * if so. |
| 769 | */ | 738 | */ |
| 770 | if (!user_mode(regs)) | 739 | if (!user_mode(regs)) |
| 771 | return 1; | 740 | return; |
| 772 | 741 | ||
| 773 | if (!oldset) | 742 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
| 743 | oldset = ¤t->saved_sigmask; | ||
| 744 | else | ||
| 774 | oldset = ¤t->blocked; | 745 | oldset = ¤t->blocked; |
| 775 | 746 | ||
| 776 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 747 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
| 777 | if (signr > 0) { | 748 | if (signr > 0) { |
| 778 | /* Whee! Actually deliver the signal. */ | 749 | /* Whee! Actually deliver the signal. */ |
| 779 | handle_signal(signr, &ka, &info, oldset, regs); | 750 | handle_signal(signr, &ka, &info, oldset, regs); |
| 780 | return 1; | 751 | return; |
| 781 | } | 752 | } |
| 782 | 753 | ||
| 783 | /* Did we come from a system call? */ | 754 | /* Did we come from a system call? */ |
| @@ -785,5 +756,10 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) | |||
| 785 | /* Restart the system call - no handlers present */ | 756 | /* Restart the system call - no handlers present */ |
| 786 | handle_restart(regs, NULL, 0); | 757 | handle_restart(regs, NULL, 0); |
| 787 | } | 758 | } |
| 788 | return 0; | 759 | |
| 760 | /* If there's no signal to deliver, we just restore the saved mask. */ | ||
| 761 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
| 762 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
| 763 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
| 764 | } | ||
| 789 | } | 765 | } |
diff --git a/arch/m68knommu/platform/68328/entry.S b/arch/m68knommu/platform/68328/entry.S index 27241e16a526..240a7a6e25c8 100644 --- a/arch/m68knommu/platform/68328/entry.S +++ b/arch/m68knommu/platform/68328/entry.S | |||
| @@ -106,6 +106,7 @@ Luser_return: | |||
| 106 | movel %sp,%d1 /* get thread_info pointer */ | 106 | movel %sp,%d1 /* get thread_info pointer */ |
| 107 | andl #-THREAD_SIZE,%d1 | 107 | andl #-THREAD_SIZE,%d1 |
| 108 | movel %d1,%a2 | 108 | movel %d1,%a2 |
| 109 | 1: | ||
| 109 | move %a2@(TI_FLAGS),%d1 /* thread_info->flags */ | 110 | move %a2@(TI_FLAGS),%d1 /* thread_info->flags */ |
| 110 | andl #_TIF_WORK_MASK,%d1 | 111 | andl #_TIF_WORK_MASK,%d1 |
| 111 | jne Lwork_to_do | 112 | jne Lwork_to_do |
| @@ -120,13 +121,11 @@ Lsignal_return: | |||
| 120 | subql #4,%sp /* dummy return address*/ | 121 | subql #4,%sp /* dummy return address*/ |
| 121 | SAVE_SWITCH_STACK | 122 | SAVE_SWITCH_STACK |
| 122 | pea %sp@(SWITCH_STACK_SIZE) | 123 | pea %sp@(SWITCH_STACK_SIZE) |
| 123 | clrl %sp@- | ||
| 124 | bsrw do_signal | 124 | bsrw do_signal |
| 125 | addql #8,%sp | 125 | addql #4,%sp |
| 126 | RESTORE_SWITCH_STACK | 126 | RESTORE_SWITCH_STACK |
| 127 | addql #4,%sp | 127 | addql #4,%sp |
| 128 | Lreturn: | 128 | jra 1b |
| 129 | RESTORE_ALL | ||
| 130 | 129 | ||
| 131 | /* | 130 | /* |
| 132 | * This is the main interrupt handler, responsible for calling process_int() | 131 | * This is the main interrupt handler, responsible for calling process_int() |
diff --git a/arch/m68knommu/platform/68360/entry.S b/arch/m68knommu/platform/68360/entry.S index c131c6e1d92d..8a28788c0eea 100644 --- a/arch/m68knommu/platform/68360/entry.S +++ b/arch/m68knommu/platform/68360/entry.S | |||
| @@ -102,6 +102,7 @@ Luser_return: | |||
| 102 | movel %sp,%d1 /* get thread_info pointer */ | 102 | movel %sp,%d1 /* get thread_info pointer */ |
| 103 | andl #-THREAD_SIZE,%d1 | 103 | andl #-THREAD_SIZE,%d1 |
| 104 | movel %d1,%a2 | 104 | movel %d1,%a2 |
| 105 | 1: | ||
| 105 | move %a2@(TI_FLAGS),%d1 /* thread_info->flags */ | 106 | move %a2@(TI_FLAGS),%d1 /* thread_info->flags */ |
| 106 | andl #_TIF_WORK_MASK,%d1 | 107 | andl #_TIF_WORK_MASK,%d1 |
| 107 | jne Lwork_to_do | 108 | jne Lwork_to_do |
| @@ -116,13 +117,11 @@ Lsignal_return: | |||
| 116 | subql #4,%sp /* dummy return address*/ | 117 | subql #4,%sp /* dummy return address*/ |
| 117 | SAVE_SWITCH_STACK | 118 | SAVE_SWITCH_STACK |
| 118 | pea %sp@(SWITCH_STACK_SIZE) | 119 | pea %sp@(SWITCH_STACK_SIZE) |
| 119 | clrl %sp@- | ||
| 120 | bsrw do_signal | 120 | bsrw do_signal |
| 121 | addql #8,%sp | 121 | addql #4,%sp |
| 122 | RESTORE_SWITCH_STACK | 122 | RESTORE_SWITCH_STACK |
| 123 | addql #4,%sp | 123 | addql #4,%sp |
| 124 | Lreturn: | 124 | jra 1b |
| 125 | RESTORE_ALL | ||
| 126 | 125 | ||
| 127 | /* | 126 | /* |
| 128 | * This is the main interrupt handler, responsible for calling do_IRQ() | 127 | * This is the main interrupt handler, responsible for calling do_IRQ() |
diff --git a/arch/m68knommu/platform/coldfire/entry.S b/arch/m68knommu/platform/coldfire/entry.S index 5e92bed94b7e..e1debc8285ef 100644 --- a/arch/m68knommu/platform/coldfire/entry.S +++ b/arch/m68knommu/platform/coldfire/entry.S | |||
| @@ -167,12 +167,11 @@ Lsignal_return: | |||
| 167 | subql #4,%sp /* dummy return address */ | 167 | subql #4,%sp /* dummy return address */ |
| 168 | SAVE_SWITCH_STACK | 168 | SAVE_SWITCH_STACK |
| 169 | pea %sp@(SWITCH_STACK_SIZE) | 169 | pea %sp@(SWITCH_STACK_SIZE) |
| 170 | clrl %sp@- | ||
| 171 | jsr do_signal | 170 | jsr do_signal |
| 172 | addql #8,%sp | 171 | addql #4,%sp |
| 173 | RESTORE_SWITCH_STACK | 172 | RESTORE_SWITCH_STACK |
| 174 | addql #4,%sp | 173 | addql #4,%sp |
| 175 | jmp Lreturn | 174 | jmp Luser_return |
| 176 | 175 | ||
| 177 | /* | 176 | /* |
| 178 | * This is the generic interrupt handler (for all hardware interrupt | 177 | * This is the generic interrupt handler (for all hardware interrupt |
