microblaze: Support ptrace syscall tracing.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com> Signed-off-by: Michal Simek <monstr@monstr.eu>
This commit is contained in:
parent
f97b4f7de4
commit
235754834b
@ -308,38 +308,69 @@ C_ENTRY(_user_exception):
|
||||
swi r12, r1, PTO+PT_R0;
|
||||
tovirt(r1,r1)
|
||||
|
||||
la r15, r0, ret_from_trap-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
|
||||
* (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. */
|
||||
|
||||
# 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;
|
||||
bgei r11,1f;
|
||||
bgei r11,5f;
|
||||
/* Figure out which function to use for this system call. */
|
||||
/* Note Microblaze barrel shift is optional, so don't rely on it */
|
||||
add r12, r12, r12; /* convert num -> ptr */
|
||||
add r12, r12, r12;
|
||||
|
||||
/* 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
|
||||
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. */
|
||||
1: VM_ON; /* RETURN() expects virtual mode*/
|
||||
5:
|
||||
addi r3, r0, -ENOSYS;
|
||||
rtsd r15,8; /* looks like a normal subroutine return */
|
||||
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 */
|
||||
C_ENTRY(ret_from_trap):
|
||||
set_bip; /* Ints masked for state restore*/
|
||||
@ -347,6 +378,23 @@ C_ENTRY(ret_from_trap):
|
||||
/* See if returning to kernel mode, if so, skip resched &c. */
|
||||
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
|
||||
* trigger rescheduling. */
|
||||
/* Get current task ptr into r11 */
|
||||
|
@ -29,6 +29,10 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ptrace.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 <asm/processor.h>
|
||||
@ -174,6 +178,64 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
||||
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)
|
||||
{
|
||||
/* nothing to do */
|
||||
|
Loading…
Reference in New Issue
Block a user