Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 23575483 authored by Michal Simek's avatar Michal Simek
Browse files

microblaze: Support ptrace syscall tracing.

parent f97b4f7d
Loading
Loading
Loading
Loading
+60 −12
Original line number Original line Diff line number Diff line
@@ -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):
/* 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 */
+62 −0
Original line number Original line Diff line number Diff line
@@ -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)
	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 */