linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [ftrace-bpf 1/5] add BPF_PROG_TYPE_FTRACE to bpf
@ 2017-11-12  7:28 yupeng0921
  2017-11-12  7:28 ` [ftrace-bpf 2/5] add bpf prog interface for ftrace yupeng0921
                   ` (6 more replies)
  0 siblings, 7 replies; 10+ messages in thread
From: yupeng0921 @ 2017-11-12  7:28 UTC (permalink / raw)
  To: linux-kernel; +Cc: ast, daniel, rostedt, mingo, yupeng0921

Add a new type BPF_PROG_TYPE_FTRACE to bpf, let bpf can be attached to
ftrace. Ftrace pass the function parameters to bpf prog, bpf prog
return 1 or 0 to indicate whether ftrace can trace this function. The
major propose is provide an accurate way to trigger function graph
trace. Changes in code:
1. add FTRACE_BPF_FILTER in kernel/trace/Kconfig. Let ftrace pass
function parameter to bpf need to modify architecture dependent code,
so this feature will only be enabled only when it is enabled in
Kconfig and the architecture support this feature. If an architecture
support this feature, it should define a macro whose name is
FTRACE_BPF_FILTER, e.g.:
So other code in kernel can check whether the macro FTRACE_BPF_FILTER
is defined to know whether this feature is really enabled.
2. add BPF_PROG_TYPE_FTRACE in bpf_prog_type
3. check kernel version when load BPF_PROG_TYPE_FTRACE bpf prog
4. define ftrace_prog_func_proto, the prog input is a struct
ftrace_regs type pointer, it is similar as pt_regs in kprobe, it
is an architecture dependent code, if an architecture doens't define
FTRACE_BPF_FILTER, use a fake ftrace_prog_func_proto.
5. add BPF_PROG_TYPE in bpf_types.h

Signed-off-by: yupeng0921@gmail.com
---
 include/linux/bpf_types.h |  3 +++
 include/uapi/linux/bpf.h  |  1 +
 kernel/bpf/syscall.c      |  8 +++++---
 kernel/trace/Kconfig      |  7 +++++++
 kernel/trace/bpf_trace.c  | 42 ++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 58 insertions(+), 3 deletions(-)

diff --git a/include/linux/bpf_types.h b/include/linux/bpf_types.h
index e114932..c828904 100644
--- a/include/linux/bpf_types.h
+++ b/include/linux/bpf_types.h
@@ -19,6 +19,9 @@ BPF_PROG_TYPE(BPF_PROG_TYPE_KPROBE, kprobe_prog_ops)
 BPF_PROG_TYPE(BPF_PROG_TYPE_TRACEPOINT, tracepoint_prog_ops)
 BPF_PROG_TYPE(BPF_PROG_TYPE_PERF_EVENT, perf_event_prog_ops)
 #endif
+#ifdef CONFIG_FTRACE_BPF_FILTER
+BPF_PROG_TYPE(BPF_PROG_TYPE_FTRACE, ftrace_prog_ops)
+#endif
 
 BPF_MAP_TYPE(BPF_MAP_TYPE_ARRAY, array_map_ops)
 BPF_MAP_TYPE(BPF_MAP_TYPE_PERCPU_ARRAY, percpu_array_map_ops)
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 30f2ce7..cced53c 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -118,6 +118,7 @@ enum bpf_prog_type {
 	BPF_PROG_TYPE_UNSPEC,
 	BPF_PROG_TYPE_SOCKET_FILTER,
 	BPF_PROG_TYPE_KPROBE,
+	BPF_PROG_TYPE_FTRACE,
 	BPF_PROG_TYPE_SCHED_CLS,
 	BPF_PROG_TYPE_SCHED_ACT,
 	BPF_PROG_TYPE_TRACEPOINT,
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 25d0749..f73f951 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -1001,9 +1001,11 @@ static int bpf_prog_load(union bpf_attr *attr)
 	if (attr->insn_cnt == 0 || attr->insn_cnt > BPF_MAXINSNS)
 		return -E2BIG;
 
-	if (type == BPF_PROG_TYPE_KPROBE &&
-	    attr->kern_version != LINUX_VERSION_CODE)
-		return -EINVAL;
+	if (type == BPF_PROG_TYPE_KPROBE || type == BPF_PROG_TYPE_FTRACE) {
+		if (attr->kern_version != LINUX_VERSION_CODE) {
+			return -EINVAL;
+		}
+	}
 
 	if (type != BPF_PROG_TYPE_SOCKET_FILTER &&
 	    type != BPF_PROG_TYPE_CGROUP_SKB &&
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index 434c840..dde0f01 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -702,6 +702,13 @@ config TRACING_EVENTS_GPIO
 	help
 	  Enable tracing events for gpio subsystem
 
+config FTRACE_BPF_FILTER
+	bool "filter function trace by bpf"
+	depends on FUNCTION_GRAPH_TRACER
+	default y
+	help
+	  Enable the kernel to triger ftrace by a bpf program
+
 endif # FTRACE
 
 endif # TRACING_SUPPORT
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index dc498b6..46e74d1 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -667,3 +667,45 @@ const struct bpf_verifier_ops perf_event_prog_ops = {
 	.is_valid_access	= pe_prog_is_valid_access,
 	.convert_ctx_access	= pe_prog_convert_ctx_access,
 };
+
+#ifdef FTRACE_BPF_FILTER
+static const struct bpf_func_proto *ftrace_prog_func_proto(
+	enum bpf_func_id func_id)
+{
+	switch (func_id) {
+	case BPF_FUNC_perf_event_output:
+		return &bpf_perf_event_output_proto;
+	case BPF_FUNC_get_stackid:
+		return &bpf_get_stackid_proto;
+	default:
+		return tracing_func_proto(func_id);
+	}
+}
+
+static bool ftrace_prog_is_valid_access(int off, int size,
+					enum bpf_access_type type,
+					struct bpf_insn_access_aux *info)
+{
+	if (off < 0 || off >= sizeof(struct ftrace_regs))
+		return false;
+	if (type != BPF_READ)
+		return false;
+	if (off % size != 0)
+		return false;
+	/*
+	 * Assertion for 32 bit to make sure last 8 byte access
+	 * (BPF_DW) to the last 4 byte member is disallowed.
+	 */
+	if (off + size > sizeof(struct ftrace_regs))
+		return false;
+
+	return true;
+}
+
+const struct bpf_verifier_ops ftrace_prog_ops = {
+	.get_func_proto  = ftrace_prog_func_proto,
+	.is_valid_access = ftrace_prog_is_valid_access,
+};
+#else
+const struct bpf_verifier_ops ftrace_prog_ops;
+#endif	/* FTRACE_BPF_FILTER */
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [ftrace-bpf 2/5] add bpf prog interface for ftrace
  2017-11-12  7:28 [ftrace-bpf 1/5] add BPF_PROG_TYPE_FTRACE to bpf yupeng0921
@ 2017-11-12  7:28 ` yupeng0921
  2017-11-12  7:28 ` [ftrace-bpf 3/5] add bpf prog filter for graph trace yupeng0921
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: yupeng0921 @ 2017-11-12  7:28 UTC (permalink / raw)
  To: linux-kernel; +Cc: ast, daniel, rostedt, mingo, yupeng0921

create ftrace_bpf_filter in tracefs, to set a bpf filter, write a bpf
prog file descriptor to this file, to clean the bpf filter, write
empty string to this file.

Signed-off-by: yupeng0921@gmail.com
---
 include/linux/ftrace.h |  3 ++
 kernel/trace/ftrace.c  | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++
 kernel/trace/trace.c   |  6 ++++
 kernel/trace/trace.h   |  4 +++
 4 files changed, 87 insertions(+)

diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index e54d257..9959435 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -769,6 +769,9 @@ static inline void ftrace_init(void) { }
 struct ftrace_graph_ent {
 	unsigned long func; /* Current function */
 	int depth;
+#ifdef FTRACE_BPF_FILTER
+	struct ftrace_regs *ctx;
+#endif
 } __packed;
 
 /*
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 8319e09..acb73f6 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -33,6 +33,7 @@
 #include <linux/list.h>
 #include <linux/hash.h>
 #include <linux/rcupdate.h>
+#include <linux/bpf.h>
 
 #include <trace/events/sched.h>
 
@@ -6415,10 +6416,83 @@ static const struct file_operations ftrace_pid_fops = {
 	.release	= ftrace_pid_release,
 };
 
+#ifdef FTRACE_BPF_FILTER
+static int
+ftrace_bpf_open(struct inode *inode, struct file *file)
+{
+	struct trace_array *tr = inode->i_private;
+
+	if (trace_array_get(tr) < 0)
+		return -ENODEV;
+
+	file->private_data = tr;
+
+	return 0;
+}
+
+static int
+ftrace_bpf_release(struct inode *inode, struct file *file)
+{
+	struct trace_array *tr = inode->i_private;
+
+	trace_array_put(tr);
+	return 0;
+}
+
+static ssize_t
+ftrace_bpf_write(struct file *filp, const char __user *ubuf,
+		   size_t cnt, loff_t *ppos)
+{
+	struct trace_array *tr = filp->private_data;
+	unsigned long prog_fd;
+	struct bpf_prog *prog, *old_prog;
+	ssize_t ret = 0;
+
+	old_prog = NULL;
+	mutex_lock(&ftrace_lock);
+	if (!cnt) {
+		old_prog = tr->prog;
+		goto out;
+	}
+	ret = kstrtoul_from_user(ubuf, cnt, 10, &prog_fd);
+	if (ret)
+		goto out;
+
+	prog = bpf_prog_get(prog_fd);
+	if (IS_ERR(prog)) {
+		ret = PTR_ERR(prog);
+		goto out;
+	}
+
+	old_prog = tr->prog;
+	rcu_assign_pointer(tr->prog, prog);
+
+ out:
+	mutex_unlock(&ftrace_lock);
+	if (old_prog) {
+		synchronize_rcu();
+		bpf_prog_put(old_prog);
+	}
+	if (ret)
+		return ret;
+
+	return cnt;
+}
+
+static const struct file_operations ftrace_bpf_fops = {
+	.open		= ftrace_bpf_open,
+	.write		= ftrace_bpf_write,
+	.release	= ftrace_bpf_release,
+};
+#endif	/* FTRACE_BPF_FILTER */
 void ftrace_init_tracefs(struct trace_array *tr, struct dentry *d_tracer)
 {
 	trace_create_file("set_ftrace_pid", 0644, d_tracer,
 			    tr, &ftrace_pid_fops);
+#ifdef FTRACE_BPF_FILTER
+	trace_create_file("set_ftrace_bpf", 0644, d_tracer,
+				tr, &ftrace_bpf_fops);
+#endif
 }
 
 void __init ftrace_init_tracefs_toplevel(struct trace_array *tr,
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 752e5da..09c75c7 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -7714,6 +7714,9 @@ static int instance_mkdir(const char *name)
 	raw_spin_lock_init(&tr->start_lock);
 
 	tr->max_lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
+#ifdef FTRACE_BPF_FILTER
+	tr->prog = NULL;
+#endif
 
 	tr->current_trace = &nop_trace;
 
@@ -8354,6 +8357,9 @@ __init static int tracer_alloc_buffers(void)
 	global_trace.current_trace = &nop_trace;
 
 	global_trace.max_lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
+#ifdef FTRACE_BPF_FILTER
+	global_trace.prog = NULL;
+#endif
 
 	ftrace_init_global_array_ops(&global_trace);
 
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 401b063..dedecd6 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -17,6 +17,7 @@
 #include <linux/compiler.h>
 #include <linux/trace_seq.h>
 #include <linux/glob.h>
+#include <linux/filter.h>
 
 #ifdef CONFIG_FTRACE_SYSCALLS
 #include <asm/unistd.h>		/* For NR_SYSCALLS	     */
@@ -261,6 +262,9 @@ struct trace_array {
 	struct list_head	events;
 	cpumask_var_t		tracing_cpumask; /* only trace on set CPUs */
 	int			ref;
+#ifdef FTRACE_BPF_FILTER
+	struct bpf_prog __rcu *prog;
+#endif
 #ifdef CONFIG_FUNCTION_TRACER
 	struct ftrace_ops	*ops;
 	struct trace_pid_list	__rcu *function_pids;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [ftrace-bpf 3/5] add bpf prog filter for graph trace
  2017-11-12  7:28 [ftrace-bpf 1/5] add BPF_PROG_TYPE_FTRACE to bpf yupeng0921
  2017-11-12  7:28 ` [ftrace-bpf 2/5] add bpf prog interface for ftrace yupeng0921
@ 2017-11-12  7:28 ` yupeng0921
  2017-11-12  7:28 ` [ftrace-bpf 4/5] enable bpf filter for graph trace in x86-64 arch yupeng0921
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: yupeng0921 @ 2017-11-12  7:28 UTC (permalink / raw)
  To: linux-kernel; +Cc: ast, daniel, rostedt, mingo, yupeng0921

When set a bpf prog through set_bpf_filter, graph trace will check
whether it should trace the function depend on the bpf prog return
value. It passes the parameters of the function to bpf prog, let bpf
prog determine whether this function should be traced. It only makes
sense if the user set only one function in set_graph_function, because
bpf prog is hard to distinguish different functions.

Signed-off-by: yupeng0921@gmail.com
---
 kernel/trace/trace_functions_graph.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index 23c0b0c..5894439b2 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -372,6 +372,24 @@ static inline int ftrace_graph_ignore_irqs(void)
 	return in_irq();
 }
 
+#ifdef FTRACE_BPF_FILTER
+static inline int ftrace_graph_bpf_filter(
+	struct trace_array *tr, struct ftrace_graph_ent *trace)
+{
+	struct bpf_prog *prog;
+	int ret = 1;
+
+	if (!ftrace_graph_addr(trace->func))
+		return ret;
+	rcu_read_lock();
+	prog = rcu_dereference(tr->prog);
+	if (prog)
+		ret = trace_call_bpf(prog, trace->ctx);
+	rcu_read_unlock();
+	return ret;
+}
+#endif
+
 int trace_graph_entry(struct ftrace_graph_ent *trace)
 {
 	struct trace_array *tr = graph_array;
@@ -391,6 +409,11 @@ int trace_graph_entry(struct ftrace_graph_ent *trace)
 	if (ftrace_graph_ignore_irqs())
 		return 0;
 
+#ifdef FTRACE_BPF_FILTER
+	if (!ftrace_graph_bpf_filter(tr, trace))
+		return 0;
+#endif
+
 	/*
 	 * Do not trace a function if it's filtered by set_graph_notrace.
 	 * Make the index of ret stack negative to indicate that it should
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [ftrace-bpf 4/5] enable bpf filter for graph trace in x86-64 arch
  2017-11-12  7:28 [ftrace-bpf 1/5] add BPF_PROG_TYPE_FTRACE to bpf yupeng0921
  2017-11-12  7:28 ` [ftrace-bpf 2/5] add bpf prog interface for ftrace yupeng0921
  2017-11-12  7:28 ` [ftrace-bpf 3/5] add bpf prog filter for graph trace yupeng0921
@ 2017-11-12  7:28 ` yupeng0921
  2017-11-12  7:28 ` [ftrace-bpf 5/5] add BPF_PROG_TYPE_FTRACE support for samples/bpf yupeng0921
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: yupeng0921 @ 2017-11-12  7:28 UTC (permalink / raw)
  To: linux-kernel; +Cc: ast, daniel, rostedt, mingo, yupeng0921

define FTRACE_BPF_FILTER if CONFIG_FTRACE_BPF_FILTER is enabled,
create struct ftrace_regs, struct ftrace_regs is similar as pt_regs in
kprobe, but ftrace doesn't save all context, only caller save
registers, so use ftrace_regs to store these registers.

Signed-off-by: yupeng0921@gmail.com
---
 arch/x86/include/asm/ftrace.h | 22 ++++++++++++++++++++++
 arch/x86/kernel/ftrace.c      | 15 +++++++++++++++
 arch/x86/kernel/ftrace_64.S   |  1 +
 3 files changed, 38 insertions(+)

diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h
index 09ad885..9a5bffc 100644
--- a/arch/x86/include/asm/ftrace.h
+++ b/arch/x86/include/asm/ftrace.h
@@ -11,6 +11,28 @@
 #endif
 #define MCOUNT_INSN_SIZE	5 /* sizeof mcount call */
 
+#ifndef __i386__
+#ifdef CONFIG_FTRACE_BPF_FILTER
+#define FTRACE_BPF_FILTER
+#ifndef __ASSEMBLY__
+/*
+ * The order is exactly same as
+ * arch/x86/entry/calling.h
+ */
+struct ftrace_regs {
+	unsigned long r9;
+	unsigned long r8;
+	unsigned long rax;
+	unsigned long rcx;
+	unsigned long rdx;
+	unsigned long rsi;
+	unsigned long rdi;
+};
+#endif
+#endif	/* CONFIG_FTRACE_BPF_FILTER */
+
+#endif
+
 #ifdef CONFIG_DYNAMIC_FTRACE
 #define ARCH_SUPPORTS_FTRACE_OPS 1
 #endif
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index 01ebcb6..d190534 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -896,8 +896,14 @@ static void *addr_from_call(void *ptr)
 	return ptr + MCOUNT_INSN_SIZE + calc.offset;
 }
 
+#ifdef FTRACE_BPF_FILTER
+void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
+			   unsigned long frame_pointer,
+			   struct ftrace_regs *ctx);
+#else
 void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
 			   unsigned long frame_pointer);
+#endif
 
 /*
  * If the ops->trampoline was not allocated, then it probably
@@ -989,8 +995,14 @@ int ftrace_disable_ftrace_graph_caller(void)
  * Hook the return address and push it in the stack of return addrs
  * in current thread info.
  */
+#ifdef FTRACE_BPF_FILTER
+void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
+			   unsigned long frame_pointer,
+			   struct ftrace_regs *ctx)
+#else
 void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
 			   unsigned long frame_pointer)
+#endif
 {
 	unsigned long old;
 	int faulted;
@@ -1048,6 +1060,9 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
 
 	trace.func = self_addr;
 	trace.depth = current->curr_ret_stack + 1;
+#ifdef FTRACE_BPF_FILTER
+	trace.ctx = ctx;
+#endif
 
 	/* Only trace if the calling function expects to */
 	if (!ftrace_graph_entry(&trace)) {
diff --git a/arch/x86/kernel/ftrace_64.S b/arch/x86/kernel/ftrace_64.S
index c832291..5e51b93 100644
--- a/arch/x86/kernel/ftrace_64.S
+++ b/arch/x86/kernel/ftrace_64.S
@@ -108,6 +108,7 @@ EXPORT_SYMBOL(mcount)
 	movq MCOUNT_REG_SIZE-8(%rsp), %rdx
 	movq %rdx, RBP(%rsp)
 
+	leaq R9(%rsp), %rcx
 	/* Copy the parent address into %rsi (second parameter) */
 #ifdef CC_USING_FENTRY
 	movq MCOUNT_REG_SIZE+8+\added(%rsp), %rsi
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [ftrace-bpf 5/5] add BPF_PROG_TYPE_FTRACE support for samples/bpf
  2017-11-12  7:28 [ftrace-bpf 1/5] add BPF_PROG_TYPE_FTRACE to bpf yupeng0921
                   ` (2 preceding siblings ...)
  2017-11-12  7:28 ` [ftrace-bpf 4/5] enable bpf filter for graph trace in x86-64 arch yupeng0921
@ 2017-11-12  7:28 ` yupeng0921
  2017-11-13  1:02 ` [ftrace-bpf 1/5] add BPF_PROG_TYPE_FTRACE to bpf Alexei Starovoitov
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: yupeng0921 @ 2017-11-12  7:28 UTC (permalink / raw)
  To: linux-kernel; +Cc: ast, daniel, rostedt, mingo, yupeng0921

let bpf_load.c write prog file descriptor to
/sys/kernel/debug/tracing/set_ftrace_bpf if the prog sector name is
"ftrace". Add test code ftrace_graph_kern.c and ftrace_graph_user.c in
samples/bpf directory. ftrace_graph_kern.c works on the ip_rcv
function, return 1 if the packet is received by lo
device. ftrace_graph_user.c load the ftrace_graph_kern.c to kernel,
and let the graph function tracer only trace ip_rcv function, and
check the packet by bpf prog.

Signed-off-by: yupeng0921@gmail.com
---
 samples/bpf/Makefile                      |  4 +++
 samples/bpf/bpf_load.c                    | 24 +++++++++++++++++
 samples/bpf/ftrace_graph_kern.c           | 43 +++++++++++++++++++++++++++++
 samples/bpf/ftrace_graph_user.c           | 45 +++++++++++++++++++++++++++++++
 tools/include/uapi/linux/bpf.h            |  1 +
 tools/testing/selftests/bpf/bpf_helpers.h |  7 +++++
 6 files changed, 124 insertions(+)
 create mode 100644 samples/bpf/ftrace_graph_kern.c
 create mode 100644 samples/bpf/ftrace_graph_user.c

diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index 9b4a66e..e7e4010 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -42,6 +42,7 @@ hostprogs-y += xdp_redirect
 hostprogs-y += xdp_redirect_map
 hostprogs-y += xdp_monitor
 hostprogs-y += syscall_tp
+hostprogs-y += ftrace_graph
 
 # Libbpf dependencies
 LIBBPF := ../../tools/lib/bpf/bpf.o
@@ -87,6 +88,7 @@ xdp_redirect-objs := bpf_load.o $(LIBBPF) xdp_redirect_user.o
 xdp_redirect_map-objs := bpf_load.o $(LIBBPF) xdp_redirect_map_user.o
 xdp_monitor-objs := bpf_load.o $(LIBBPF) xdp_monitor_user.o
 syscall_tp-objs := bpf_load.o $(LIBBPF) syscall_tp_user.o
+ftrace_graph-objs := bpf_load.o $(LIBBPF) ftrace_graph_user.o
 
 # Tell kbuild to always build the programs
 always := $(hostprogs-y)
@@ -132,6 +134,7 @@ always += xdp_redirect_kern.o
 always += xdp_redirect_map_kern.o
 always += xdp_monitor_kern.o
 always += syscall_tp_kern.o
+always += ftrace_graph_kern.o
 
 HOSTCFLAGS += -I$(objtree)/usr/include
 HOSTCFLAGS += -I$(srctree)/tools/lib/
@@ -172,6 +175,7 @@ HOSTLOADLIBES_xdp_redirect += -lelf
 HOSTLOADLIBES_xdp_redirect_map += -lelf
 HOSTLOADLIBES_xdp_monitor += -lelf
 HOSTLOADLIBES_syscall_tp += -lelf
+HOSTLOADLIBES_ftrace_graph += -lelf
 
 # Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline:
 #  make samples/bpf/ LLC=~/git/llvm/build/bin/llc CLANG=~/git/llvm/build/bin/clang
diff --git a/samples/bpf/bpf_load.c b/samples/bpf/bpf_load.c
index 2325d7a..b9e9c14 100644
--- a/samples/bpf/bpf_load.c
+++ b/samples/bpf/bpf_load.c
@@ -61,6 +61,7 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
 	bool is_kprobe = strncmp(event, "kprobe/", 7) == 0;
 	bool is_kretprobe = strncmp(event, "kretprobe/", 10) == 0;
 	bool is_tracepoint = strncmp(event, "tracepoint/", 11) == 0;
+	bool is_ftrace = strncmp(event, "ftrace", 6) == 0;
 	bool is_xdp = strncmp(event, "xdp", 3) == 0;
 	bool is_perf_event = strncmp(event, "perf_event", 10) == 0;
 	bool is_cgroup_skb = strncmp(event, "cgroup/skb", 10) == 0;
@@ -71,6 +72,7 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
 	enum bpf_prog_type prog_type;
 	char buf[256];
 	int fd, efd, err, id;
+	int cnt;
 	struct perf_event_attr attr = {};
 
 	attr.type = PERF_TYPE_TRACEPOINT;
@@ -84,6 +86,8 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
 		prog_type = BPF_PROG_TYPE_KPROBE;
 	} else if (is_tracepoint) {
 		prog_type = BPF_PROG_TYPE_TRACEPOINT;
+	} else if (is_ftrace) {
+		prog_type = BPF_PROG_TYPE_FTRACE;
 	} else if (is_xdp) {
 		prog_type = BPF_PROG_TYPE_XDP;
 	} else if (is_perf_event) {
@@ -128,6 +132,25 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size)
 		return populate_prog_array(event, fd);
 	}
 
+	if (is_ftrace) {
+		cnt = snprintf(buf, sizeof(buf), "%d", fd);
+		efd = open("/sys/kernel/debug/tracing/set_ftrace_bpf",
+				   O_WRONLY, 0);
+		if (efd < 0) {
+			printf("open set_ftrace_bpf failed %s\n",
+				   strerror(errno));
+			return -1;
+		}
+		err = write(efd, buf, cnt);
+		if (err < 0 || err > cnt) {
+			printf("write set_ftrace_bpf failed %s\n",
+				   strerror(errno));
+			return -1;
+		}
+		close(efd);
+		return 0;
+	}
+
 	if (is_kprobe || is_kretprobe) {
 		if (is_kprobe)
 			event += 7;
@@ -572,6 +595,7 @@ static int do_load_bpf_file(const char *path, fixup_map_cb fixup_map)
 		if (memcmp(shname, "kprobe/", 7) == 0 ||
 		    memcmp(shname, "kretprobe/", 10) == 0 ||
 		    memcmp(shname, "tracepoint/", 11) == 0 ||
+			memcmp(shname, "ftrace", 6) == 0 ||
 		    memcmp(shname, "xdp", 3) == 0 ||
 		    memcmp(shname, "perf_event", 10) == 0 ||
 		    memcmp(shname, "socket", 6) == 0 ||
diff --git a/samples/bpf/ftrace_graph_kern.c b/samples/bpf/ftrace_graph_kern.c
new file mode 100644
index 0000000..f4d172d
--- /dev/null
+++ b/samples/bpf/ftrace_graph_kern.c
@@ -0,0 +1,43 @@
+/* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ */
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <uapi/linux/bpf.h>
+#include <linux/version.h>
+#include <linux/ftrace.h>
+#include "bpf_helpers.h"
+
+#define _(P) ({typeof(P) val = 0; bpf_probe_read(&val, sizeof(val), &P); val; })
+
+/* kprobe is NOT a stable ABI
+ * kernel functions can be removed, renamed or completely change semantics.
+ * Number of arguments and their positions can change, etc.
+ * In such case this bpf+kprobe example will no longer be meaningful
+ */
+SEC("ftrace")
+int bpf_prog1(struct ftrace_regs *ctx)
+{
+	char devname[IFNAMSIZ];
+	struct net_device *dev;
+	struct sk_buff *skb;
+
+	skb = (struct sk_buff *) FTRACE_REGS_PARAM1(ctx);
+	dev = _(skb->dev);
+
+	bpf_probe_read(devname, sizeof(devname), dev->name);
+	if (devname[0] == 'l' && devname[1] == 'o') {
+		char fmt[] = "track dev: %s";
+
+		bpf_trace_printk(fmt, sizeof(fmt), devname);
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+char _license[] SEC("license") = "GPL";
+u32 _version SEC("version") = LINUX_VERSION_CODE;
diff --git a/samples/bpf/ftrace_graph_user.c b/samples/bpf/ftrace_graph_user.c
new file mode 100644
index 0000000..5b2a085
--- /dev/null
+++ b/samples/bpf/ftrace_graph_user.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <linux/bpf.h>
+#include <unistd.h>
+#include "libbpf.h"
+#include "bpf_load.h"
+
+int main(int ac, char **argv)
+{
+	FILE *f;
+	char filename[256];
+	int ret;
+
+	snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
+
+	if (load_bpf_file(filename)) {
+		printf("%s", bpf_log_buf);
+		return 1;
+	}
+
+	ret = system(
+		"echo ip_rcv > /sys/kernel/debug/tracing/set_graph_function");
+	if (ret != 0) {
+		printf("set_graph_function failed\n");
+		return 1;
+	}
+	ret = system(
+		"echo function_graph > /sys/kernel/debug/tracing/current_tracer");
+	if (ret != 0) {
+		printf("set current_tracer faield\n");
+		return 1;
+	}
+	ret = system(
+		"echo 1 > /sys/kernel/debug/tracing/tracing_on");
+	if (ret != 0) {
+		printf("tracing_on failed\n");
+		return 1;
+	}
+	f = popen("nc localhost 9001", "r");
+	(void) f;
+
+	read_trace_pipe();
+
+	return 0;
+}
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 30f2ce7..cced53c 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -118,6 +118,7 @@ enum bpf_prog_type {
 	BPF_PROG_TYPE_UNSPEC,
 	BPF_PROG_TYPE_SOCKET_FILTER,
 	BPF_PROG_TYPE_KPROBE,
+	BPF_PROG_TYPE_FTRACE,
 	BPF_PROG_TYPE_SCHED_CLS,
 	BPF_PROG_TYPE_SCHED_ACT,
 	BPF_PROG_TYPE_TRACEPOINT,
diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h
index 50353c1..dcbc209 100644
--- a/tools/testing/selftests/bpf/bpf_helpers.h
+++ b/tools/testing/selftests/bpf/bpf_helpers.h
@@ -123,6 +123,13 @@ static int (*bpf_skb_change_head)(void *, int len, int flags) =
 #define PT_REGS_SP(x) ((x)->sp)
 #define PT_REGS_IP(x) ((x)->ip)
 
+#define FTRACE_REGS_PARAM1(x) ((x)->rdi)
+#define FTRACE_REGS_PARAM2(x) ((x)->rsi)
+#define FTRACE_REGS_PARAM3(x) ((x)->rdx)
+#define FTRACE_REGS_PARAM4(x) ((x)->rcx)
+#define FTRACE_REGS_PARAM5(x) ((x)->r8)
+#define FTRACE_REGS_PARAM6(x) ((x)->r9)
+
 #elif defined(__s390x__)
 
 #define PT_REGS_PARM1(x) ((x)->gprs[2])
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [ftrace-bpf 1/5] add BPF_PROG_TYPE_FTRACE to bpf
  2017-11-12  7:28 [ftrace-bpf 1/5] add BPF_PROG_TYPE_FTRACE to bpf yupeng0921
                   ` (3 preceding siblings ...)
  2017-11-12  7:28 ` [ftrace-bpf 5/5] add BPF_PROG_TYPE_FTRACE support for samples/bpf yupeng0921
@ 2017-11-13  1:02 ` Alexei Starovoitov
  2017-11-13  8:06   ` peng yu
  2017-11-14 17:47 ` kbuild test robot
  2017-11-14 21:01 ` kbuild test robot
  6 siblings, 1 reply; 10+ messages in thread
From: Alexei Starovoitov @ 2017-11-13  1:02 UTC (permalink / raw)
  To: yupeng0921
  Cc: linux-kernel, ast, daniel, rostedt, mingo, David S. Miller, netdev

On Sun, Nov 12, 2017 at 07:28:24AM +0000, yupeng0921@gmail.com wrote:
> Add a new type BPF_PROG_TYPE_FTRACE to bpf, let bpf can be attached to
> ftrace. Ftrace pass the function parameters to bpf prog, bpf prog
> return 1 or 0 to indicate whether ftrace can trace this function. The
> major propose is provide an accurate way to trigger function graph
> trace. Changes in code:
> 1. add FTRACE_BPF_FILTER in kernel/trace/Kconfig. Let ftrace pass
> function parameter to bpf need to modify architecture dependent code,
> so this feature will only be enabled only when it is enabled in
> Kconfig and the architecture support this feature. If an architecture
> support this feature, it should define a macro whose name is
> FTRACE_BPF_FILTER, e.g.:
> So other code in kernel can check whether the macro FTRACE_BPF_FILTER
> is defined to know whether this feature is really enabled.
> 2. add BPF_PROG_TYPE_FTRACE in bpf_prog_type
> 3. check kernel version when load BPF_PROG_TYPE_FTRACE bpf prog
> 4. define ftrace_prog_func_proto, the prog input is a struct
> ftrace_regs type pointer, it is similar as pt_regs in kprobe, it
> is an architecture dependent code, if an architecture doens't define
> FTRACE_BPF_FILTER, use a fake ftrace_prog_func_proto.
> 5. add BPF_PROG_TYPE in bpf_types.h
> 
> Signed-off-by: yupeng0921@gmail.com

In general I like the bigger concept of adding bpf filtering to ftrace,
but there are a lot of fundamental issues with this patch set.

1. anything bpf related has to go via net-next tree.

> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -118,6 +118,7 @@ enum bpf_prog_type {
>  	BPF_PROG_TYPE_UNSPEC,
>  	BPF_PROG_TYPE_SOCKET_FILTER,
>  	BPF_PROG_TYPE_KPROBE,
> +	BPF_PROG_TYPE_FTRACE,
>  	BPF_PROG_TYPE_SCHED_CLS,

2.
this obviously breaks ABI. New types can only be added to the end.

> +static bool ftrace_prog_is_valid_access(int off, int size,
> +					enum bpf_access_type type,
> +					struct bpf_insn_access_aux *info)
> +{
> +	if (off < 0 || off >= sizeof(struct ftrace_regs))
> +		return false;

3.
this won't even compile, since ftrace_regs is only added in the patch 4.

Since bpf program will see ftrace_regs as an input it becomes
abi, so has to be defined in uapi/linux/bpf_ftrace.h or similar.
We need to think through how to make it generic across archs
instead of defining ftrace_regs for each arch.

4.
the patch 2/3 takes an approach of passing FD integer value in text form
to the kernel. That approach was discussed years ago and rejected.
It has to use binary interface like perf_event + ioctl.
See RFC patches where we're extending perf_event_open syscall to
support binary access to kprobe/uprobe.
imo binary interface to ftrace is pre-requisite to ftrace+bpf work.
We've had too many issues with text based kprobe api to repeat
the same mistake here.

5.
patch 4 hacks save_mcount_regs asm to pass ctx pointer in %rcx
whereas it's only used in ftrace_graph_caller which doesn't seem right.
It points out to another issue that such ftrace+bpf integration
is only done for ftrace_graph_caller without extensibility in mind.
If we do ftrace+bpf I'd rather see generic framework that applies
to all of ftrace instead of single feature of it.

6.
copyright line copy-pasted incorrectly.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [ftrace-bpf 1/5] add BPF_PROG_TYPE_FTRACE to bpf
  2017-11-13  1:02 ` [ftrace-bpf 1/5] add BPF_PROG_TYPE_FTRACE to bpf Alexei Starovoitov
@ 2017-11-13  8:06   ` peng yu
  2017-11-17 23:48     ` Alexei Starovoitov
  0 siblings, 1 reply; 10+ messages in thread
From: peng yu @ 2017-11-13  8:06 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: linux-kernel, ast, daniel, rostedt, mingo, David S. Miller, netdev

> 1. anything bpf related has to go via net-next tree.
I found there is a net-next git repo:
https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
I will use this repo for the further bpf-ftrace patch set.

> 2.
> this obviously breaks ABI. New types can only be added to the end.
Sure, I will add the new type at the end.

> 3.
> this won't even compile, since ftrace_regs is only added in the patch 4.
It could compile, as the ftrace_regs related code is inside the
"#ifdef FTRACE_BPF_FILTER" macro, if this macro is not defined, no
ftrace_regs related code would be compiled.


> Since bpf program will see ftrace_regs as an input it becomes
> abi, so has to be defined in uapi/linux/bpf_ftrace.h or similar.
> We need to think through how to make it generic across archs
> instead of defining ftrace_regs for each arch.
I'm not sure whether I'm fully understand your meaning. Like kprobe,
the ftrace-bpf need to get a function's parameters and check them. So
it won't be abi stable, and it should depend on architecture
implement. I can create a header file like uapi/linux/bpf_ftrace.h,
but I noticed that kprobe doesn't have such a header file, if I'm
wrong, please let me know. And about make it generic across archs, I
know kprobe use pt_regs as parameter, the pt_regs is defined on each
arch, so I can't see how bpf-ftrace can get a generic interface across
archs if it need to check function's parameters. If I misunderstand
anything, please let me know.

> 4.
> the patch 2/3 takes an approach of passing FD integer value in text form
> to the kernel. That approach was discussed years ago and rejected.
> It has to use binary interface like perf_event + ioctl.
> See RFC patches where we're extending perf_event_open syscall to
> support binary access to kprobe/uprobe.
> imo binary interface to ftrace is pre-requisite to ftrace+bpf work.
> We've had too many issues with text based kprobe api to repeat
> the same mistake here.
I notice the kprobe-bpf prog is set through the PERF_EVENT_IOC_SET_BPF
ioctl, I may try to see whether I can reuse this interface, or if it
is not suitable, I will try to define a new binary interface.

> 5.
> patch 4 hacks save_mcount_regs asm to pass ctx pointer in %rcx
> whereas it's only used in ftrace_graph_caller which doesn't seem right.
> It points out to another issue that such ftrace+bpf integration
> is only done for ftrace_graph_caller without extensibility in mind.
> If we do ftrace+bpf I'd rather see generic framework that applies
> to all of ftrace instead of single feature of it.
It is a hard problem. The ftrace framework has lots of tracers,
function tracer and function graph tracer use the 'gcc -pg' directly,
other tracers use tracepoint, I should spend more time to find a
suitable solution.


> 6.
> copyright line copy-pasted incorrectly.
I will fix it.

Summary:
The question 1,2 and 6 are easy to fix. About question 4, I need to do
more research, it shouldn't be very hard. About question 3 and 5, both

2017-11-12 17:02 GMT-08:00 Alexei Starovoitov <alexei.starovoitov@gmail.com>:
> On Sun, Nov 12, 2017 at 07:28:24AM +0000, yupeng0921@gmail.com wrote:
>> Add a new type BPF_PROG_TYPE_FTRACE to bpf, let bpf can be attached to
>> ftrace. Ftrace pass the function parameters to bpf prog, bpf prog
>> return 1 or 0 to indicate whether ftrace can trace this function. The
>> major propose is provide an accurate way to trigger function graph
>> trace. Changes in code:
>> 1. add FTRACE_BPF_FILTER in kernel/trace/Kconfig. Let ftrace pass
>> function parameter to bpf need to modify architecture dependent code,
>> so this feature will only be enabled only when it is enabled in
>> Kconfig and the architecture support this feature. If an architecture
>> support this feature, it should define a macro whose name is
>> FTRACE_BPF_FILTER, e.g.:
>> So other code in kernel can check whether the macro FTRACE_BPF_FILTER
>> is defined to know whether this feature is really enabled.
>> 2. add BPF_PROG_TYPE_FTRACE in bpf_prog_type
>> 3. check kernel version when load BPF_PROG_TYPE_FTRACE bpf prog
>> 4. define ftrace_prog_func_proto, the prog input is a struct
>> ftrace_regs type pointer, it is similar as pt_regs in kprobe, it
>> is an architecture dependent code, if an architecture doens't define
>> FTRACE_BPF_FILTER, use a fake ftrace_prog_func_proto.
>> 5. add BPF_PROG_TYPE in bpf_types.h
>>
>> Signed-off-by: yupeng0921@gmail.com
>
> In general I like the bigger concept of adding bpf filtering to ftrace,
> but there are a lot of fundamental issues with this patch set.
>
> 1. anything bpf related has to go via net-next tree.
>
>> --- a/include/uapi/linux/bpf.h
>> +++ b/include/uapi/linux/bpf.h
>> @@ -118,6 +118,7 @@ enum bpf_prog_type {
>>       BPF_PROG_TYPE_UNSPEC,
>>       BPF_PROG_TYPE_SOCKET_FILTER,
>>       BPF_PROG_TYPE_KPROBE,
>> +     BPF_PROG_TYPE_FTRACE,
>>       BPF_PROG_TYPE_SCHED_CLS,
>
> 2.
> this obviously breaks ABI. New types can only be added to the end.
>
>> +static bool ftrace_prog_is_valid_access(int off, int size,
>> +                                     enum bpf_access_type type,
>> +                                     struct bpf_insn_access_aux *info)
>> +{
>> +     if (off < 0 || off >= sizeof(struct ftrace_regs))
>> +             return false;
>
> 3.
> this won't even compile, since ftrace_regs is only added in the patch 4.
>
> Since bpf program will see ftrace_regs as an input it becomes
> abi, so has to be defined in uapi/linux/bpf_ftrace.h or similar.
> We need to think through how to make it generic across archs
> instead of defining ftrace_regs for each arch.
>
> 4.
> the patch 2/3 takes an approach of passing FD integer value in text form
> to the kernel. That approach was discussed years ago and rejected.
> It has to use binary interface like perf_event + ioctl.
> See RFC patches where we're extending perf_event_open syscall to
> support binary access to kprobe/uprobe.
> imo binary interface to ftrace is pre-requisite to ftrace+bpf work.
> We've had too many issues with text based kprobe api to repeat
> the same mistake here.
>
> 5.
> patch 4 hacks save_mcount_regs asm to pass ctx pointer in %rcx
> whereas it's only used in ftrace_graph_caller which doesn't seem right.
> It points out to another issue that such ftrace+bpf integration
> is only done for ftrace_graph_caller without extensibility in mind.
> If we do ftrace+bpf I'd rather see generic framework that applies
> to all of ftrace instead of single feature of it.
>
> 6.
> copyright line copy-pasted incorrectly.
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [ftrace-bpf 1/5] add BPF_PROG_TYPE_FTRACE to bpf
  2017-11-12  7:28 [ftrace-bpf 1/5] add BPF_PROG_TYPE_FTRACE to bpf yupeng0921
                   ` (4 preceding siblings ...)
  2017-11-13  1:02 ` [ftrace-bpf 1/5] add BPF_PROG_TYPE_FTRACE to bpf Alexei Starovoitov
@ 2017-11-14 17:47 ` kbuild test robot
  2017-11-14 21:01 ` kbuild test robot
  6 siblings, 0 replies; 10+ messages in thread
From: kbuild test robot @ 2017-11-14 17:47 UTC (permalink / raw)
  To: yupeng0921
  Cc: kbuild-all, linux-kernel, ast, daniel, rostedt, mingo, yupeng0921

[-- Attachment #1: Type: text/plain, Size: 1008 bytes --]

Hi,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v4.14]
[cannot apply to next-20171114]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/yupeng0921-gmail-com/add-BPF_PROG_TYPE_FTRACE-to-bpf/20171114-202535
config: parisc-allmodconfig (attached as .config)
compiler: hppa-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=parisc 

All errors (new ones prefixed by >>):

>> kernel/bpf/syscall.o:(.data.rel.ro+0xc): undefined reference to `ftrace_prog_ops'

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 51284 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [ftrace-bpf 1/5] add BPF_PROG_TYPE_FTRACE to bpf
  2017-11-12  7:28 [ftrace-bpf 1/5] add BPF_PROG_TYPE_FTRACE to bpf yupeng0921
                   ` (5 preceding siblings ...)
  2017-11-14 17:47 ` kbuild test robot
@ 2017-11-14 21:01 ` kbuild test robot
  6 siblings, 0 replies; 10+ messages in thread
From: kbuild test robot @ 2017-11-14 21:01 UTC (permalink / raw)
  To: yupeng0921
  Cc: kbuild-all, linux-kernel, ast, daniel, rostedt, mingo, yupeng0921

[-- Attachment #1: Type: text/plain, Size: 864 bytes --]

Hi,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v4.14]
[cannot apply to next-20171114]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/yupeng0921-gmail-com/add-BPF_PROG_TYPE_FTRACE-to-bpf/20171114-202535
config: x86_64-randconfig-s3-11150026 (attached as .config)
compiler: gcc-6 (Debian 6.4.0-9) 6.4.0 20171026
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

>> kernel/bpf/syscall.o:(.rodata+0x198): undefined reference to `ftrace_prog_ops'

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 32138 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [ftrace-bpf 1/5] add BPF_PROG_TYPE_FTRACE to bpf
  2017-11-13  8:06   ` peng yu
@ 2017-11-17 23:48     ` Alexei Starovoitov
  0 siblings, 0 replies; 10+ messages in thread
From: Alexei Starovoitov @ 2017-11-17 23:48 UTC (permalink / raw)
  To: peng yu
  Cc: linux-kernel, ast, daniel, rostedt, mingo, David S. Miller, netdev

On Mon, Nov 13, 2017 at 12:06:17AM -0800, peng yu wrote:
> > 1. anything bpf related has to go via net-next tree.
> I found there is a net-next git repo:
> https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
> I will use this repo for the further bpf-ftrace patch set.
> 
> > 2.
> > this obviously breaks ABI. New types can only be added to the end.
> Sure, I will add the new type at the end.
> 
> > 3.
> > this won't even compile, since ftrace_regs is only added in the patch 4.
> It could compile, as the ftrace_regs related code is inside the
> "#ifdef FTRACE_BPF_FILTER" macro, if this macro is not defined, no
> ftrace_regs related code would be compiled.
> 
> 
> > Since bpf program will see ftrace_regs as an input it becomes
> > abi, so has to be defined in uapi/linux/bpf_ftrace.h or similar.
> > We need to think through how to make it generic across archs
> > instead of defining ftrace_regs for each arch.
> I'm not sure whether I'm fully understand your meaning. Like kprobe,
> the ftrace-bpf need to get a function's parameters and check them. So
> it won't be abi stable, and it should depend on architecture
> implement. I can create a header file like uapi/linux/bpf_ftrace.h,
> but I noticed that kprobe doesn't have such a header file, if I'm
> wrong, please let me know. And about make it generic across archs, I
> know kprobe use pt_regs as parameter, the pt_regs is defined on each
> arch, so I can't see how bpf-ftrace can get a generic interface across
> archs if it need to check function's parameters. If I misunderstand
> anything, please let me know.

all of ftrace are called at function entry and calling convention
is fixed per architecture, so we can make a generic and stable
struct bpf_ftrace_args {
  __u64 arg1, arg2, .. arg5;
};
save_mcount_regs doesn't care what order the regs are stored
so the same stack space can be used to keep bpf_ftrace_args
and used in restore_mcount_regs.
I'd also make it depend on DYNAMIC_FTRACE_WITH_REGS to avoid
dealing with obscure corner cases.

> 
> > 4.
> > the patch 2/3 takes an approach of passing FD integer value in text form
> > to the kernel. That approach was discussed years ago and rejected.
> > It has to use binary interface like perf_event + ioctl.
> > See RFC patches where we're extending perf_event_open syscall to
> > support binary access to kprobe/uprobe.
> > imo binary interface to ftrace is pre-requisite to ftrace+bpf work.
> > We've had too many issues with text based kprobe api to repeat
> > the same mistake here.
> I notice the kprobe-bpf prog is set through the PERF_EVENT_IOC_SET_BPF
> ioctl, I may try to see whether I can reuse this interface, or if it
> is not suitable, I will try to define a new binary interface.
> 
> > 5.
> > patch 4 hacks save_mcount_regs asm to pass ctx pointer in %rcx
> > whereas it's only used in ftrace_graph_caller which doesn't seem right.
> > It points out to another issue that such ftrace+bpf integration
> > is only done for ftrace_graph_caller without extensibility in mind.
> > If we do ftrace+bpf I'd rather see generic framework that applies
> > to all of ftrace instead of single feature of it.
> It is a hard problem. The ftrace framework has lots of tracers,
> function tracer and function graph tracer use the 'gcc -pg' directly,
> other tracers use tracepoint, I should spend more time to find a
> suitable solution.

since all of ftrace goes through the same function entry point
it should be possible to have one generic bpf filter interface
suitable for all tracers that ftrace supports.

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2017-11-17 23:48 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-12  7:28 [ftrace-bpf 1/5] add BPF_PROG_TYPE_FTRACE to bpf yupeng0921
2017-11-12  7:28 ` [ftrace-bpf 2/5] add bpf prog interface for ftrace yupeng0921
2017-11-12  7:28 ` [ftrace-bpf 3/5] add bpf prog filter for graph trace yupeng0921
2017-11-12  7:28 ` [ftrace-bpf 4/5] enable bpf filter for graph trace in x86-64 arch yupeng0921
2017-11-12  7:28 ` [ftrace-bpf 5/5] add BPF_PROG_TYPE_FTRACE support for samples/bpf yupeng0921
2017-11-13  1:02 ` [ftrace-bpf 1/5] add BPF_PROG_TYPE_FTRACE to bpf Alexei Starovoitov
2017-11-13  8:06   ` peng yu
2017-11-17 23:48     ` Alexei Starovoitov
2017-11-14 17:47 ` kbuild test robot
2017-11-14 21:01 ` kbuild test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).