powerpc/ftrace: Implement raw syscall tracepoints on PowerPC
This patch implements the raw syscall tracepoints on PowerPC and exports them for ftrace syscalls to use. To minimise reworking existing code, I slightly re-ordered the thread info flags such that the new TIF_SYSCALL_TRACEPOINT bit would still fit within the 16 bits of the andi. instruction's UI field. The instructions in question are in /arch/powerpc/kernel/entry_{32,64}.S to and the _TIF_SYSCALL_T_OR_A with the thread flags to see if system call tracing is enabled. In the case of 64bit PowerPC, arch_syscall_addr and arch_syscall_match_sym_name are overridden to allow ftrace syscalls to work given the unusual system call table structure and symbol names that start with a period. Signed-off-by: Ian Munsie <imunsie@au1.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
committed by
Benjamin Herrenschmidt
parent
3f5785ec31
commit
02424d8966
@@ -141,6 +141,7 @@ config PPC
|
|||||||
select GENERIC_IRQ_SHOW
|
select GENERIC_IRQ_SHOW
|
||||||
select GENERIC_IRQ_SHOW_LEVEL
|
select GENERIC_IRQ_SHOW_LEVEL
|
||||||
select HAVE_RCU_TABLE_FREE if SMP
|
select HAVE_RCU_TABLE_FREE if SMP
|
||||||
|
select HAVE_SYSCALL_TRACEPOINTS
|
||||||
|
|
||||||
config EARLY_PRINTK
|
config EARLY_PRINTK
|
||||||
bool
|
bool
|
||||||
|
@@ -60,4 +60,18 @@ struct dyn_arch_ftrace {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_FTRACE_SYSCALLS) && defined(CONFIG_PPC64) && !defined(__ASSEMBLY__)
|
||||||
|
#define ARCH_HAS_SYSCALL_MATCH_SYM_NAME
|
||||||
|
static inline bool arch_syscall_match_sym_name(const char *sym, const char *name)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Compare the symbol name with the system call name. Skip the .sys or .SyS
|
||||||
|
* prefix from the symbol name and the sys prefix from the system call name and
|
||||||
|
* just match the rest. This is only needed on ppc64 since symbol names on
|
||||||
|
* 32bit do not start with a period so the generic function will work.
|
||||||
|
*/
|
||||||
|
return !strcmp(sym + 4, name + 3);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_FTRACE_SYSCALLS && CONFIG_PPC64 && !__ASSEMBLY__ */
|
||||||
|
|
||||||
#endif /* _ASM_POWERPC_FTRACE */
|
#endif /* _ASM_POWERPC_FTRACE */
|
||||||
|
@@ -15,6 +15,11 @@
|
|||||||
|
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
|
||||||
|
/* ftrace syscalls requires exporting the sys_call_table */
|
||||||
|
#ifdef CONFIG_FTRACE_SYSCALLS
|
||||||
|
extern const unsigned long *sys_call_table;
|
||||||
|
#endif /* CONFIG_FTRACE_SYSCALLS */
|
||||||
|
|
||||||
static inline long syscall_get_nr(struct task_struct *task,
|
static inline long syscall_get_nr(struct task_struct *task,
|
||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
|
@@ -110,7 +110,8 @@ static inline struct thread_info *current_thread_info(void)
|
|||||||
#define TIF_NOERROR 12 /* Force successful syscall return */
|
#define TIF_NOERROR 12 /* Force successful syscall return */
|
||||||
#define TIF_NOTIFY_RESUME 13 /* callback before returning to user */
|
#define TIF_NOTIFY_RESUME 13 /* callback before returning to user */
|
||||||
#define TIF_FREEZE 14 /* Freezing for suspend */
|
#define TIF_FREEZE 14 /* Freezing for suspend */
|
||||||
#define TIF_RUNLATCH 15 /* Is the runlatch enabled? */
|
#define TIF_SYSCALL_TRACEPOINT 15 /* syscall tracepoint instrumentation */
|
||||||
|
#define TIF_RUNLATCH 16 /* Is the runlatch enabled? */
|
||||||
|
|
||||||
/* as above, but as bit values */
|
/* as above, but as bit values */
|
||||||
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
|
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
|
||||||
@@ -127,8 +128,10 @@ static inline struct thread_info *current_thread_info(void)
|
|||||||
#define _TIF_NOERROR (1<<TIF_NOERROR)
|
#define _TIF_NOERROR (1<<TIF_NOERROR)
|
||||||
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
|
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
|
||||||
#define _TIF_FREEZE (1<<TIF_FREEZE)
|
#define _TIF_FREEZE (1<<TIF_FREEZE)
|
||||||
|
#define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT)
|
||||||
#define _TIF_RUNLATCH (1<<TIF_RUNLATCH)
|
#define _TIF_RUNLATCH (1<<TIF_RUNLATCH)
|
||||||
#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
|
#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
|
||||||
|
_TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT)
|
||||||
|
|
||||||
#define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
|
#define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
|
||||||
_TIF_NOTIFY_RESUME)
|
_TIF_NOTIFY_RESUME)
|
||||||
|
@@ -109,6 +109,7 @@ obj-$(CONFIG_PPC_IO_WORKAROUNDS) += io-workarounds.o
|
|||||||
|
|
||||||
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
|
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
|
||||||
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
|
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
|
||||||
|
obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o
|
||||||
obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o
|
obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o
|
||||||
|
|
||||||
obj-$(CONFIG_PPC_PERF_CTRS) += perf_event.o
|
obj-$(CONFIG_PPC_PERF_CTRS) += perf_event.o
|
||||||
|
@@ -22,6 +22,7 @@
|
|||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/code-patching.h>
|
#include <asm/code-patching.h>
|
||||||
#include <asm/ftrace.h>
|
#include <asm/ftrace.h>
|
||||||
|
#include <asm/syscall.h>
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||||
@@ -600,3 +601,10 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
|
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
|
||||||
|
|
||||||
|
#if defined(CONFIG_FTRACE_SYSCALLS) && defined(CONFIG_PPC64)
|
||||||
|
unsigned long __init arch_syscall_addr(int nr)
|
||||||
|
{
|
||||||
|
return sys_call_table[nr*2];
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_FTRACE_SYSCALLS && CONFIG_PPC64 */
|
||||||
|
@@ -29,6 +29,7 @@
|
|||||||
#include <linux/signal.h>
|
#include <linux/signal.h>
|
||||||
#include <linux/seccomp.h>
|
#include <linux/seccomp.h>
|
||||||
#include <linux/audit.h>
|
#include <linux/audit.h>
|
||||||
|
#include <trace/syscall.h>
|
||||||
#ifdef CONFIG_PPC32
|
#ifdef CONFIG_PPC32
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -40,6 +41,9 @@
|
|||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
|
|
||||||
|
#define CREATE_TRACE_POINTS
|
||||||
|
#include <trace/events/syscalls.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The parameter save area on the stack is used to store arguments being passed
|
* The parameter save area on the stack is used to store arguments being passed
|
||||||
* to callee function and is located at fixed offset from stack pointer.
|
* to callee function and is located at fixed offset from stack pointer.
|
||||||
@@ -1710,6 +1714,9 @@ long do_syscall_trace_enter(struct pt_regs *regs)
|
|||||||
*/
|
*/
|
||||||
ret = -1L;
|
ret = -1L;
|
||||||
|
|
||||||
|
if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
|
||||||
|
trace_sys_enter(regs, regs->gpr[0]);
|
||||||
|
|
||||||
if (unlikely(current->audit_context)) {
|
if (unlikely(current->audit_context)) {
|
||||||
#ifdef CONFIG_PPC64
|
#ifdef CONFIG_PPC64
|
||||||
if (!is_32bit_task())
|
if (!is_32bit_task())
|
||||||
@@ -1738,6 +1745,9 @@ void do_syscall_trace_leave(struct pt_regs *regs)
|
|||||||
audit_syscall_exit((regs->ccr&0x10000000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
|
audit_syscall_exit((regs->ccr&0x10000000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
|
||||||
regs->result);
|
regs->result);
|
||||||
|
|
||||||
|
if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
|
||||||
|
trace_sys_exit(regs, regs->result);
|
||||||
|
|
||||||
step = test_thread_flag(TIF_SINGLESTEP);
|
step = test_thread_flag(TIF_SINGLESTEP);
|
||||||
if (step || test_thread_flag(TIF_SYSCALL_TRACE))
|
if (step || test_thread_flag(TIF_SYSCALL_TRACE))
|
||||||
tracehook_report_syscall_exit(regs, step);
|
tracehook_report_syscall_exit(regs, step);
|
||||||
|
Reference in New Issue
Block a user