aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/ia64/kernel/process.c6
-rw-r--r--arch/ia64/kernel/ptrace.c82
2 files changed, 88 insertions, 0 deletions
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index 5c9efe626563..be6c6f7be027 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -163,6 +163,8 @@ void tsk_clear_notify_resume(struct task_struct *tsk)
163 if (tsk->thread.pfm_needs_checking) 163 if (tsk->thread.pfm_needs_checking)
164 return; 164 return;
165#endif 165#endif
166 if (test_ti_thread_flag(task_thread_info(tsk), TIF_RESTORE_RSE))
167 return;
166 clear_ti_thread_flag(task_thread_info(tsk), TIF_NOTIFY_RESUME); 168 clear_ti_thread_flag(task_thread_info(tsk), TIF_NOTIFY_RESUME);
167} 169}
168 170
@@ -184,6 +186,10 @@ do_notify_resume_user (sigset_t *unused, struct sigscratch *scr, long in_syscall
184 /* deal with pending signal delivery */ 186 /* deal with pending signal delivery */
185 if (test_thread_flag(TIF_SIGPENDING)||test_thread_flag(TIF_RESTORE_SIGMASK)) 187 if (test_thread_flag(TIF_SIGPENDING)||test_thread_flag(TIF_RESTORE_SIGMASK))
186 ia64_do_signal(scr, in_syscall); 188 ia64_do_signal(scr, in_syscall);
189
190 /* copy user rbs to kernel rbs */
191 if (unlikely(test_thread_flag(TIF_RESTORE_RSE)))
192 ia64_sync_krbs();
187} 193}
188 194
189static int pal_halt = 1; 195static int pal_halt = 1;
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index 2e96f17b2f3b..2de5a524a0ee 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -547,6 +547,72 @@ ia64_sync_user_rbs (struct task_struct *child, struct switch_stack *sw,
547 return 0; 547 return 0;
548} 548}
549 549
550static long
551ia64_sync_kernel_rbs (struct task_struct *child, struct switch_stack *sw,
552 unsigned long user_rbs_start, unsigned long user_rbs_end)
553{
554 unsigned long addr, val;
555 long ret;
556
557 /* now copy word for word from user rbs to kernel rbs: */
558 for (addr = user_rbs_start; addr < user_rbs_end; addr += 8) {
559 if (access_process_vm(child, addr, &val, sizeof(val), 0)
560 != sizeof(val))
561 return -EIO;
562
563 ret = ia64_poke(child, sw, user_rbs_end, addr, val);
564 if (ret < 0)
565 return ret;
566 }
567 return 0;
568}
569
570typedef long (*syncfunc_t)(struct task_struct *, struct switch_stack *,
571 unsigned long, unsigned long);
572
573static void do_sync_rbs(struct unw_frame_info *info, void *arg)
574{
575 struct pt_regs *pt;
576 unsigned long urbs_end;
577 syncfunc_t fn = arg;
578
579 if (unw_unwind_to_user(info) < 0)
580 return;
581 pt = task_pt_regs(info->task);
582 urbs_end = ia64_get_user_rbs_end(info->task, pt, NULL);
583
584 fn(info->task, info->sw, pt->ar_bspstore, urbs_end);
585}
586
587/*
588 * when a thread is stopped (ptraced), debugger might change thread's user
589 * stack (change memory directly), and we must avoid the RSE stored in kernel
590 * to override user stack (user space's RSE is newer than kernel's in the
591 * case). To workaround the issue, we copy kernel RSE to user RSE before the
592 * task is stopped, so user RSE has updated data. we then copy user RSE to
593 * kernel after the task is resummed from traced stop and kernel will use the
594 * newer RSE to return to user. TIF_RESTORE_RSE is the flag to indicate we need
595 * synchronize user RSE to kernel.
596 */
597void ia64_ptrace_stop(void)
598{
599 if (test_and_set_tsk_thread_flag(current, TIF_RESTORE_RSE))
600 return;
601 tsk_set_notify_resume(current);
602 unw_init_running(do_sync_rbs, ia64_sync_user_rbs);
603}
604
605/*
606 * This is called to read back the register backing store.
607 */
608void ia64_sync_krbs(void)
609{
610 clear_tsk_thread_flag(current, TIF_RESTORE_RSE);
611 tsk_clear_notify_resume(current);
612
613 unw_init_running(do_sync_rbs, ia64_sync_kernel_rbs);
614}
615
550static inline int 616static inline int
551thread_matches (struct task_struct *thread, unsigned long addr) 617thread_matches (struct task_struct *thread, unsigned long addr)
552{ 618{
@@ -1422,6 +1488,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data)
1422 struct task_struct *child; 1488 struct task_struct *child;
1423 struct switch_stack *sw; 1489 struct switch_stack *sw;
1424 long ret; 1490 long ret;
1491 struct unw_frame_info info;
1425 1492
1426 lock_kernel(); 1493 lock_kernel();
1427 ret = -EPERM; 1494 ret = -EPERM;
@@ -1453,6 +1520,8 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data)
1453 1520
1454 if (request == PTRACE_ATTACH) { 1521 if (request == PTRACE_ATTACH) {
1455 ret = ptrace_attach(child); 1522 ret = ptrace_attach(child);
1523 if (!ret)
1524 arch_ptrace_attach(child);
1456 goto out_tsk; 1525 goto out_tsk;
1457 } 1526 }
1458 1527
@@ -1481,6 +1550,11 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data)
1481 /* write the word at location addr */ 1550 /* write the word at location addr */
1482 urbs_end = ia64_get_user_rbs_end(child, pt, NULL); 1551 urbs_end = ia64_get_user_rbs_end(child, pt, NULL);
1483 ret = ia64_poke(child, sw, urbs_end, addr, data); 1552 ret = ia64_poke(child, sw, urbs_end, addr, data);
1553
1554 /* Make sure user RBS has the latest data */
1555 unw_init_from_blocked_task(&info, child);
1556 do_sync_rbs(&info, ia64_sync_user_rbs);
1557
1484 goto out_tsk; 1558 goto out_tsk;
1485 1559
1486 case PTRACE_PEEKUSR: 1560 case PTRACE_PEEKUSR:
@@ -1634,6 +1708,10 @@ syscall_trace_enter (long arg0, long arg1, long arg2, long arg3,
1634 && (current->ptrace & PT_PTRACED)) 1708 && (current->ptrace & PT_PTRACED))
1635 syscall_trace(); 1709 syscall_trace();
1636 1710
1711 /* copy user rbs to kernel rbs */
1712 if (test_thread_flag(TIF_RESTORE_RSE))
1713 ia64_sync_krbs();
1714
1637 if (unlikely(current->audit_context)) { 1715 if (unlikely(current->audit_context)) {
1638 long syscall; 1716 long syscall;
1639 int arch; 1717 int arch;
@@ -1671,4 +1749,8 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3,
1671 || test_thread_flag(TIF_SINGLESTEP)) 1749 || test_thread_flag(TIF_SINGLESTEP))
1672 && (current->ptrace & PT_PTRACED)) 1750 && (current->ptrace & PT_PTRACED))
1673 syscall_trace(); 1751 syscall_trace();
1752
1753 /* copy user rbs to kernel rbs */
1754 if (test_thread_flag(TIF_RESTORE_RSE))
1755 ia64_sync_krbs();
1674} 1756}