diff options
Diffstat (limited to 'arch/ia64/kernel/ptrace.c')
-rw-r--r-- | arch/ia64/kernel/ptrace.c | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index 907464ee7273..575a8f657b31 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c | |||
@@ -635,11 +635,17 @@ ia64_flush_fph (struct task_struct *task) | |||
635 | { | 635 | { |
636 | struct ia64_psr *psr = ia64_psr(ia64_task_regs(task)); | 636 | struct ia64_psr *psr = ia64_psr(ia64_task_regs(task)); |
637 | 637 | ||
638 | /* | ||
639 | * Prevent migrating this task while | ||
640 | * we're fiddling with the FPU state | ||
641 | */ | ||
642 | preempt_disable(); | ||
638 | if (ia64_is_local_fpu_owner(task) && psr->mfh) { | 643 | if (ia64_is_local_fpu_owner(task) && psr->mfh) { |
639 | psr->mfh = 0; | 644 | psr->mfh = 0; |
640 | task->thread.flags |= IA64_THREAD_FPH_VALID; | 645 | task->thread.flags |= IA64_THREAD_FPH_VALID; |
641 | ia64_save_fpu(&task->thread.fph[0]); | 646 | ia64_save_fpu(&task->thread.fph[0]); |
642 | } | 647 | } |
648 | preempt_enable(); | ||
643 | } | 649 | } |
644 | 650 | ||
645 | /* | 651 | /* |
@@ -692,16 +698,30 @@ convert_to_non_syscall (struct task_struct *child, struct pt_regs *pt, | |||
692 | unsigned long cfm) | 698 | unsigned long cfm) |
693 | { | 699 | { |
694 | struct unw_frame_info info, prev_info; | 700 | struct unw_frame_info info, prev_info; |
695 | unsigned long ip, pr; | 701 | unsigned long ip, sp, pr; |
696 | 702 | ||
697 | unw_init_from_blocked_task(&info, child); | 703 | unw_init_from_blocked_task(&info, child); |
698 | while (1) { | 704 | while (1) { |
699 | prev_info = info; | 705 | prev_info = info; |
700 | if (unw_unwind(&info) < 0) | 706 | if (unw_unwind(&info) < 0) |
701 | return; | 707 | return; |
702 | if (unw_get_rp(&info, &ip) < 0) | 708 | |
709 | unw_get_sp(&info, &sp); | ||
710 | if ((long)((unsigned long)child + IA64_STK_OFFSET - sp) | ||
711 | < IA64_PT_REGS_SIZE) { | ||
712 | dprintk("ptrace.%s: ran off the top of the kernel " | ||
713 | "stack\n", __FUNCTION__); | ||
714 | return; | ||
715 | } | ||
716 | if (unw_get_pr (&prev_info, &pr) < 0) { | ||
717 | unw_get_rp(&prev_info, &ip); | ||
718 | dprintk("ptrace.%s: failed to read " | ||
719 | "predicate register (ip=0x%lx)\n", | ||
720 | __FUNCTION__, ip); | ||
703 | return; | 721 | return; |
704 | if (ip < FIXADDR_USER_END) | 722 | } |
723 | if (unw_is_intr_frame(&info) | ||
724 | && (pr & (1UL << PRED_USER_STACK))) | ||
705 | break; | 725 | break; |
706 | } | 726 | } |
707 | 727 | ||