diff options
author | Tony Luck <tony.luck@intel.com> | 2008-10-17 16:51:16 -0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2008-10-17 16:51:16 -0400 |
commit | 9224652cc76417bfe779bcdb1243cf0b083e3eee (patch) | |
tree | d80d0f2d00d9eda6500deedc9488071f005f732b /arch/ia64/kernel | |
parent | 4d4230c27f380745b7fc30c0906402eede3b2cff (diff) | |
parent | 680973edf122fd95735ecfc077cf79645d2e5081 (diff) |
Pull utrace into release branch
Diffstat (limited to 'arch/ia64/kernel')
-rw-r--r-- | arch/ia64/kernel/entry.S | 5 | ||||
-rw-r--r-- | arch/ia64/kernel/perfmon.c | 7 | ||||
-rw-r--r-- | arch/ia64/kernel/process.c | 21 | ||||
-rw-r--r-- | arch/ia64/kernel/ptrace.c | 112 | ||||
-rw-r--r-- | arch/ia64/kernel/signal.c | 8 |
5 files changed, 101 insertions, 52 deletions
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 0dd6c1419d8d..7ef0c594f5ed 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S | |||
@@ -534,6 +534,11 @@ GLOBAL_ENTRY(ia64_trace_syscall) | |||
534 | stf.spill [r16]=f10 | 534 | stf.spill [r16]=f10 |
535 | stf.spill [r17]=f11 | 535 | stf.spill [r17]=f11 |
536 | br.call.sptk.many rp=syscall_trace_enter // give parent a chance to catch syscall args | 536 | br.call.sptk.many rp=syscall_trace_enter // give parent a chance to catch syscall args |
537 | cmp.lt p6,p0=r8,r0 // check tracehook | ||
538 | adds r2=PT(R8)+16,sp // r2 = &pt_regs.r8 | ||
539 | adds r3=PT(R10)+16,sp // r3 = &pt_regs.r10 | ||
540 | mov r10=0 | ||
541 | (p6) br.cond.sptk strace_error // syscall failed -> | ||
537 | adds r16=PT(F6)+16,sp | 542 | adds r16=PT(F6)+16,sp |
538 | adds r17=PT(F7)+16,sp | 543 | adds r17=PT(F7)+16,sp |
539 | ;; | 544 | ;; |
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index fc8f3509df27..ada4605d1223 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/capability.h> | 40 | #include <linux/capability.h> |
41 | #include <linux/rcupdate.h> | 41 | #include <linux/rcupdate.h> |
42 | #include <linux/completion.h> | 42 | #include <linux/completion.h> |
43 | #include <linux/tracehook.h> | ||
43 | 44 | ||
44 | #include <asm/errno.h> | 45 | #include <asm/errno.h> |
45 | #include <asm/intrinsics.h> | 46 | #include <asm/intrinsics.h> |
@@ -3684,7 +3685,7 @@ pfm_restart(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) | |||
3684 | 3685 | ||
3685 | PFM_SET_WORK_PENDING(task, 1); | 3686 | PFM_SET_WORK_PENDING(task, 1); |
3686 | 3687 | ||
3687 | tsk_set_notify_resume(task); | 3688 | set_notify_resume(task); |
3688 | 3689 | ||
3689 | /* | 3690 | /* |
3690 | * XXX: send reschedule if task runs on another CPU | 3691 | * XXX: send reschedule if task runs on another CPU |
@@ -5044,8 +5045,6 @@ pfm_handle_work(void) | |||
5044 | 5045 | ||
5045 | PFM_SET_WORK_PENDING(current, 0); | 5046 | PFM_SET_WORK_PENDING(current, 0); |
5046 | 5047 | ||
5047 | tsk_clear_notify_resume(current); | ||
5048 | |||
5049 | regs = task_pt_regs(current); | 5048 | regs = task_pt_regs(current); |
5050 | 5049 | ||
5051 | /* | 5050 | /* |
@@ -5414,7 +5413,7 @@ pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, str | |||
5414 | * when coming from ctxsw, current still points to the | 5413 | * when coming from ctxsw, current still points to the |
5415 | * previous task, therefore we must work with task and not current. | 5414 | * previous task, therefore we must work with task and not current. |
5416 | */ | 5415 | */ |
5417 | tsk_set_notify_resume(task); | 5416 | set_notify_resume(task); |
5418 | } | 5417 | } |
5419 | /* | 5418 | /* |
5420 | * defer until state is changed (shorten spin window). the context is locked | 5419 | * defer until state is changed (shorten spin window). the context is locked |
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 3ab8373103ec..341a0319a5ba 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
29 | #include <linux/kdebug.h> | 29 | #include <linux/kdebug.h> |
30 | #include <linux/utsname.h> | 30 | #include <linux/utsname.h> |
31 | #include <linux/tracehook.h> | ||
31 | 32 | ||
32 | #include <asm/cpu.h> | 33 | #include <asm/cpu.h> |
33 | #include <asm/delay.h> | 34 | #include <asm/delay.h> |
@@ -160,21 +161,6 @@ show_regs (struct pt_regs *regs) | |||
160 | show_stack(NULL, NULL); | 161 | show_stack(NULL, NULL); |
161 | } | 162 | } |
162 | 163 | ||
163 | void tsk_clear_notify_resume(struct task_struct *tsk) | ||
164 | { | ||
165 | #ifdef CONFIG_PERFMON | ||
166 | if (tsk->thread.pfm_needs_checking) | ||
167 | return; | ||
168 | #endif | ||
169 | if (test_ti_thread_flag(task_thread_info(tsk), TIF_RESTORE_RSE)) | ||
170 | return; | ||
171 | clear_ti_thread_flag(task_thread_info(tsk), TIF_NOTIFY_RESUME); | ||
172 | } | ||
173 | |||
174 | /* | ||
175 | * do_notify_resume_user(): | ||
176 | * Called from notify_resume_user at entry.S, with interrupts disabled. | ||
177 | */ | ||
178 | void | 164 | void |
179 | do_notify_resume_user(sigset_t *unused, struct sigscratch *scr, long in_syscall) | 165 | do_notify_resume_user(sigset_t *unused, struct sigscratch *scr, long in_syscall) |
180 | { | 166 | { |
@@ -203,6 +189,11 @@ do_notify_resume_user(sigset_t *unused, struct sigscratch *scr, long in_syscall) | |||
203 | ia64_do_signal(scr, in_syscall); | 189 | ia64_do_signal(scr, in_syscall); |
204 | } | 190 | } |
205 | 191 | ||
192 | if (test_thread_flag(TIF_NOTIFY_RESUME)) { | ||
193 | clear_thread_flag(TIF_NOTIFY_RESUME); | ||
194 | tracehook_notify_resume(&scr->pt); | ||
195 | } | ||
196 | |||
206 | /* copy user rbs to kernel rbs */ | 197 | /* copy user rbs to kernel rbs */ |
207 | if (unlikely(test_thread_flag(TIF_RESTORE_RSE))) { | 198 | if (unlikely(test_thread_flag(TIF_RESTORE_RSE))) { |
208 | local_irq_enable(); /* force interrupt enable */ | 199 | local_irq_enable(); /* force interrupt enable */ |
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index 2a9943b5947f..92c9689b7d97 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/signal.h> | 22 | #include <linux/signal.h> |
23 | #include <linux/regset.h> | 23 | #include <linux/regset.h> |
24 | #include <linux/elf.h> | 24 | #include <linux/elf.h> |
25 | #include <linux/tracehook.h> | ||
25 | 26 | ||
26 | #include <asm/pgtable.h> | 27 | #include <asm/pgtable.h> |
27 | #include <asm/processor.h> | 28 | #include <asm/processor.h> |
@@ -603,7 +604,7 @@ void ia64_ptrace_stop(void) | |||
603 | { | 604 | { |
604 | if (test_and_set_tsk_thread_flag(current, TIF_RESTORE_RSE)) | 605 | if (test_and_set_tsk_thread_flag(current, TIF_RESTORE_RSE)) |
605 | return; | 606 | return; |
606 | tsk_set_notify_resume(current); | 607 | set_notify_resume(current); |
607 | unw_init_running(do_sync_rbs, ia64_sync_user_rbs); | 608 | unw_init_running(do_sync_rbs, ia64_sync_user_rbs); |
608 | } | 609 | } |
609 | 610 | ||
@@ -613,7 +614,6 @@ void ia64_ptrace_stop(void) | |||
613 | void ia64_sync_krbs(void) | 614 | void ia64_sync_krbs(void) |
614 | { | 615 | { |
615 | clear_tsk_thread_flag(current, TIF_RESTORE_RSE); | 616 | clear_tsk_thread_flag(current, TIF_RESTORE_RSE); |
616 | tsk_clear_notify_resume(current); | ||
617 | 617 | ||
618 | unw_init_running(do_sync_rbs, ia64_sync_kernel_rbs); | 618 | unw_init_running(do_sync_rbs, ia64_sync_kernel_rbs); |
619 | } | 619 | } |
@@ -644,7 +644,7 @@ ptrace_attach_sync_user_rbs (struct task_struct *child) | |||
644 | spin_lock_irq(&child->sighand->siglock); | 644 | spin_lock_irq(&child->sighand->siglock); |
645 | if (child->state == TASK_STOPPED && | 645 | if (child->state == TASK_STOPPED && |
646 | !test_and_set_tsk_thread_flag(child, TIF_RESTORE_RSE)) { | 646 | !test_and_set_tsk_thread_flag(child, TIF_RESTORE_RSE)) { |
647 | tsk_set_notify_resume(child); | 647 | set_notify_resume(child); |
648 | 648 | ||
649 | child->state = TASK_TRACED; | 649 | child->state = TASK_TRACED; |
650 | stopped = 1; | 650 | stopped = 1; |
@@ -1232,37 +1232,16 @@ arch_ptrace (struct task_struct *child, long request, long addr, long data) | |||
1232 | } | 1232 | } |
1233 | 1233 | ||
1234 | 1234 | ||
1235 | static void | ||
1236 | syscall_trace (void) | ||
1237 | { | ||
1238 | /* | ||
1239 | * The 0x80 provides a way for the tracing parent to | ||
1240 | * distinguish between a syscall stop and SIGTRAP delivery. | ||
1241 | */ | ||
1242 | ptrace_notify(SIGTRAP | ||
1243 | | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); | ||
1244 | |||
1245 | /* | ||
1246 | * This isn't the same as continuing with a signal, but it | ||
1247 | * will do for normal use. strace only continues with a | ||
1248 | * signal if the stopping signal is not SIGTRAP. -brl | ||
1249 | */ | ||
1250 | if (current->exit_code) { | ||
1251 | send_sig(current->exit_code, current, 1); | ||
1252 | current->exit_code = 0; | ||
1253 | } | ||
1254 | } | ||
1255 | |||
1256 | /* "asmlinkage" so the input arguments are preserved... */ | 1235 | /* "asmlinkage" so the input arguments are preserved... */ |
1257 | 1236 | ||
1258 | asmlinkage void | 1237 | asmlinkage long |
1259 | syscall_trace_enter (long arg0, long arg1, long arg2, long arg3, | 1238 | syscall_trace_enter (long arg0, long arg1, long arg2, long arg3, |
1260 | long arg4, long arg5, long arg6, long arg7, | 1239 | long arg4, long arg5, long arg6, long arg7, |
1261 | struct pt_regs regs) | 1240 | struct pt_regs regs) |
1262 | { | 1241 | { |
1263 | if (test_thread_flag(TIF_SYSCALL_TRACE) | 1242 | if (test_thread_flag(TIF_SYSCALL_TRACE)) |
1264 | && (current->ptrace & PT_PTRACED)) | 1243 | if (tracehook_report_syscall_entry(®s)) |
1265 | syscall_trace(); | 1244 | return -ENOSYS; |
1266 | 1245 | ||
1267 | /* copy user rbs to kernel rbs */ | 1246 | /* copy user rbs to kernel rbs */ |
1268 | if (test_thread_flag(TIF_RESTORE_RSE)) | 1247 | if (test_thread_flag(TIF_RESTORE_RSE)) |
@@ -1283,6 +1262,7 @@ syscall_trace_enter (long arg0, long arg1, long arg2, long arg3, | |||
1283 | audit_syscall_entry(arch, syscall, arg0, arg1, arg2, arg3); | 1262 | audit_syscall_entry(arch, syscall, arg0, arg1, arg2, arg3); |
1284 | } | 1263 | } |
1285 | 1264 | ||
1265 | return 0; | ||
1286 | } | 1266 | } |
1287 | 1267 | ||
1288 | /* "asmlinkage" so the input arguments are preserved... */ | 1268 | /* "asmlinkage" so the input arguments are preserved... */ |
@@ -1292,6 +1272,8 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3, | |||
1292 | long arg4, long arg5, long arg6, long arg7, | 1272 | long arg4, long arg5, long arg6, long arg7, |
1293 | struct pt_regs regs) | 1273 | struct pt_regs regs) |
1294 | { | 1274 | { |
1275 | int step; | ||
1276 | |||
1295 | if (unlikely(current->audit_context)) { | 1277 | if (unlikely(current->audit_context)) { |
1296 | int success = AUDITSC_RESULT(regs.r10); | 1278 | int success = AUDITSC_RESULT(regs.r10); |
1297 | long result = regs.r8; | 1279 | long result = regs.r8; |
@@ -1301,10 +1283,9 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3, | |||
1301 | audit_syscall_exit(success, result); | 1283 | audit_syscall_exit(success, result); |
1302 | } | 1284 | } |
1303 | 1285 | ||
1304 | if ((test_thread_flag(TIF_SYSCALL_TRACE) | 1286 | step = test_thread_flag(TIF_SINGLESTEP); |
1305 | || test_thread_flag(TIF_SINGLESTEP)) | 1287 | if (step || test_thread_flag(TIF_SYSCALL_TRACE)) |
1306 | && (current->ptrace & PT_PTRACED)) | 1288 | tracehook_report_syscall_exit(®s, step); |
1307 | syscall_trace(); | ||
1308 | 1289 | ||
1309 | /* copy user rbs to kernel rbs */ | 1290 | /* copy user rbs to kernel rbs */ |
1310 | if (test_thread_flag(TIF_RESTORE_RSE)) | 1291 | if (test_thread_flag(TIF_RESTORE_RSE)) |
@@ -1940,7 +1921,7 @@ gpregs_writeback(struct task_struct *target, | |||
1940 | { | 1921 | { |
1941 | if (test_and_set_tsk_thread_flag(target, TIF_RESTORE_RSE)) | 1922 | if (test_and_set_tsk_thread_flag(target, TIF_RESTORE_RSE)) |
1942 | return 0; | 1923 | return 0; |
1943 | tsk_set_notify_resume(target); | 1924 | set_notify_resume(target); |
1944 | return do_regset_call(do_gpregs_writeback, target, regset, 0, 0, | 1925 | return do_regset_call(do_gpregs_writeback, target, regset, 0, 0, |
1945 | NULL, NULL); | 1926 | NULL, NULL); |
1946 | } | 1927 | } |
@@ -2199,3 +2180,68 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *tsk) | |||
2199 | #endif | 2180 | #endif |
2200 | return &user_ia64_view; | 2181 | return &user_ia64_view; |
2201 | } | 2182 | } |
2183 | |||
2184 | struct syscall_get_set_args { | ||
2185 | unsigned int i; | ||
2186 | unsigned int n; | ||
2187 | unsigned long *args; | ||
2188 | struct pt_regs *regs; | ||
2189 | int rw; | ||
2190 | }; | ||
2191 | |||
2192 | static void syscall_get_set_args_cb(struct unw_frame_info *info, void *data) | ||
2193 | { | ||
2194 | struct syscall_get_set_args *args = data; | ||
2195 | struct pt_regs *pt = args->regs; | ||
2196 | unsigned long *krbs, cfm, ndirty; | ||
2197 | int i, count; | ||
2198 | |||
2199 | if (unw_unwind_to_user(info) < 0) | ||
2200 | return; | ||
2201 | |||
2202 | cfm = pt->cr_ifs; | ||
2203 | krbs = (unsigned long *)info->task + IA64_RBS_OFFSET/8; | ||
2204 | ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 19)); | ||
2205 | |||
2206 | count = 0; | ||
2207 | if (in_syscall(pt)) | ||
2208 | count = min_t(int, args->n, cfm & 0x7f); | ||
2209 | |||
2210 | for (i = 0; i < count; i++) { | ||
2211 | if (args->rw) | ||
2212 | *ia64_rse_skip_regs(krbs, ndirty + i + args->i) = | ||
2213 | args->args[i]; | ||
2214 | else | ||
2215 | args->args[i] = *ia64_rse_skip_regs(krbs, | ||
2216 | ndirty + i + args->i); | ||
2217 | } | ||
2218 | |||
2219 | if (!args->rw) { | ||
2220 | while (i < args->n) { | ||
2221 | args->args[i] = 0; | ||
2222 | i++; | ||
2223 | } | ||
2224 | } | ||
2225 | } | ||
2226 | |||
2227 | void ia64_syscall_get_set_arguments(struct task_struct *task, | ||
2228 | struct pt_regs *regs, unsigned int i, unsigned int n, | ||
2229 | unsigned long *args, int rw) | ||
2230 | { | ||
2231 | struct syscall_get_set_args data = { | ||
2232 | .i = i, | ||
2233 | .n = n, | ||
2234 | .args = args, | ||
2235 | .regs = regs, | ||
2236 | .rw = rw, | ||
2237 | }; | ||
2238 | |||
2239 | if (task == current) | ||
2240 | unw_init_running(syscall_get_set_args_cb, &data); | ||
2241 | else { | ||
2242 | struct unw_frame_info ufi; | ||
2243 | memset(&ufi, 0, sizeof(ufi)); | ||
2244 | unw_init_from_blocked_task(&ufi, task); | ||
2245 | syscall_get_set_args_cb(&ufi, &data); | ||
2246 | } | ||
2247 | } | ||
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c index 19c5a78636fc..e12500a9c443 100644 --- a/arch/ia64/kernel/signal.c +++ b/arch/ia64/kernel/signal.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/mm.h> | 12 | #include <linux/mm.h> |
13 | #include <linux/ptrace.h> | 13 | #include <linux/ptrace.h> |
14 | #include <linux/tracehook.h> | ||
14 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
15 | #include <linux/signal.h> | 16 | #include <linux/signal.h> |
16 | #include <linux/smp.h> | 17 | #include <linux/smp.h> |
@@ -439,6 +440,13 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse | |||
439 | sigaddset(¤t->blocked, sig); | 440 | sigaddset(¤t->blocked, sig); |
440 | recalc_sigpending(); | 441 | recalc_sigpending(); |
441 | spin_unlock_irq(¤t->sighand->siglock); | 442 | spin_unlock_irq(¤t->sighand->siglock); |
443 | |||
444 | /* | ||
445 | * Let tracing know that we've done the handler setup. | ||
446 | */ | ||
447 | tracehook_signal_handler(sig, info, ka, &scr->pt, | ||
448 | test_thread_flag(TIF_SINGLESTEP)); | ||
449 | |||
442 | return 1; | 450 | return 1; |
443 | } | 451 | } |
444 | 452 | ||