Commit 23575483 authored by Michal Simek's avatar Michal Simek

microblaze: Support ptrace syscall tracing.

Signed-off-by: default avatarEdgar E. Iglesias <edgar.iglesias@gmail.com>
Signed-off-by: default avatarMichal Simek <monstr@monstr.eu>
parent f97b4f7d
...@@ -308,38 +308,69 @@ C_ENTRY(_user_exception): ...@@ -308,38 +308,69 @@ C_ENTRY(_user_exception):
swi r12, r1, PTO+PT_R0; swi r12, r1, PTO+PT_R0;
tovirt(r1,r1) tovirt(r1,r1)
la r15, r0, ret_from_trap-8
/* where the trap should return need -8 to adjust for rtsd r15, 8*/ /* where the trap should return need -8 to adjust for rtsd r15, 8*/
/* Jump to the appropriate function for the system call number in r12 /* Jump to the appropriate function for the system call number in r12
* (r12 is not preserved), or return an error if r12 is not valid. The LP * (r12 is not preserved), or return an error if r12 is not valid. The LP
* register should point to the location where * register should point to the location where
* the called function should return. [note that MAKE_SYS_CALL uses label 1] */ * the called function should return. [note that MAKE_SYS_CALL uses label 1] */
/* See if the system call number is valid. */
# Step into virtual mode.
set_vms;
addik r11, r0, 3f
rtid r11, 0
nop
3:
add r11, r0, CURRENT_TASK /* Get current task ptr into r11 */
lwi r11, r11, TS_THREAD_INFO /* get thread info */
lwi r11, r11, TI_FLAGS /* get flags in thread info */
andi r11, r11, _TIF_WORK_SYSCALL_MASK
beqi r11, 4f
addik r3, r0, -ENOSYS
swi r3, r1, PTO + PT_R3
brlid r15, do_syscall_trace_enter
addik r5, r1, PTO + PT_R0
# do_syscall_trace_enter returns the new syscall nr.
addk r12, r0, r3
lwi r5, r1, PTO+PT_R5;
lwi r6, r1, PTO+PT_R6;
lwi r7, r1, PTO+PT_R7;
lwi r8, r1, PTO+PT_R8;
lwi r9, r1, PTO+PT_R9;
lwi r10, r1, PTO+PT_R10;
4:
/* Jump to the appropriate function for the system call number in r12
* (r12 is not preserved), or return an error if r12 is not valid.
* The LP register should point to the location where the called function
* should return. [note that MAKE_SYS_CALL uses label 1] */
/* See if the system call number is valid */
addi r11, r12, -__NR_syscalls; addi r11, r12, -__NR_syscalls;
bgei r11,1f; bgei r11,5f;
/* Figure out which function to use for this system call. */ /* Figure out which function to use for this system call. */
/* Note Microblaze barrel shift is optional, so don't rely on it */ /* Note Microblaze barrel shift is optional, so don't rely on it */
add r12, r12, r12; /* convert num -> ptr */ add r12, r12, r12; /* convert num -> ptr */
add r12, r12, r12; add r12, r12, r12;
/* Trac syscalls and stored them to r0_ram */ /* Trac syscalls and stored them to r0_ram */
lwi r3, r12, 0x400 + TOPHYS(r0_ram) lwi r3, r12, 0x400 + r0_ram
addi r3, r3, 1 addi r3, r3, 1
swi r3, r12, 0x400 + TOPHYS(r0_ram) swi r3, r12, 0x400 + r0_ram
# Find and jump into the syscall handler.
lwi r12, r12, sys_call_table
/* where the trap should return need -8 to adjust for rtsd r15, 8 */
la r15, r0, ret_from_trap-8
bra r12
lwi r12, r12, TOPHYS(sys_call_table); /* Function ptr */
/* Make the system call. to r12*/
set_vms;
rtid r12, 0;
nop;
/* The syscall number is invalid, return an error. */ /* The syscall number is invalid, return an error. */
1: VM_ON; /* RETURN() expects virtual mode*/ 5:
addi r3, r0, -ENOSYS; addi r3, r0, -ENOSYS;
rtsd r15,8; /* looks like a normal subroutine return */ rtsd r15,8; /* looks like a normal subroutine return */
or r0, r0, r0 or r0, r0, r0
/* Entry point used to return from a syscall/trap. */ /* Entry point used to return from a syscall/trap */
/* We re-enable BIP bit before state restore */ /* We re-enable BIP bit before state restore */
C_ENTRY(ret_from_trap): C_ENTRY(ret_from_trap):
set_bip; /* Ints masked for state restore*/ set_bip; /* Ints masked for state restore*/
...@@ -347,6 +378,23 @@ C_ENTRY(ret_from_trap): ...@@ -347,6 +378,23 @@ C_ENTRY(ret_from_trap):
/* See if returning to kernel mode, if so, skip resched &c. */ /* See if returning to kernel mode, if so, skip resched &c. */
bnei r11, 2f; bnei r11, 2f;
/* We're returning to user mode, so check for various conditions that
* trigger rescheduling. */
# FIXME: Restructure all these flag checks.
add r11, r0, CURRENT_TASK; /* Get current task ptr into r11 */
lwi r11, r11, TS_THREAD_INFO; /* get thread info */
lwi r11, r11, TI_FLAGS; /* get flags in thread info */
andi r11, r11, _TIF_WORK_SYSCALL_MASK
beqi r11, 1f
swi r3, r1, PTO + PT_R3
swi r4, r1, PTO + PT_R4
brlid r15, do_syscall_trace_leave
addik r5, r1, PTO + PT_R0
lwi r3, r1, PTO + PT_R3
lwi r4, r1, PTO + PT_R4
1:
/* We're returning to user mode, so check for various conditions that /* We're returning to user mode, so check for various conditions that
* trigger rescheduling. */ * trigger rescheduling. */
/* Get current task ptr into r11 */ /* Get current task ptr into r11 */
......
...@@ -29,6 +29,10 @@ ...@@ -29,6 +29,10 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/elf.h>
#include <linux/audit.h>
#include <linux/seccomp.h>
#include <linux/tracehook.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <asm/processor.h> #include <asm/processor.h>
...@@ -174,6 +178,64 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -174,6 +178,64 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
return rval; return rval;
} }
asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
{
long ret = 0;
secure_computing(regs->r12);
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
tracehook_report_syscall_entry(regs))
/*
* Tracing decided this syscall should not happen.
* We'll return a bogus call number to get an ENOSYS
* error, but leave the original number in regs->regs[0].
*/
ret = -1L;
if (unlikely(current->audit_context))
audit_syscall_entry(EM_XILINX_MICROBLAZE, regs->r12,
regs->r5, regs->r6,
regs->r7, regs->r8);
return ret ?: regs->r12;
}
asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
{
int step;
if (unlikely(current->audit_context))
audit_syscall_exit(AUDITSC_RESULT(regs->r3), regs->r3);
step = test_thread_flag(TIF_SINGLESTEP);
if (step || test_thread_flag(TIF_SYSCALL_TRACE))
tracehook_report_syscall_exit(regs, step);
}
#if 0
static asmlinkage void syscall_trace(void)
{
if (!test_thread_flag(TIF_SYSCALL_TRACE))
return;
if (!(current->ptrace & PT_PTRACED))
return;
/* The 0x80 provides a way for the tracing parent to distinguish
between a syscall stop and SIGTRAP delivery */
ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
? 0x80 : 0));
/*
* this isn't the same as continuing with a signal, but it will do
* for normal use. strace only continues with a signal if the
* stopping signal is not SIGTRAP. -brl
*/
if (current->exit_code) {
send_sig(current->exit_code, current, 1);
current->exit_code = 0;
}
}
#endif
void ptrace_disable(struct task_struct *child) void ptrace_disable(struct task_struct *child)
{ {
/* nothing to do */ /* nothing to do */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment