aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-05-14 22:11:36 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-05-14 22:11:36 -0400
commit8978a318837d7acefca82645017c0534aeba5a36 (patch)
treef69f5bc9a11d1a3a5c6391a9b48c9bcae4615a5a /arch
parentf7fd63c0b5e170efc20e7b9a0aad7f69dff62c64 (diff)
parent9a28dbf8af11d127bf1c644143e7882cb91515dd (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6: sparc64: Use a TS_RESTORE_SIGMASK lmb: Make lmb debugging more useful. lmb: Fix inconsistent alignment of size argument. sparc: Fix mremap address range validation.
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc/kernel/sys_sparc.c48
-rw-r--r--arch/sparc64/kernel/rtrap.S6
-rw-r--r--arch/sparc64/kernel/signal.c21
-rw-r--r--arch/sparc64/kernel/signal32.c13
-rw-r--r--arch/sparc64/kernel/sys_sparc.c36
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c33
6 files changed, 31 insertions, 126 deletions
diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c
index e995491c4436..3c6b49a53ae8 100644
--- a/arch/sparc/kernel/sys_sparc.c
+++ b/arch/sparc/kernel/sys_sparc.c
@@ -219,7 +219,7 @@ 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 ||
@@ -295,52 +295,14 @@ asmlinkage unsigned long sparc_mremap(unsigned long addr,
295 unsigned long old_len, unsigned long new_len, 295 unsigned long old_len, unsigned long new_len,
296 unsigned long flags, unsigned long new_addr) 296 unsigned long flags, unsigned long new_addr)
297{ 297{
298 struct vm_area_struct *vma;
299 unsigned long ret = -EINVAL; 298 unsigned long ret = -EINVAL;
300 if (ARCH_SUN4C_SUN4) { 299
301 if (old_len > 0x20000000 || new_len > 0x20000000) 300 if (unlikely(sparc_mmap_check(addr, old_len)))
302 goto out; 301 goto out;
303 if (addr < 0xe0000000 && addr + old_len > 0x20000000) 302 if (unlikely(sparc_mmap_check(new_addr, new_len)))
304 goto out;
305 }
306 if (old_len > TASK_SIZE - PAGE_SIZE ||
307 new_len > TASK_SIZE - PAGE_SIZE)
308 goto out; 303 goto out;
309 down_write(&current->mm->mmap_sem); 304 down_write(&current->mm->mmap_sem);
310 if (flags & MREMAP_FIXED) {
311 if (ARCH_SUN4C_SUN4 &&
312 new_addr < 0xe0000000 &&
313 new_addr + new_len > 0x20000000)
314 goto out_sem;
315 if (new_addr + new_len > TASK_SIZE - PAGE_SIZE)
316 goto out_sem;
317 } else if ((ARCH_SUN4C_SUN4 && addr < 0xe0000000 &&
318 addr + new_len > 0x20000000) ||
319 addr + new_len > TASK_SIZE - PAGE_SIZE) {
320 unsigned long map_flags = 0;
321 struct file *file = NULL;
322
323 ret = -ENOMEM;
324 if (!(flags & MREMAP_MAYMOVE))
325 goto out_sem;
326
327 vma = find_vma(current->mm, addr);
328 if (vma) {
329 if (vma->vm_flags & VM_SHARED)
330 map_flags |= MAP_SHARED;
331 file = vma->vm_file;
332 }
333
334 new_addr = get_unmapped_area(file, addr, new_len,
335 vma ? vma->vm_pgoff : 0,
336 map_flags);
337 ret = new_addr;
338 if (new_addr & ~PAGE_MASK)
339 goto out_sem;
340 flags |= MREMAP_FIXED;
341 }
342 ret = do_mremap(addr, old_len, new_len, flags, new_addr); 305 ret = do_mremap(addr, old_len, new_len, flags, new_addr);
343out_sem:
344 up_write(&current->mm->mmap_sem); 306 up_write(&current->mm->mmap_sem);
345out: 307out:
346 return ret; 308 return ret;
diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S
index b9b785fd8b46..16689b2930db 100644
--- a/arch/sparc64/kernel/rtrap.S
+++ b/arch/sparc64/kernel/rtrap.S
@@ -46,7 +46,7 @@ __handle_user_windows:
46 wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate 46 wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate
47 ldx [%g6 + TI_FLAGS], %l0 47 ldx [%g6 + TI_FLAGS], %l0
48 48
491: andcc %l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0 491: andcc %l0, _TIF_SIGPENDING, %g0
50 be,pt %xcc, __handle_user_windows_continue 50 be,pt %xcc, __handle_user_windows_continue
51 nop 51 nop
52 mov %l5, %o1 52 mov %l5, %o1
@@ -86,7 +86,7 @@ __handle_perfctrs:
86 wrpr %g0, RTRAP_PSTATE, %pstate 86 wrpr %g0, RTRAP_PSTATE, %pstate
87 wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate 87 wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate
88 ldx [%g6 + TI_FLAGS], %l0 88 ldx [%g6 + TI_FLAGS], %l0
891: andcc %l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0 891: andcc %l0, _TIF_SIGPENDING, %g0
90 90
91 be,pt %xcc, __handle_perfctrs_continue 91 be,pt %xcc, __handle_perfctrs_continue
92 sethi %hi(TSTATE_PEF), %o0 92 sethi %hi(TSTATE_PEF), %o0
@@ -195,7 +195,7 @@ __handle_preemption_continue:
195 andcc %l1, %o0, %g0 195 andcc %l1, %o0, %g0
196 andcc %l0, _TIF_NEED_RESCHED, %g0 196 andcc %l0, _TIF_NEED_RESCHED, %g0
197 bne,pn %xcc, __handle_preemption 197 bne,pn %xcc, __handle_preemption
198 andcc %l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0 198 andcc %l0, _TIF_SIGPENDING, %g0
199 bne,pn %xcc, __handle_signal 199 bne,pn %xcc, __handle_signal
200__handle_signal_continue: 200__handle_signal_continue:
201 ldub [%g6 + TI_WSAVED], %o2 201 ldub [%g6 + TI_WSAVED], %o2
diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
index 2378482c2aab..6e4dc67d16af 100644
--- a/arch/sparc64/kernel/signal.c
+++ b/arch/sparc64/kernel/signal.c
@@ -247,7 +247,9 @@ static long _sigpause_common(old_sigset_t set)
247 247
248 current->state = TASK_INTERRUPTIBLE; 248 current->state = TASK_INTERRUPTIBLE;
249 schedule(); 249 schedule();
250 set_thread_flag(TIF_RESTORE_SIGMASK); 250
251 set_restore_sigmask();
252
251 return -ERESTARTNOHAND; 253 return -ERESTARTNOHAND;
252} 254}
253 255
@@ -537,7 +539,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
537 } else 539 } else
538 restart_syscall = 0; 540 restart_syscall = 0;
539 541
540 if (test_thread_flag(TIF_RESTORE_SIGMASK)) 542 if (current_thread_info()->status & TS_RESTORE_SIGMASK)
541 oldset = &current->saved_sigmask; 543 oldset = &current->saved_sigmask;
542 else 544 else
543 oldset = &current->blocked; 545 oldset = &current->blocked;
@@ -566,13 +568,12 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
566 syscall_restart(orig_i0, regs, &ka.sa); 568 syscall_restart(orig_i0, regs, &ka.sa);
567 handle_signal(signr, &ka, &info, oldset, regs); 569 handle_signal(signr, &ka, &info, oldset, regs);
568 570
569 /* a signal was successfully delivered; the saved 571 /* A signal was successfully delivered; the saved
570 * sigmask will have been stored in the signal frame, 572 * sigmask will have been stored in the signal frame,
571 * and will be restored by sigreturn, so we can simply 573 * and will be restored by sigreturn, so we can simply
572 * clear the TIF_RESTORE_SIGMASK flag. 574 * clear the TS_RESTORE_SIGMASK flag.
573 */ 575 */
574 if (test_thread_flag(TIF_RESTORE_SIGMASK)) 576 current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
575 clear_thread_flag(TIF_RESTORE_SIGMASK);
576 return; 577 return;
577 } 578 }
578 if (restart_syscall && 579 if (restart_syscall &&
@@ -591,17 +592,17 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
591 regs->tnpc -= 4; 592 regs->tnpc -= 4;
592 } 593 }
593 594
594 /* if there's no signal to deliver, we just put the saved sigmask 595 /* If there's no signal to deliver, we just put the saved sigmask
595 * back 596 * back
596 */ 597 */
597 if (test_thread_flag(TIF_RESTORE_SIGMASK)) { 598 if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
598 clear_thread_flag(TIF_RESTORE_SIGMASK); 599 current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
599 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL); 600 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
600 } 601 }
601} 602}
602 603
603void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags) 604void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags)
604{ 605{
605 if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) 606 if (thread_info_flags & _TIF_SIGPENDING)
606 do_signal(regs, orig_i0); 607 do_signal(regs, orig_i0);
607} 608}
diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
index 3f19e9af3d1b..97cdd1bf4a10 100644
--- a/arch/sparc64/kernel/signal32.c
+++ b/arch/sparc64/kernel/signal32.c
@@ -788,13 +788,12 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs,
788 syscall_restart32(orig_i0, regs, &ka.sa); 788 syscall_restart32(orig_i0, regs, &ka.sa);
789 handle_signal32(signr, &ka, &info, oldset, regs); 789 handle_signal32(signr, &ka, &info, oldset, regs);
790 790
791 /* a signal was successfully delivered; the saved 791 /* A signal was successfully delivered; the saved
792 * sigmask will have been stored in the signal frame, 792 * sigmask will have been stored in the signal frame,
793 * and will be restored by sigreturn, so we can simply 793 * and will be restored by sigreturn, so we can simply
794 * clear the TIF_RESTORE_SIGMASK flag. 794 * clear the TS_RESTORE_SIGMASK flag.
795 */ 795 */
796 if (test_thread_flag(TIF_RESTORE_SIGMASK)) 796 current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
797 clear_thread_flag(TIF_RESTORE_SIGMASK);
798 return; 797 return;
799 } 798 }
800 if (restart_syscall && 799 if (restart_syscall &&
@@ -813,11 +812,11 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs,
813 regs->tnpc -= 4; 812 regs->tnpc -= 4;
814 } 813 }
815 814
816 /* if there's no signal to deliver, we just put the saved sigmask 815 /* If there's no signal to deliver, we just put the saved sigmask
817 * back 816 * back
818 */ 817 */
819 if (test_thread_flag(TIF_RESTORE_SIGMASK)) { 818 if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
820 clear_thread_flag(TIF_RESTORE_SIGMASK); 819 current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
821 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL); 820 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
822 } 821 }
823} 822}
diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
index 0dbc941f130e..ac1bff58c1ac 100644
--- a/arch/sparc64/kernel/sys_sparc.c
+++ b/arch/sparc64/kernel/sys_sparc.c
@@ -542,8 +542,7 @@ asmlinkage long sparc64_personality(unsigned long personality)
542 return ret; 542 return ret;
543} 543}
544 544
545int sparc64_mmap_check(unsigned long addr, unsigned long len, 545int sparc64_mmap_check(unsigned long addr, unsigned long len)
546 unsigned long flags)
547{ 546{
548 if (test_thread_flag(TIF_32BIT)) { 547 if (test_thread_flag(TIF_32BIT)) {
549 if (len >= STACK_TOP32) 548 if (len >= STACK_TOP32)
@@ -609,46 +608,19 @@ asmlinkage unsigned long sys64_mremap(unsigned long addr,
609 unsigned long old_len, unsigned long new_len, 608 unsigned long old_len, unsigned long new_len,
610 unsigned long flags, unsigned long new_addr) 609 unsigned long flags, unsigned long new_addr)
611{ 610{
612 struct vm_area_struct *vma;
613 unsigned long ret = -EINVAL; 611 unsigned long ret = -EINVAL;
614 612
615 if (test_thread_flag(TIF_32BIT)) 613 if (test_thread_flag(TIF_32BIT))
616 goto out; 614 goto out;
617 if (unlikely(new_len >= VA_EXCLUDE_START)) 615 if (unlikely(new_len >= VA_EXCLUDE_START))
618 goto out; 616 goto out;
619 if (unlikely(invalid_64bit_range(addr, old_len))) 617 if (unlikely(sparc64_mmap_check(addr, old_len)))
618 goto out;
619 if (unlikely(sparc64_mmap_check(new_addr, new_len)))
620 goto out; 620 goto out;
621 621
622 down_write(&current->mm->mmap_sem); 622 down_write(&current->mm->mmap_sem);
623 if (flags & MREMAP_FIXED) {
624 if (invalid_64bit_range(new_addr, new_len))
625 goto out_sem;
626 } else if (invalid_64bit_range(addr, new_len)) {
627 unsigned long map_flags = 0;
628 struct file *file = NULL;
629
630 ret = -ENOMEM;
631 if (!(flags & MREMAP_MAYMOVE))
632 goto out_sem;
633
634 vma = find_vma(current->mm, addr);
635 if (vma) {
636 if (vma->vm_flags & VM_SHARED)
637 map_flags |= MAP_SHARED;
638 file = vma->vm_file;
639 }
640
641 /* MREMAP_FIXED checked above. */
642 new_addr = get_unmapped_area(file, addr, new_len,
643 vma ? vma->vm_pgoff : 0,
644 map_flags);
645 ret = new_addr;
646 if (new_addr & ~PAGE_MASK)
647 goto out_sem;
648 flags |= MREMAP_FIXED;
649 }
650 ret = do_mremap(addr, old_len, new_len, flags, new_addr); 623 ret = do_mremap(addr, old_len, new_len, flags, new_addr);
651out_sem:
652 up_write(&current->mm->mmap_sem); 624 up_write(&current->mm->mmap_sem);
653out: 625out:
654 return ret; 626 return ret;
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 1aa4288125f2..ba5bd626b39e 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -867,44 +867,15 @@ asmlinkage unsigned long sys32_mremap(unsigned long addr,
867 unsigned long old_len, unsigned long new_len, 867 unsigned long old_len, unsigned long new_len,
868 unsigned long flags, u32 __new_addr) 868 unsigned long flags, u32 __new_addr)
869{ 869{
870 struct vm_area_struct *vma;
871 unsigned long ret = -EINVAL; 870 unsigned long ret = -EINVAL;
872 unsigned long new_addr = __new_addr; 871 unsigned long new_addr = __new_addr;
873 872
874 if (old_len > STACK_TOP32 || new_len > STACK_TOP32) 873 if (unlikely(sparc64_mmap_check(addr, old_len)))
875 goto out; 874 goto out;
876 if (addr > STACK_TOP32 - old_len) 875 if (unlikely(sparc64_mmap_check(new_addr, new_len)))
877 goto out; 876 goto out;
878 down_write(&current->mm->mmap_sem); 877 down_write(&current->mm->mmap_sem);
879 if (flags & MREMAP_FIXED) {
880 if (new_addr > STACK_TOP32 - new_len)
881 goto out_sem;
882 } else if (addr > STACK_TOP32 - new_len) {
883 unsigned long map_flags = 0;
884 struct file *file = NULL;
885
886 ret = -ENOMEM;
887 if (!(flags & MREMAP_MAYMOVE))
888 goto out_sem;
889
890 vma = find_vma(current->mm, addr);
891 if (vma) {
892 if (vma->vm_flags & VM_SHARED)
893 map_flags |= MAP_SHARED;
894 file = vma->vm_file;
895 }
896
897 /* MREMAP_FIXED checked above. */
898 new_addr = get_unmapped_area(file, addr, new_len,
899 vma ? vma->vm_pgoff : 0,
900 map_flags);
901 ret = new_addr;
902 if (new_addr & ~PAGE_MASK)
903 goto out_sem;
904 flags |= MREMAP_FIXED;
905 }
906 ret = do_mremap(addr, old_len, new_len, flags, new_addr); 878 ret = do_mremap(addr, old_len, new_len, flags, new_addr);
907out_sem:
908 up_write(&current->mm->mmap_sem); 879 up_write(&current->mm->mmap_sem);
909out: 880out:
910 return ret; 881 return ret;