aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/kernel')
-rw-r--r--arch/sparc/kernel/entry.S2
-rw-r--r--arch/sparc/kernel/process.c25
-rw-r--r--arch/sparc/kernel/ptrace.c6
-rw-r--r--arch/sparc/kernel/rtrap.S11
-rw-r--r--arch/sparc/kernel/signal.c84
-rw-r--r--arch/sparc/kernel/sys_sparc.c51
6 files changed, 81 insertions, 98 deletions
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index 57d1bbdd0bd2..4bcfe54f878d 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -1306,6 +1306,8 @@ ret_from_fork:
1306 .align 4 1306 .align 4
1307 .globl linux_sparc_syscall 1307 .globl linux_sparc_syscall
1308linux_sparc_syscall: 1308linux_sparc_syscall:
1309 sethi %hi(PSR_SYSCALL), %l4
1310 or %l0, %l4, %l0
1309 /* Direct access to user regs, must faster. */ 1311 /* Direct access to user regs, must faster. */
1310 cmp %g1, NR_SYSCALLS 1312 cmp %g1, NR_SYSCALLS
1311 bgeu linux_sparc_ni_syscall 1313 bgeu linux_sparc_ni_syscall
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
index e7f35198ae34..da48d248cc17 100644
--- a/arch/sparc/kernel/process.c
+++ b/arch/sparc/kernel/process.c
@@ -419,14 +419,26 @@ asmlinkage int sparc_do_fork(unsigned long clone_flags,
419 unsigned long stack_size) 419 unsigned long stack_size)
420{ 420{
421 unsigned long parent_tid_ptr, child_tid_ptr; 421 unsigned long parent_tid_ptr, child_tid_ptr;
422 unsigned long orig_i1 = regs->u_regs[UREG_I1];
423 long ret;
422 424
423 parent_tid_ptr = regs->u_regs[UREG_I2]; 425 parent_tid_ptr = regs->u_regs[UREG_I2];
424 child_tid_ptr = regs->u_regs[UREG_I4]; 426 child_tid_ptr = regs->u_regs[UREG_I4];
425 427
426 return do_fork(clone_flags, stack_start, 428 ret = do_fork(clone_flags, stack_start,
427 regs, stack_size, 429 regs, stack_size,
428 (int __user *) parent_tid_ptr, 430 (int __user *) parent_tid_ptr,
429 (int __user *) child_tid_ptr); 431 (int __user *) child_tid_ptr);
432
433 /* If we get an error and potentially restart the system
434 * call, we're screwed because copy_thread() clobbered
435 * the parent's %o1. So detect that case and restore it
436 * here.
437 */
438 if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK)
439 regs->u_regs[UREG_I1] = orig_i1;
440
441 return ret;
430} 442}
431 443
432/* Copy a Sparc thread. The fork() return value conventions 444/* Copy a Sparc thread. The fork() return value conventions
@@ -626,11 +638,6 @@ asmlinkage int sparc_execve(struct pt_regs *regs)
626 (char __user * __user *)regs->u_regs[base + UREG_I2], 638 (char __user * __user *)regs->u_regs[base + UREG_I2],
627 regs); 639 regs);
628 putname(filename); 640 putname(filename);
629 if (error == 0) {
630 task_lock(current);
631 current->ptrace &= ~PT_DTRACE;
632 task_unlock(current);
633 }
634out: 641out:
635 return error; 642 return error;
636} 643}
diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c
index 7f44ae69b29e..81f3b929743f 100644
--- a/arch/sparc/kernel/ptrace.c
+++ b/arch/sparc/kernel/ptrace.c
@@ -170,8 +170,8 @@ static int genregs32_set(struct task_struct *target,
170 switch (pos) { 170 switch (pos) {
171 case 32: /* PSR */ 171 case 32: /* PSR */
172 psr = regs->psr; 172 psr = regs->psr;
173 psr &= ~PSR_ICC; 173 psr &= ~(PSR_ICC | PSR_SYSCALL);
174 psr |= (reg & PSR_ICC); 174 psr |= (reg & (PSR_ICC | PSR_SYSCALL));
175 regs->psr = psr; 175 regs->psr = psr;
176 break; 176 break;
177 case 33: /* PC */ 177 case 33: /* PC */
@@ -441,6 +441,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
441 break; 441 break;
442 442
443 default: 443 default:
444 if (request == PTRACE_SPARC_DETACH)
445 request = PTRACE_DETACH;
444 ret = ptrace_request(child, request, addr, data); 446 ret = ptrace_request(child, request, addr, data);
445 break; 447 break;
446 } 448 }
diff --git a/arch/sparc/kernel/rtrap.S b/arch/sparc/kernel/rtrap.S
index 77ca6fd81253..ab818cdc4cc0 100644
--- a/arch/sparc/kernel/rtrap.S
+++ b/arch/sparc/kernel/rtrap.S
@@ -50,8 +50,9 @@ rtrap_7win_patch5: and %g1, 0x7f, %g1
50ret_trap_entry: 50ret_trap_entry:
51ret_trap_lockless_ipi: 51ret_trap_lockless_ipi:
52 andcc %t_psr, PSR_PS, %g0 52 andcc %t_psr, PSR_PS, %g0
53 sethi %hi(PSR_SYSCALL), %g1
53 be 1f 54 be 1f
54 nop 55 andn %t_psr, %g1, %t_psr
55 56
56 wr %t_psr, 0x0, %psr 57 wr %t_psr, 0x0, %psr
57 b ret_trap_kernel 58 b ret_trap_kernel
@@ -73,7 +74,6 @@ signal_p:
73 ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr 74 ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr
74 75
75 mov %l5, %o1 76 mov %l5, %o1
76 mov %l6, %o2
77 call do_signal 77 call do_signal
78 add %sp, STACKFRAME_SZ, %o0 ! pt_regs ptr 78 add %sp, STACKFRAME_SZ, %o0 ! pt_regs ptr
79 79
@@ -81,6 +81,8 @@ signal_p:
81 ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr 81 ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr
82 clr %l6 82 clr %l6
83ret_trap_continue: 83ret_trap_continue:
84 sethi %hi(PSR_SYSCALL), %g1
85 andn %t_psr, %g1, %t_psr
84 wr %t_psr, 0x0, %psr 86 wr %t_psr, 0x0, %psr
85 WRITE_PAUSE 87 WRITE_PAUSE
86 88
@@ -137,8 +139,9 @@ ret_trap_userwins_ok:
137 LOAD_PT_PRIV(sp, t_psr, t_pc, t_npc) 139 LOAD_PT_PRIV(sp, t_psr, t_pc, t_npc)
138 or %t_pc, %t_npc, %g2 140 or %t_pc, %t_npc, %g2
139 andcc %g2, 0x3, %g0 141 andcc %g2, 0x3, %g0
142 sethi %hi(PSR_SYSCALL), %g2
140 be 1f 143 be 1f
141 nop 144 andn %t_psr, %g2, %t_psr
142 145
143 b ret_trap_unaligned_pc 146 b ret_trap_unaligned_pc
144 add %sp, STACKFRAME_SZ, %o0 147 add %sp, STACKFRAME_SZ, %o0
@@ -201,6 +204,8 @@ rtrap_patch5: and %g1, 0xff, %g1
2011: 2041:
202 LOAD_PT_ALL(sp, t_psr, t_pc, t_npc, g1) 205 LOAD_PT_ALL(sp, t_psr, t_pc, t_npc, g1)
2032: 2062:
207 sethi %hi(PSR_SYSCALL), %twin_tmp1
208 andn %t_psr, %twin_tmp1, %t_psr
204 wr %t_psr, 0x0, %psr 209 wr %t_psr, 0x0, %psr
205 WRITE_PAUSE 210 WRITE_PAUSE
206 211
diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c
index 3c312290c3c2..3fd1df9f9ba7 100644
--- a/arch/sparc/kernel/signal.c
+++ b/arch/sparc/kernel/signal.c
@@ -145,6 +145,9 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
145 regs->psr = (up_psr & ~(PSR_ICC | PSR_EF)) 145 regs->psr = (up_psr & ~(PSR_ICC | PSR_EF))
146 | (regs->psr & (PSR_ICC | PSR_EF)); 146 | (regs->psr & (PSR_ICC | PSR_EF));
147 147
148 /* Prevent syscall restart. */
149 pt_regs_clear_syscall(regs);
150
148 err |= __get_user(fpu_save, &sf->fpu_save); 151 err |= __get_user(fpu_save, &sf->fpu_save);
149 152
150 if (fpu_save) 153 if (fpu_save)
@@ -199,6 +202,9 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
199 202
200 regs->psr = (regs->psr & ~PSR_ICC) | (psr & PSR_ICC); 203 regs->psr = (regs->psr & ~PSR_ICC) | (psr & PSR_ICC);
201 204
205 /* Prevent syscall restart. */
206 pt_regs_clear_syscall(regs);
207
202 err |= __get_user(fpu_save, &sf->fpu_save); 208 err |= __get_user(fpu_save, &sf->fpu_save);
203 209
204 if (fpu_save) 210 if (fpu_save)
@@ -245,15 +251,29 @@ static inline int invalid_frame_pointer(void __user *fp, int fplen)
245 251
246static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, unsigned long framesize) 252static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, unsigned long framesize)
247{ 253{
248 unsigned long sp; 254 unsigned long sp = regs->u_regs[UREG_FP];
249 255
250 sp = regs->u_regs[UREG_FP]; 256 /*
257 * If we are on the alternate signal stack and would overflow it, don't.
258 * Return an always-bogus address instead so we will die with SIGSEGV.
259 */
260 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize)))
261 return (void __user *) -1L;
251 262
252 /* This is the X/Open sanctioned signal stack switching. */ 263 /* This is the X/Open sanctioned signal stack switching. */
253 if (sa->sa_flags & SA_ONSTACK) { 264 if (sa->sa_flags & SA_ONSTACK) {
254 if (!on_sig_stack(sp) && !((current->sas_ss_sp + current->sas_ss_size) & 7)) 265 if (sas_ss_flags(sp) == 0)
255 sp = current->sas_ss_sp + current->sas_ss_size; 266 sp = current->sas_ss_sp + current->sas_ss_size;
256 } 267 }
268
269 /* Always align the stack frame. This handles two cases. First,
270 * sigaltstack need not be mindful of platform specific stack
271 * alignment. Second, if we took this signal because the stack
272 * is not aligned properly, we'd like to take the signal cleanly
273 * and report that.
274 */
275 sp &= ~7UL;
276
257 return (void __user *)(sp - framesize); 277 return (void __user *)(sp - framesize);
258} 278}
259 279
@@ -493,26 +513,36 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
493 * want to handle. Thus you cannot kill init even with a SIGKILL even by 513 * want to handle. Thus you cannot kill init even with a SIGKILL even by
494 * mistake. 514 * mistake.
495 */ 515 */
496asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int restart_syscall) 516asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0)
497{ 517{
498 siginfo_t info;
499 struct sparc_deliver_cookie cookie;
500 struct k_sigaction ka; 518 struct k_sigaction ka;
501 int signr; 519 int restart_syscall;
502 sigset_t *oldset; 520 sigset_t *oldset;
521 siginfo_t info;
522 int signr;
503 523
504 cookie.restart_syscall = restart_syscall; 524 if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C))
505 cookie.orig_i0 = orig_i0; 525 restart_syscall = 1;
526 else
527 restart_syscall = 0;
506 528
507 if (test_thread_flag(TIF_RESTORE_SIGMASK)) 529 if (test_thread_flag(TIF_RESTORE_SIGMASK))
508 oldset = &current->saved_sigmask; 530 oldset = &current->saved_sigmask;
509 else 531 else
510 oldset = &current->blocked; 532 oldset = &current->blocked;
511 533
512 signr = get_signal_to_deliver(&info, &ka, regs, &cookie); 534 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
535
536 /* If the debugger messes with the program counter, it clears
537 * the software "in syscall" bit, directing us to not perform
538 * a syscall restart.
539 */
540 if (restart_syscall && !pt_regs_is_syscall(regs))
541 restart_syscall = 0;
542
513 if (signr > 0) { 543 if (signr > 0) {
514 if (cookie.restart_syscall) 544 if (restart_syscall)
515 syscall_restart(cookie.orig_i0, regs, &ka.sa); 545 syscall_restart(orig_i0, regs, &ka.sa);
516 handle_signal(signr, &ka, &info, oldset, regs); 546 handle_signal(signr, &ka, &info, oldset, regs);
517 547
518 /* a signal was successfully delivered; the saved 548 /* a signal was successfully delivered; the saved
@@ -524,16 +554,16 @@ asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int rest
524 clear_thread_flag(TIF_RESTORE_SIGMASK); 554 clear_thread_flag(TIF_RESTORE_SIGMASK);
525 return; 555 return;
526 } 556 }
527 if (cookie.restart_syscall && 557 if (restart_syscall &&
528 (regs->u_regs[UREG_I0] == ERESTARTNOHAND || 558 (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
529 regs->u_regs[UREG_I0] == ERESTARTSYS || 559 regs->u_regs[UREG_I0] == ERESTARTSYS ||
530 regs->u_regs[UREG_I0] == ERESTARTNOINTR)) { 560 regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
531 /* replay the system call when we are done */ 561 /* replay the system call when we are done */
532 regs->u_regs[UREG_I0] = cookie.orig_i0; 562 regs->u_regs[UREG_I0] = orig_i0;
533 regs->pc -= 4; 563 regs->pc -= 4;
534 regs->npc -= 4; 564 regs->npc -= 4;
535 } 565 }
536 if (cookie.restart_syscall && 566 if (restart_syscall &&
537 regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { 567 regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
538 regs->u_regs[UREG_G1] = __NR_restart_syscall; 568 regs->u_regs[UREG_G1] = __NR_restart_syscall;
539 regs->pc -= 4; 569 regs->pc -= 4;
@@ -585,27 +615,3 @@ do_sys_sigstack(struct sigstack __user *ssptr, struct sigstack __user *ossptr,
585out: 615out:
586 return ret; 616 return ret;
587} 617}
588
589void ptrace_signal_deliver(struct pt_regs *regs, void *cookie)
590{
591 struct sparc_deliver_cookie *cp = cookie;
592
593 if (cp->restart_syscall &&
594 (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
595 regs->u_regs[UREG_I0] == ERESTARTSYS ||
596 regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
597 /* replay the system call when we are done */
598 regs->u_regs[UREG_I0] = cp->orig_i0;
599 regs->pc -= 4;
600 regs->npc -= 4;
601 cp->restart_syscall = 0;
602 }
603
604 if (cp->restart_syscall &&
605 regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
606 regs->u_regs[UREG_G1] = __NR_restart_syscall;
607 regs->pc -= 4;
608 regs->npc -= 4;
609 cp->restart_syscall = 0;
610 }
611}
diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c
index f188b5dc9fd0..3c6b49a53ae8 100644
--- a/arch/sparc/kernel/sys_sparc.c
+++ b/arch/sparc/kernel/sys_sparc.c
@@ -219,12 +219,11 @@ out:
219 return err; 219 return err;
220} 220}
221 221
222int sparc_mmap_check(unsigned long addr, unsigned long len, unsigned long flags) 222int sparc_mmap_check(unsigned long addr, unsigned long len)
223{ 223{
224 if (ARCH_SUN4C_SUN4 && 224 if (ARCH_SUN4C_SUN4 &&
225 (len > 0x20000000 || 225 (len > 0x20000000 ||
226 ((flags & MAP_FIXED) && 226 (addr < 0xe0000000 && addr + len > 0x20000000)))
227 addr < 0xe0000000 && addr + len > 0x20000000)))
228 return -EINVAL; 227 return -EINVAL;
229 228
230 /* See asm-sparc/uaccess.h */ 229 /* See asm-sparc/uaccess.h */
@@ -296,52 +295,14 @@ asmlinkage unsigned long sparc_mremap(unsigned long addr,
296 unsigned long old_len, unsigned long new_len, 295 unsigned long old_len, unsigned long new_len,
297 unsigned long flags, unsigned long new_addr) 296 unsigned long flags, unsigned long new_addr)
298{ 297{
299 struct vm_area_struct *vma;
300 unsigned long ret = -EINVAL; 298 unsigned long ret = -EINVAL;
301 if (ARCH_SUN4C_SUN4) { 299
302 if (old_len > 0x20000000 || new_len > 0x20000000) 300 if (unlikely(sparc_mmap_check(addr, old_len)))
303 goto out; 301 goto out;
304 if (addr < 0xe0000000 && addr + old_len > 0x20000000) 302 if (unlikely(sparc_mmap_check(new_addr, new_len)))
305 goto out;
306 }
307 if (old_len > TASK_SIZE - PAGE_SIZE ||
308 new_len > TASK_SIZE - PAGE_SIZE)
309 goto out; 303 goto out;
310 down_write(&current->mm->mmap_sem); 304 down_write(&current->mm->mmap_sem);
311 if (flags & MREMAP_FIXED) {
312 if (ARCH_SUN4C_SUN4 &&
313 new_addr < 0xe0000000 &&
314 new_addr + new_len > 0x20000000)
315 goto out_sem;
316 if (new_addr + new_len > TASK_SIZE - PAGE_SIZE)
317 goto out_sem;
318 } else if ((ARCH_SUN4C_SUN4 && addr < 0xe0000000 &&
319 addr + new_len > 0x20000000) ||
320 addr + new_len > TASK_SIZE - PAGE_SIZE) {
321 unsigned long map_flags = 0;
322 struct file *file = NULL;
323
324 ret = -ENOMEM;
325 if (!(flags & MREMAP_MAYMOVE))
326 goto out_sem;
327
328 vma = find_vma(current->mm, addr);
329 if (vma) {
330 if (vma->vm_flags & VM_SHARED)
331 map_flags |= MAP_SHARED;
332 file = vma->vm_file;
333 }
334
335 new_addr = get_unmapped_area(file, addr, new_len,
336 vma ? vma->vm_pgoff : 0,
337 map_flags);
338 ret = new_addr;
339 if (new_addr & ~PAGE_MASK)
340 goto out_sem;
341 flags |= MREMAP_FIXED;
342 }
343 ret = do_mremap(addr, old_len, new_len, flags, new_addr); 305 ret = do_mremap(addr, old_len, new_len, flags, new_addr);
344out_sem:
345 up_write(&current->mm->mmap_sem); 306 up_write(&current->mm->mmap_sem);
346out: 307out:
347 return ret; 308 return ret;