aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Simek <monstr@monstr.eu>2009-08-24 07:26:04 -0400
committerMichal Simek <monstr@monstr.eu>2009-09-22 04:00:45 -0400
commit235754834b6818e727d6b8e240c4ec7f79e2f457 (patch)
treea58160000a994c22f41abdbcb783dc076c9ae7a0
parentf97b4f7de4a4d92e578845d517660942e851ca4f (diff)
microblaze: Support ptrace syscall tracing.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com> Signed-off-by: Michal Simek <monstr@monstr.eu>
-rw-r--r--arch/microblaze/kernel/entry.S72
-rw-r--r--arch/microblaze/kernel/ptrace.c62
2 files changed, 122 insertions, 12 deletions
diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S
index c7353e79f4a2..acc1f05d1e2c 100644
--- a/arch/microblaze/kernel/entry.S
+++ b/arch/microblaze/kernel/entry.S
@@ -308,38 +308,69 @@ C_ENTRY(_user_exception):
308 swi r12, r1, PTO+PT_R0; 308 swi r12, r1, PTO+PT_R0;
309 tovirt(r1,r1) 309 tovirt(r1,r1)
310 310
311 la r15, r0, ret_from_trap-8
312/* where the trap should return need -8 to adjust for rtsd r15, 8*/ 311/* where the trap should return need -8 to adjust for rtsd r15, 8*/
313/* Jump to the appropriate function for the system call number in r12 312/* Jump to the appropriate function for the system call number in r12
314 * (r12 is not preserved), or return an error if r12 is not valid. The LP 313 * (r12 is not preserved), or return an error if r12 is not valid. The LP
315 * register should point to the location where 314 * register should point to the location where
316 * the called function should return. [note that MAKE_SYS_CALL uses label 1] */ 315 * the called function should return. [note that MAKE_SYS_CALL uses label 1] */
317 /* See if the system call number is valid. */ 316
317 # Step into virtual mode.
318 set_vms;
319 addik r11, r0, 3f
320 rtid r11, 0
321 nop
3223:
323 add r11, r0, CURRENT_TASK /* Get current task ptr into r11 */
324 lwi r11, r11, TS_THREAD_INFO /* get thread info */
325 lwi r11, r11, TI_FLAGS /* get flags in thread info */
326 andi r11, r11, _TIF_WORK_SYSCALL_MASK
327 beqi r11, 4f
328
329 addik r3, r0, -ENOSYS
330 swi r3, r1, PTO + PT_R3
331 brlid r15, do_syscall_trace_enter
332 addik r5, r1, PTO + PT_R0
333
334 # do_syscall_trace_enter returns the new syscall nr.
335 addk r12, r0, r3
336 lwi r5, r1, PTO+PT_R5;
337 lwi r6, r1, PTO+PT_R6;
338 lwi r7, r1, PTO+PT_R7;
339 lwi r8, r1, PTO+PT_R8;
340 lwi r9, r1, PTO+PT_R9;
341 lwi r10, r1, PTO+PT_R10;
3424:
343/* Jump to the appropriate function for the system call number in r12
344 * (r12 is not preserved), or return an error if r12 is not valid.
345 * The LP register should point to the location where the called function
346 * should return. [note that MAKE_SYS_CALL uses label 1] */
347 /* See if the system call number is valid */
318 addi r11, r12, -__NR_syscalls; 348 addi r11, r12, -__NR_syscalls;
319 bgei r11,1f; 349 bgei r11,5f;
320 /* Figure out which function to use for this system call. */ 350 /* Figure out which function to use for this system call. */
321 /* Note Microblaze barrel shift is optional, so don't rely on it */ 351 /* Note Microblaze barrel shift is optional, so don't rely on it */
322 add r12, r12, r12; /* convert num -> ptr */ 352 add r12, r12, r12; /* convert num -> ptr */
323 add r12, r12, r12; 353 add r12, r12, r12;
324 354
325 /* Trac syscalls and stored them to r0_ram */ 355 /* Trac syscalls and stored them to r0_ram */
326 lwi r3, r12, 0x400 + TOPHYS(r0_ram) 356 lwi r3, r12, 0x400 + r0_ram
327 addi r3, r3, 1 357 addi r3, r3, 1
328 swi r3, r12, 0x400 + TOPHYS(r0_ram) 358 swi r3, r12, 0x400 + r0_ram
359
360 # Find and jump into the syscall handler.
361 lwi r12, r12, sys_call_table
362 /* where the trap should return need -8 to adjust for rtsd r15, 8 */
363 la r15, r0, ret_from_trap-8
364 bra r12
329 365
330 lwi r12, r12, TOPHYS(sys_call_table); /* Function ptr */
331 /* Make the system call. to r12*/
332 set_vms;
333 rtid r12, 0;
334 nop;
335 /* The syscall number is invalid, return an error. */ 366 /* The syscall number is invalid, return an error. */
3361: VM_ON; /* RETURN() expects virtual mode*/ 3675:
337 addi r3, r0, -ENOSYS; 368 addi r3, r0, -ENOSYS;
338 rtsd r15,8; /* looks like a normal subroutine return */ 369 rtsd r15,8; /* looks like a normal subroutine return */
339 or r0, r0, r0 370 or r0, r0, r0
340 371
341 372
342/* Entry point used to return from a syscall/trap. */ 373/* Entry point used to return from a syscall/trap */
343/* We re-enable BIP bit before state restore */ 374/* We re-enable BIP bit before state restore */
344C_ENTRY(ret_from_trap): 375C_ENTRY(ret_from_trap):
345 set_bip; /* Ints masked for state restore*/ 376 set_bip; /* Ints masked for state restore*/
@@ -349,6 +380,23 @@ C_ENTRY(ret_from_trap):
349 380
350 /* We're returning to user mode, so check for various conditions that 381 /* We're returning to user mode, so check for various conditions that
351 * trigger rescheduling. */ 382 * trigger rescheduling. */
383 # FIXME: Restructure all these flag checks.
384 add r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */
385 lwi r11, r11, TS_THREAD_INFO; /* get thread info */
386 lwi r11, r11, TI_FLAGS; /* get flags in thread info */
387 andi r11, r11, _TIF_WORK_SYSCALL_MASK
388 beqi r11, 1f
389
390 swi r3, r1, PTO + PT_R3
391 swi r4, r1, PTO + PT_R4
392 brlid r15, do_syscall_trace_leave
393 addik r5, r1, PTO + PT_R0
394 lwi r3, r1, PTO + PT_R3
395 lwi r4, r1, PTO + PT_R4
3961:
397
398 /* We're returning to user mode, so check for various conditions that
399 * trigger rescheduling. */
352 /* Get current task ptr into r11 */ 400 /* Get current task ptr into r11 */
353 add r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */ 401 add r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */
354 lwi r11, r11, TS_THREAD_INFO; /* get thread info */ 402 lwi r11, r11, TS_THREAD_INFO; /* get thread info */
diff --git a/arch/microblaze/kernel/ptrace.c b/arch/microblaze/kernel/ptrace.c
index 53ff39af6a5c..4b3ac32754de 100644
--- a/arch/microblaze/kernel/ptrace.c
+++ b/arch/microblaze/kernel/ptrace.c
@@ -29,6 +29,10 @@
29#include <linux/sched.h> 29#include <linux/sched.h>
30#include <linux/ptrace.h> 30#include <linux/ptrace.h>
31#include <linux/signal.h> 31#include <linux/signal.h>
32#include <linux/elf.h>
33#include <linux/audit.h>
34#include <linux/seccomp.h>
35#include <linux/tracehook.h>
32 36
33#include <linux/errno.h> 37#include <linux/errno.h>
34#include <asm/processor.h> 38#include <asm/processor.h>
@@ -174,6 +178,64 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
174 return rval; 178 return rval;
175} 179}
176 180
181asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
182{
183 long ret = 0;
184
185 secure_computing(regs->r12);
186
187 if (test_thread_flag(TIF_SYSCALL_TRACE) &&
188 tracehook_report_syscall_entry(regs))
189 /*
190 * Tracing decided this syscall should not happen.
191 * We'll return a bogus call number to get an ENOSYS
192 * error, but leave the original number in regs->regs[0].
193 */
194 ret = -1L;
195
196 if (unlikely(current->audit_context))
197 audit_syscall_entry(EM_XILINX_MICROBLAZE, regs->r12,
198 regs->r5, regs->r6,
199 regs->r7, regs->r8);
200
201 return ret ?: regs->r12;
202}
203
204asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
205{
206 int step;
207
208 if (unlikely(current->audit_context))
209 audit_syscall_exit(AUDITSC_RESULT(regs->r3), regs->r3);
210
211 step = test_thread_flag(TIF_SINGLESTEP);
212 if (step || test_thread_flag(TIF_SYSCALL_TRACE))
213 tracehook_report_syscall_exit(regs, step);
214}
215
216#if 0
217static asmlinkage void syscall_trace(void)
218{
219 if (!test_thread_flag(TIF_SYSCALL_TRACE))
220 return;
221 if (!(current->ptrace & PT_PTRACED))
222 return;
223 /* The 0x80 provides a way for the tracing parent to distinguish
224 between a syscall stop and SIGTRAP delivery */
225 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
226 ? 0x80 : 0));
227 /*
228 * this isn't the same as continuing with a signal, but it will do
229 * for normal use. strace only continues with a signal if the
230 * stopping signal is not SIGTRAP. -brl
231 */
232 if (current->exit_code) {
233 send_sig(current->exit_code, current, 1);
234 current->exit_code = 0;
235 }
236}
237#endif
238
177void ptrace_disable(struct task_struct *child) 239void ptrace_disable(struct task_struct *child)
178{ 240{
179 /* nothing to do */ 241 /* nothing to do */