linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH v2 00/26] perf tools: Support uBPF script
@ 2016-06-26 11:20 He Kuang
  2016-06-26 11:20 ` [RFC PATCH v2 01/26] tools include: Adopt byte ordering macros from byteorder/generic.h He Kuang
                   ` (26 more replies)
  0 siblings, 27 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:20 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

This patchset is based on Wang Nan's v1:
     http://thread.gmane.org/gmane.linux.kernel/2203717/focus=2203707

""" 
  This patch set allows to perf invoke some user space BPF scripts on
  some point. uBPF scripts and kernel BPF scripts reside in one BPF
  object.  They communicate with each other with BPF maps. uBPF
  scripts can invoke helper functions provided by perf.
  
  At least following new features can be achieved based on uBPF
  support:
  
   1) Report statistical result:

      Like DTrace, perf print statistical report before quit. No need
      to extract data using 'perf report'. Statistical method is
      controled by user.
  
   2) Control perf's behavior:

      Dynamically adjust period of different events. Policy is defined
      by user.
"""

and modified by following the reviewers' suggestions.

v1-v2:

  - Split bpf vm part out of kernel/bpf/core.c and link to it instead
    of using ubpf library(Suggested by Alexei Starovoitov). And add
    runtime bounds check just like ubpf library does.
    
  - Introduce bpf_engine(engine-kbpf, engine-ubpf) operations and
    getting rid of the complicate macros(Suggested by Arnaldo).

  - Use void pointer to reference kbpf/ubpf entries.(Suggested by
    Arnaldo)

The test case in the v1 cover letter still works but there's a slight
problem which should be pointed out to clarify the usage of ubpf
function arguments.

-int perf_record_end(int samples)
+struct perf_record_end_ctx {
+       int samples;
+       int dummy;
+};
+int perf_record_end(struct perf_record_end_ctx *ctx)

And the argument 'samples' should be referenced as 'ctx->samples'.

Thank you.

He Kuang (17):
  bpf: extract jmp and default handler and introduce UBPF_BUILD flag
  tools include: Add (atomic|atomic64)_add implementation from the
    kernel sources
  perf bpf: Implement empty instruction handler and build bpf-vm
  perf bpf: Remove unused code in libbpf
  perf bpf: Store arbitrary entries instread fd array in bpf_program
  perf bpf: Add libbpf-internal.h header file
  perf bpf: Add abstraction for bpf program methods
  perf bpf: Add -Wextra to cflags for more warnings and fix them
  perf bpf: Introduce the entity and engine for userspace bpf
  perf bpf: Add method for fetching nth ubpf vm
  perf bpf: Add methods to set/check ubpf engine for bpf programs
  perf bpf: Add ubpf helper function slots and set/get methods
  bpf: Support bpf load/store boundary check for ubpf
  perf bpf: Implement boundary check code in ubpf
  perf record: Add uBPF hooks at beginning and end of perf record
  perf bpf: Fillup bpf jmp_call handler
  perf bpf: Implement run_ubpf_program

Wang Nan (9):
  tools include: Adopt byte ordering macros from byteorder/generic.h
  tools include: Fix wrong macro definitions for cpu_to_le* for big
    endian
  bpf: split __bpf_prog_run code into new file
  tools include: Sync math64.h and div64.h
  perf bpf: Add map related BPF helper
  perf bpf: Add UBPF flags and makefile options
  perf tools: Register basic uBPF helpers
  perf bpf: Accept uBPF programs
  perf tests: Add uBPF test case

 include/linux/filter.h                             |   1 +
 kernel/bpf/Makefile                                |   2 +-
 kernel/bpf/core.c                                  | 487 -------------------
 kernel/bpf/vm.c                                    | 517 +++++++++++++++++++++
 tools/arch/x86/include/asm/atomic.h                |  28 ++
 tools/include/asm-generic/atomic-gcc.h             |  10 +
 tools/include/asm-generic/div64.h                  | 234 ++++++++++
 tools/include/linux/byteorder/generic.h            |  48 ++
 tools/include/linux/kernel.h                       |   7 +-
 tools/include/linux/math64.h                       | 247 ++++++++++
 tools/include/linux/types.h                        |   4 +
 tools/lib/bpf/Build                                |   2 +
 tools/lib/bpf/Makefile                             |   6 +-
 tools/lib/bpf/bpf.c                                |  24 +
 tools/lib/bpf/bpf.h                                |   2 +
 tools/lib/bpf/engine-kbpf.c                        | 131 ++++++
 tools/lib/bpf/engine-ubpf.c                        | 134 ++++++
 tools/lib/bpf/libbpf-internal.h                    |  76 +++
 tools/lib/bpf/libbpf.c                             | 216 ++-------
 tools/lib/bpf/libbpf.h                             |  43 +-
 tools/perf/MANIFEST                                |   3 +
 tools/perf/Makefile.perf                           |   2 +
 tools/perf/builtin-record.c                        |   4 +
 tools/perf/config/Makefile                         |   4 +
 tools/perf/perf.c                                  |   3 +
 tools/perf/tests/Build                             |   8 +
 tools/perf/tests/bpf-script-test-ubpf.c            |  88 ++++
 tools/perf/tests/bpf.c                             |  78 +++-
 tools/perf/tests/llvm.c                            |   4 +
 tools/perf/tests/llvm.h                            |   2 +
 tools/perf/util/Build                              |   3 +
 tools/perf/util/bpf-loader.c                       |  23 +-
 tools/perf/util/bpf-vm.c                           |  89 ++++
 tools/perf/util/bpf-vm.h                           |   8 +
 tools/perf/util/intel-bts.c                        |   5 -
 .../util/intel-pt-decoder/intel-pt-pkt-decoder.c   |   7 +-
 tools/perf/util/ubpf-helpers-list.h                |  11 +
 tools/perf/util/ubpf-helpers.c                     |  73 +++
 tools/perf/util/ubpf-helpers.h                     |  21 +
 tools/perf/util/ubpf-hooks-list.h                  |  34 ++
 tools/perf/util/ubpf-hooks.c                       |  81 ++++
 tools/perf/util/ubpf-hooks.h                       |  41 ++
 42 files changed, 2126 insertions(+), 685 deletions(-)
 create mode 100644 kernel/bpf/vm.c
 create mode 100644 tools/include/asm-generic/div64.h
 create mode 100644 tools/include/linux/byteorder/generic.h
 create mode 100644 tools/include/linux/math64.h
 create mode 100644 tools/lib/bpf/engine-kbpf.c
 create mode 100644 tools/lib/bpf/engine-ubpf.c
 create mode 100644 tools/lib/bpf/libbpf-internal.h
 create mode 100644 tools/perf/tests/bpf-script-test-ubpf.c
 create mode 100644 tools/perf/util/bpf-vm.c
 create mode 100644 tools/perf/util/bpf-vm.h
 create mode 100644 tools/perf/util/ubpf-helpers-list.h
 create mode 100644 tools/perf/util/ubpf-helpers.c
 create mode 100644 tools/perf/util/ubpf-helpers.h
 create mode 100644 tools/perf/util/ubpf-hooks-list.h
 create mode 100644 tools/perf/util/ubpf-hooks.c
 create mode 100644 tools/perf/util/ubpf-hooks.h

-- 
1.8.5.2

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

* [RFC PATCH v2 01/26] tools include: Adopt byte ordering macros from byteorder/generic.h
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
@ 2016-06-26 11:20 ` He Kuang
  2016-06-26 11:20 ` [RFC PATCH v2 02/26] tools include: Fix wrong macro definitions for cpu_to_le* for big endian He Kuang
                   ` (25 subsequent siblings)
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:20 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

From: Wang Nan <wangnan0@huawei.com>

This patch adopts the macros for byte order conversion from
"include/linux/byteorder/generic.h" to
"tools/include/linux/byteorder/generic.h"

tools/perf/MANIFEST is also updated for 'make perf-*-src-pkg'.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Signed-off-by: He Kuang <hekuang@huawei.com>
---
 tools/include/linux/byteorder/generic.h | 48 +++++++++++++++++++++++++++++++++
 tools/perf/MANIFEST                     |  1 +
 2 files changed, 49 insertions(+)
 create mode 100644 tools/include/linux/byteorder/generic.h

diff --git a/tools/include/linux/byteorder/generic.h b/tools/include/linux/byteorder/generic.h
new file mode 100644
index 0000000..41b4507
--- /dev/null
+++ b/tools/include/linux/byteorder/generic.h
@@ -0,0 +1,48 @@
+#ifndef _TOOLS_LINUX_BYTEORDER_GENERIC_H
+#define _TOOLS_LINUX_BYTEORDER_GENERIC_H
+
+#include <endian.h>
+#include <byteswap.h>
+
+#define cpu_to_le64 __cpu_to_le64
+#define le64_to_cpu __le64_to_cpu
+#define cpu_to_le32 __cpu_to_le32
+#define le32_to_cpu __le32_to_cpu
+#define cpu_to_le16 __cpu_to_le16
+#define le16_to_cpu __le16_to_cpu
+#define cpu_to_be64 __cpu_to_be64
+#define be64_to_cpu __be64_to_cpu
+#define cpu_to_be32 __cpu_to_be32
+#define be32_to_cpu __be32_to_cpu
+#define cpu_to_be16 __cpu_to_be16
+#define be16_to_cpu __be16_to_cpu
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define __cpu_to_le16 bswap_16
+#define __cpu_to_le32 bswap_32
+#define __cpu_to_le64 bswap_64
+#define __le16_to_cpu bswap_16
+#define __le32_to_cpu bswap_32
+#define __le64_to_cpu bswap_64
+#define __cpu_to_be16
+#define __cpu_to_be32
+#define __cpu_to_be64
+#define __be16_to_cpu
+#define __be32_to_cpu
+#define __be64_to_cpu
+#else
+#define __cpu_to_le16
+#define __cpu_to_le32
+#define __cpu_to_le64
+#define __le16_to_cpu
+#define __le32_to_cpu
+#define __le64_to_cpu
+#define __cpu_to_be16 bswap_16
+#define __cpu_to_be32 bswap_32
+#define __cpu_to_be64 bswap_64
+#define __be16_to_cpu bswap_16
+#define __be32_to_cpu bswap_32
+#define __be64_to_cpu bswap_64
+#endif
+
+#endif /* _TOOLS_LINUX_BYTEORDER_GENERIC_H */
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 8c8c6b9..80ac3d4 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -46,6 +46,7 @@ tools/include/asm-generic/bitops/hweight.h
 tools/include/asm-generic/bitops.h
 tools/include/linux/atomic.h
 tools/include/linux/bitops.h
+tools/include/linux/byteorder/generic.h
 tools/include/linux/compiler.h
 tools/include/linux/filter.h
 tools/include/linux/hash.h
-- 
1.8.5.2

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

* [RFC PATCH v2 02/26] tools include: Fix wrong macro definitions for cpu_to_le* for big endian
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
  2016-06-26 11:20 ` [RFC PATCH v2 01/26] tools include: Adopt byte ordering macros from byteorder/generic.h He Kuang
@ 2016-06-26 11:20 ` He Kuang
  2016-06-26 11:20 ` [RFC PATCH v2 03/26] bpf: split __bpf_prog_run code into new file He Kuang
                   ` (24 subsequent siblings)
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:20 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

From: Wang Nan <wangnan0@huawei.com>

The cpu_to_le* macros in kernel.h are defined without considering
endianese. This patch includes "byteoder/generic.h" instead to fix the
bug, and removes redundant definitions of those macros in intel-bts.c
and intel-pt-pkt-decoder.c.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Signed-off-by: He Kuang <hekuang@huawei.com>
---
 tools/include/linux/kernel.h                            | 7 +------
 tools/perf/util/intel-bts.c                             | 5 -----
 tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c | 7 +------
 3 files changed, 2 insertions(+), 17 deletions(-)

diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h
index 76df535..ccf8daf 100644
--- a/tools/include/linux/kernel.h
+++ b/tools/include/linux/kernel.h
@@ -63,12 +63,7 @@
 #endif
 #endif
 
-/*
- * Both need more care to handle endianness
- * (Don't use bitmap_copy_le() for now)
- */
-#define cpu_to_le64(x)	(x)
-#define cpu_to_le32(x)	(x)
+#include <linux/byteorder/generic.h>
 
 static inline int
 vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c
index 749e6f2..bffd953 100644
--- a/tools/perf/util/intel-bts.c
+++ b/tools/perf/util/intel-bts.c
@@ -40,11 +40,6 @@
 #define INTEL_BTS_ERR_NOINSN  5
 #define INTEL_BTS_ERR_LOST    9
 
-#if __BYTE_ORDER == __BIG_ENDIAN
-#define le64_to_cpu bswap_64
-#else
-#define le64_to_cpu
-#endif
 
 struct intel_bts {
 	struct auxtrace			auxtrace;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
index b1257c8..9a428f7 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
@@ -17,6 +17,7 @@
 #include <string.h>
 #include <endian.h>
 #include <byteswap.h>
+#include <linux/byteorder/generic.h>
 
 #include "intel-pt-pkt-decoder.h"
 
@@ -27,17 +28,11 @@
 #define NR_FLAG		BIT63
 
 #if __BYTE_ORDER == __BIG_ENDIAN
-#define le16_to_cpu bswap_16
-#define le32_to_cpu bswap_32
-#define le64_to_cpu bswap_64
 #define memcpy_le64(d, s, n) do { \
 	memcpy((d), (s), (n));    \
 	*(d) = le64_to_cpu(*(d)); \
 } while (0)
 #else
-#define le16_to_cpu
-#define le32_to_cpu
-#define le64_to_cpu
 #define memcpy_le64 memcpy
 #endif
 
-- 
1.8.5.2

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

* [RFC PATCH v2 03/26] bpf: split __bpf_prog_run code into new file
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
  2016-06-26 11:20 ` [RFC PATCH v2 01/26] tools include: Adopt byte ordering macros from byteorder/generic.h He Kuang
  2016-06-26 11:20 ` [RFC PATCH v2 02/26] tools include: Fix wrong macro definitions for cpu_to_le* for big endian He Kuang
@ 2016-06-26 11:20 ` He Kuang
  2016-06-26 11:20 ` [RFC PATCH v2 04/26] bpf: extract jmp and default handler and introduce UBPF_BUILD flag He Kuang
                   ` (23 subsequent siblings)
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:20 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

From: Wang Nan <wangnan0@huawei.com>

Split out function __bpf_prog_run() and related macros from bpf/core.c
into bpf/vm.c.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Signed-off-by: He Kuang <hekuang@huawei.com>
---
 include/linux/filter.h |   1 +
 kernel/bpf/Makefile    |   2 +-
 kernel/bpf/core.c      | 487 ------------------------------------------------
 kernel/bpf/vm.c        | 492 +++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 494 insertions(+), 488 deletions(-)
 create mode 100644 kernel/bpf/vm.c

diff --git a/include/linux/filter.h b/include/linux/filter.h
index 6fc31ef..71da095 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -504,6 +504,7 @@ void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp);
 
 u64 __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5);
 
+unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn);
 struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog);
 bool bpf_helper_changes_skb_data(void *func);
 
diff --git a/kernel/bpf/Makefile b/kernel/bpf/Makefile
index eed911d..6958399 100644
--- a/kernel/bpf/Makefile
+++ b/kernel/bpf/Makefile
@@ -1,4 +1,4 @@
-obj-y := core.o
+obj-y := core.o vm.o
 
 obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o
 obj-$(CONFIG_BPF_SYSCALL) += hashtab.o arraymap.o percpu_freelist.o
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index b94a365..4f20791 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -31,27 +31,6 @@
 
 #include <asm/unaligned.h>
 
-/* Registers */
-#define BPF_R0	regs[BPF_REG_0]
-#define BPF_R1	regs[BPF_REG_1]
-#define BPF_R2	regs[BPF_REG_2]
-#define BPF_R3	regs[BPF_REG_3]
-#define BPF_R4	regs[BPF_REG_4]
-#define BPF_R5	regs[BPF_REG_5]
-#define BPF_R6	regs[BPF_REG_6]
-#define BPF_R7	regs[BPF_REG_7]
-#define BPF_R8	regs[BPF_REG_8]
-#define BPF_R9	regs[BPF_REG_9]
-#define BPF_R10	regs[BPF_REG_10]
-
-/* Named registers */
-#define DST	regs[insn->dst_reg]
-#define SRC	regs[insn->src_reg]
-#define FP	regs[BPF_REG_FP]
-#define ARG1	regs[BPF_REG_ARG1]
-#define CTX	regs[BPF_REG_CTX]
-#define IMM	insn->imm
-
 /* No hurry in this branch
  *
  * Exported for the bpf jit load helper.
@@ -458,472 +437,6 @@ noinline u64 __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
 }
 EXPORT_SYMBOL_GPL(__bpf_call_base);
 
-/**
- *	__bpf_prog_run - run eBPF program on a given context
- *	@ctx: is the data we are operating on
- *	@insn: is the array of eBPF instructions
- *
- * Decode and execute eBPF instructions.
- */
-static unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn)
-{
-	u64 stack[MAX_BPF_STACK / sizeof(u64)];
-	u64 regs[MAX_BPF_REG], tmp;
-	static const void *jumptable[256] = {
-		[0 ... 255] = &&default_label,
-		/* Now overwrite non-defaults ... */
-		/* 32 bit ALU operations */
-		[BPF_ALU | BPF_ADD | BPF_X] = &&ALU_ADD_X,
-		[BPF_ALU | BPF_ADD | BPF_K] = &&ALU_ADD_K,
-		[BPF_ALU | BPF_SUB | BPF_X] = &&ALU_SUB_X,
-		[BPF_ALU | BPF_SUB | BPF_K] = &&ALU_SUB_K,
-		[BPF_ALU | BPF_AND | BPF_X] = &&ALU_AND_X,
-		[BPF_ALU | BPF_AND | BPF_K] = &&ALU_AND_K,
-		[BPF_ALU | BPF_OR | BPF_X]  = &&ALU_OR_X,
-		[BPF_ALU | BPF_OR | BPF_K]  = &&ALU_OR_K,
-		[BPF_ALU | BPF_LSH | BPF_X] = &&ALU_LSH_X,
-		[BPF_ALU | BPF_LSH | BPF_K] = &&ALU_LSH_K,
-		[BPF_ALU | BPF_RSH | BPF_X] = &&ALU_RSH_X,
-		[BPF_ALU | BPF_RSH | BPF_K] = &&ALU_RSH_K,
-		[BPF_ALU | BPF_XOR | BPF_X] = &&ALU_XOR_X,
-		[BPF_ALU | BPF_XOR | BPF_K] = &&ALU_XOR_K,
-		[BPF_ALU | BPF_MUL | BPF_X] = &&ALU_MUL_X,
-		[BPF_ALU | BPF_MUL | BPF_K] = &&ALU_MUL_K,
-		[BPF_ALU | BPF_MOV | BPF_X] = &&ALU_MOV_X,
-		[BPF_ALU | BPF_MOV | BPF_K] = &&ALU_MOV_K,
-		[BPF_ALU | BPF_DIV | BPF_X] = &&ALU_DIV_X,
-		[BPF_ALU | BPF_DIV | BPF_K] = &&ALU_DIV_K,
-		[BPF_ALU | BPF_MOD | BPF_X] = &&ALU_MOD_X,
-		[BPF_ALU | BPF_MOD | BPF_K] = &&ALU_MOD_K,
-		[BPF_ALU | BPF_NEG] = &&ALU_NEG,
-		[BPF_ALU | BPF_END | BPF_TO_BE] = &&ALU_END_TO_BE,
-		[BPF_ALU | BPF_END | BPF_TO_LE] = &&ALU_END_TO_LE,
-		/* 64 bit ALU operations */
-		[BPF_ALU64 | BPF_ADD | BPF_X] = &&ALU64_ADD_X,
-		[BPF_ALU64 | BPF_ADD | BPF_K] = &&ALU64_ADD_K,
-		[BPF_ALU64 | BPF_SUB | BPF_X] = &&ALU64_SUB_X,
-		[BPF_ALU64 | BPF_SUB | BPF_K] = &&ALU64_SUB_K,
-		[BPF_ALU64 | BPF_AND | BPF_X] = &&ALU64_AND_X,
-		[BPF_ALU64 | BPF_AND | BPF_K] = &&ALU64_AND_K,
-		[BPF_ALU64 | BPF_OR | BPF_X] = &&ALU64_OR_X,
-		[BPF_ALU64 | BPF_OR | BPF_K] = &&ALU64_OR_K,
-		[BPF_ALU64 | BPF_LSH | BPF_X] = &&ALU64_LSH_X,
-		[BPF_ALU64 | BPF_LSH | BPF_K] = &&ALU64_LSH_K,
-		[BPF_ALU64 | BPF_RSH | BPF_X] = &&ALU64_RSH_X,
-		[BPF_ALU64 | BPF_RSH | BPF_K] = &&ALU64_RSH_K,
-		[BPF_ALU64 | BPF_XOR | BPF_X] = &&ALU64_XOR_X,
-		[BPF_ALU64 | BPF_XOR | BPF_K] = &&ALU64_XOR_K,
-		[BPF_ALU64 | BPF_MUL | BPF_X] = &&ALU64_MUL_X,
-		[BPF_ALU64 | BPF_MUL | BPF_K] = &&ALU64_MUL_K,
-		[BPF_ALU64 | BPF_MOV | BPF_X] = &&ALU64_MOV_X,
-		[BPF_ALU64 | BPF_MOV | BPF_K] = &&ALU64_MOV_K,
-		[BPF_ALU64 | BPF_ARSH | BPF_X] = &&ALU64_ARSH_X,
-		[BPF_ALU64 | BPF_ARSH | BPF_K] = &&ALU64_ARSH_K,
-		[BPF_ALU64 | BPF_DIV | BPF_X] = &&ALU64_DIV_X,
-		[BPF_ALU64 | BPF_DIV | BPF_K] = &&ALU64_DIV_K,
-		[BPF_ALU64 | BPF_MOD | BPF_X] = &&ALU64_MOD_X,
-		[BPF_ALU64 | BPF_MOD | BPF_K] = &&ALU64_MOD_K,
-		[BPF_ALU64 | BPF_NEG] = &&ALU64_NEG,
-		/* Call instruction */
-		[BPF_JMP | BPF_CALL] = &&JMP_CALL,
-		[BPF_JMP | BPF_CALL | BPF_X] = &&JMP_TAIL_CALL,
-		/* Jumps */
-		[BPF_JMP | BPF_JA] = &&JMP_JA,
-		[BPF_JMP | BPF_JEQ | BPF_X] = &&JMP_JEQ_X,
-		[BPF_JMP | BPF_JEQ | BPF_K] = &&JMP_JEQ_K,
-		[BPF_JMP | BPF_JNE | BPF_X] = &&JMP_JNE_X,
-		[BPF_JMP | BPF_JNE | BPF_K] = &&JMP_JNE_K,
-		[BPF_JMP | BPF_JGT | BPF_X] = &&JMP_JGT_X,
-		[BPF_JMP | BPF_JGT | BPF_K] = &&JMP_JGT_K,
-		[BPF_JMP | BPF_JGE | BPF_X] = &&JMP_JGE_X,
-		[BPF_JMP | BPF_JGE | BPF_K] = &&JMP_JGE_K,
-		[BPF_JMP | BPF_JSGT | BPF_X] = &&JMP_JSGT_X,
-		[BPF_JMP | BPF_JSGT | BPF_K] = &&JMP_JSGT_K,
-		[BPF_JMP | BPF_JSGE | BPF_X] = &&JMP_JSGE_X,
-		[BPF_JMP | BPF_JSGE | BPF_K] = &&JMP_JSGE_K,
-		[BPF_JMP | BPF_JSET | BPF_X] = &&JMP_JSET_X,
-		[BPF_JMP | BPF_JSET | BPF_K] = &&JMP_JSET_K,
-		/* Program return */
-		[BPF_JMP | BPF_EXIT] = &&JMP_EXIT,
-		/* Store instructions */
-		[BPF_STX | BPF_MEM | BPF_B] = &&STX_MEM_B,
-		[BPF_STX | BPF_MEM | BPF_H] = &&STX_MEM_H,
-		[BPF_STX | BPF_MEM | BPF_W] = &&STX_MEM_W,
-		[BPF_STX | BPF_MEM | BPF_DW] = &&STX_MEM_DW,
-		[BPF_STX | BPF_XADD | BPF_W] = &&STX_XADD_W,
-		[BPF_STX | BPF_XADD | BPF_DW] = &&STX_XADD_DW,
-		[BPF_ST | BPF_MEM | BPF_B] = &&ST_MEM_B,
-		[BPF_ST | BPF_MEM | BPF_H] = &&ST_MEM_H,
-		[BPF_ST | BPF_MEM | BPF_W] = &&ST_MEM_W,
-		[BPF_ST | BPF_MEM | BPF_DW] = &&ST_MEM_DW,
-		/* Load instructions */
-		[BPF_LDX | BPF_MEM | BPF_B] = &&LDX_MEM_B,
-		[BPF_LDX | BPF_MEM | BPF_H] = &&LDX_MEM_H,
-		[BPF_LDX | BPF_MEM | BPF_W] = &&LDX_MEM_W,
-		[BPF_LDX | BPF_MEM | BPF_DW] = &&LDX_MEM_DW,
-		[BPF_LD | BPF_ABS | BPF_W] = &&LD_ABS_W,
-		[BPF_LD | BPF_ABS | BPF_H] = &&LD_ABS_H,
-		[BPF_LD | BPF_ABS | BPF_B] = &&LD_ABS_B,
-		[BPF_LD | BPF_IND | BPF_W] = &&LD_IND_W,
-		[BPF_LD | BPF_IND | BPF_H] = &&LD_IND_H,
-		[BPF_LD | BPF_IND | BPF_B] = &&LD_IND_B,
-		[BPF_LD | BPF_IMM | BPF_DW] = &&LD_IMM_DW,
-	};
-	u32 tail_call_cnt = 0;
-	void *ptr;
-	int off;
-
-#define CONT	 ({ insn++; goto select_insn; })
-#define CONT_JMP ({ insn++; goto select_insn; })
-
-	FP = (u64) (unsigned long) &stack[ARRAY_SIZE(stack)];
-	ARG1 = (u64) (unsigned long) ctx;
-
-select_insn:
-	goto *jumptable[insn->code];
-
-	/* ALU */
-#define ALU(OPCODE, OP)			\
-	ALU64_##OPCODE##_X:		\
-		DST = DST OP SRC;	\
-		CONT;			\
-	ALU_##OPCODE##_X:		\
-		DST = (u32) DST OP (u32) SRC;	\
-		CONT;			\
-	ALU64_##OPCODE##_K:		\
-		DST = DST OP IMM;		\
-		CONT;			\
-	ALU_##OPCODE##_K:		\
-		DST = (u32) DST OP (u32) IMM;	\
-		CONT;
-
-	ALU(ADD,  +)
-	ALU(SUB,  -)
-	ALU(AND,  &)
-	ALU(OR,   |)
-	ALU(LSH, <<)
-	ALU(RSH, >>)
-	ALU(XOR,  ^)
-	ALU(MUL,  *)
-#undef ALU
-	ALU_NEG:
-		DST = (u32) -DST;
-		CONT;
-	ALU64_NEG:
-		DST = -DST;
-		CONT;
-	ALU_MOV_X:
-		DST = (u32) SRC;
-		CONT;
-	ALU_MOV_K:
-		DST = (u32) IMM;
-		CONT;
-	ALU64_MOV_X:
-		DST = SRC;
-		CONT;
-	ALU64_MOV_K:
-		DST = IMM;
-		CONT;
-	LD_IMM_DW:
-		DST = (u64) (u32) insn[0].imm | ((u64) (u32) insn[1].imm) << 32;
-		insn++;
-		CONT;
-	ALU64_ARSH_X:
-		(*(s64 *) &DST) >>= SRC;
-		CONT;
-	ALU64_ARSH_K:
-		(*(s64 *) &DST) >>= IMM;
-		CONT;
-	ALU64_MOD_X:
-		if (unlikely(SRC == 0))
-			return 0;
-		div64_u64_rem(DST, SRC, &tmp);
-		DST = tmp;
-		CONT;
-	ALU_MOD_X:
-		if (unlikely(SRC == 0))
-			return 0;
-		tmp = (u32) DST;
-		DST = do_div(tmp, (u32) SRC);
-		CONT;
-	ALU64_MOD_K:
-		div64_u64_rem(DST, IMM, &tmp);
-		DST = tmp;
-		CONT;
-	ALU_MOD_K:
-		tmp = (u32) DST;
-		DST = do_div(tmp, (u32) IMM);
-		CONT;
-	ALU64_DIV_X:
-		if (unlikely(SRC == 0))
-			return 0;
-		DST = div64_u64(DST, SRC);
-		CONT;
-	ALU_DIV_X:
-		if (unlikely(SRC == 0))
-			return 0;
-		tmp = (u32) DST;
-		do_div(tmp, (u32) SRC);
-		DST = (u32) tmp;
-		CONT;
-	ALU64_DIV_K:
-		DST = div64_u64(DST, IMM);
-		CONT;
-	ALU_DIV_K:
-		tmp = (u32) DST;
-		do_div(tmp, (u32) IMM);
-		DST = (u32) tmp;
-		CONT;
-	ALU_END_TO_BE:
-		switch (IMM) {
-		case 16:
-			DST = (__force u16) cpu_to_be16(DST);
-			break;
-		case 32:
-			DST = (__force u32) cpu_to_be32(DST);
-			break;
-		case 64:
-			DST = (__force u64) cpu_to_be64(DST);
-			break;
-		}
-		CONT;
-	ALU_END_TO_LE:
-		switch (IMM) {
-		case 16:
-			DST = (__force u16) cpu_to_le16(DST);
-			break;
-		case 32:
-			DST = (__force u32) cpu_to_le32(DST);
-			break;
-		case 64:
-			DST = (__force u64) cpu_to_le64(DST);
-			break;
-		}
-		CONT;
-
-	/* CALL */
-	JMP_CALL:
-		/* Function call scratches BPF_R1-BPF_R5 registers,
-		 * preserves BPF_R6-BPF_R9, and stores return value
-		 * into BPF_R0.
-		 */
-		BPF_R0 = (__bpf_call_base + insn->imm)(BPF_R1, BPF_R2, BPF_R3,
-						       BPF_R4, BPF_R5);
-		CONT;
-
-	JMP_TAIL_CALL: {
-		struct bpf_map *map = (struct bpf_map *) (unsigned long) BPF_R2;
-		struct bpf_array *array = container_of(map, struct bpf_array, map);
-		struct bpf_prog *prog;
-		u64 index = BPF_R3;
-
-		if (unlikely(index >= array->map.max_entries))
-			goto out;
-
-		if (unlikely(tail_call_cnt > MAX_TAIL_CALL_CNT))
-			goto out;
-
-		tail_call_cnt++;
-
-		prog = READ_ONCE(array->ptrs[index]);
-		if (unlikely(!prog))
-			goto out;
-
-		/* ARG1 at this point is guaranteed to point to CTX from
-		 * the verifier side due to the fact that the tail call is
-		 * handeled like a helper, that is, bpf_tail_call_proto,
-		 * where arg1_type is ARG_PTR_TO_CTX.
-		 */
-		insn = prog->insnsi;
-		goto select_insn;
-out:
-		CONT;
-	}
-	/* JMP */
-	JMP_JA:
-		insn += insn->off;
-		CONT;
-	JMP_JEQ_X:
-		if (DST == SRC) {
-			insn += insn->off;
-			CONT_JMP;
-		}
-		CONT;
-	JMP_JEQ_K:
-		if (DST == IMM) {
-			insn += insn->off;
-			CONT_JMP;
-		}
-		CONT;
-	JMP_JNE_X:
-		if (DST != SRC) {
-			insn += insn->off;
-			CONT_JMP;
-		}
-		CONT;
-	JMP_JNE_K:
-		if (DST != IMM) {
-			insn += insn->off;
-			CONT_JMP;
-		}
-		CONT;
-	JMP_JGT_X:
-		if (DST > SRC) {
-			insn += insn->off;
-			CONT_JMP;
-		}
-		CONT;
-	JMP_JGT_K:
-		if (DST > IMM) {
-			insn += insn->off;
-			CONT_JMP;
-		}
-		CONT;
-	JMP_JGE_X:
-		if (DST >= SRC) {
-			insn += insn->off;
-			CONT_JMP;
-		}
-		CONT;
-	JMP_JGE_K:
-		if (DST >= IMM) {
-			insn += insn->off;
-			CONT_JMP;
-		}
-		CONT;
-	JMP_JSGT_X:
-		if (((s64) DST) > ((s64) SRC)) {
-			insn += insn->off;
-			CONT_JMP;
-		}
-		CONT;
-	JMP_JSGT_K:
-		if (((s64) DST) > ((s64) IMM)) {
-			insn += insn->off;
-			CONT_JMP;
-		}
-		CONT;
-	JMP_JSGE_X:
-		if (((s64) DST) >= ((s64) SRC)) {
-			insn += insn->off;
-			CONT_JMP;
-		}
-		CONT;
-	JMP_JSGE_K:
-		if (((s64) DST) >= ((s64) IMM)) {
-			insn += insn->off;
-			CONT_JMP;
-		}
-		CONT;
-	JMP_JSET_X:
-		if (DST & SRC) {
-			insn += insn->off;
-			CONT_JMP;
-		}
-		CONT;
-	JMP_JSET_K:
-		if (DST & IMM) {
-			insn += insn->off;
-			CONT_JMP;
-		}
-		CONT;
-	JMP_EXIT:
-		return BPF_R0;
-
-	/* STX and ST and LDX*/
-#define LDST(SIZEOP, SIZE)						\
-	STX_MEM_##SIZEOP:						\
-		*(SIZE *)(unsigned long) (DST + insn->off) = SRC;	\
-		CONT;							\
-	ST_MEM_##SIZEOP:						\
-		*(SIZE *)(unsigned long) (DST + insn->off) = IMM;	\
-		CONT;							\
-	LDX_MEM_##SIZEOP:						\
-		DST = *(SIZE *)(unsigned long) (SRC + insn->off);	\
-		CONT;
-
-	LDST(B,   u8)
-	LDST(H,  u16)
-	LDST(W,  u32)
-	LDST(DW, u64)
-#undef LDST
-	STX_XADD_W: /* lock xadd *(u32 *)(dst_reg + off16) += src_reg */
-		atomic_add((u32) SRC, (atomic_t *)(unsigned long)
-			   (DST + insn->off));
-		CONT;
-	STX_XADD_DW: /* lock xadd *(u64 *)(dst_reg + off16) += src_reg */
-		atomic64_add((u64) SRC, (atomic64_t *)(unsigned long)
-			     (DST + insn->off));
-		CONT;
-	LD_ABS_W: /* BPF_R0 = ntohl(*(u32 *) (skb->data + imm32)) */
-		off = IMM;
-load_word:
-		/* BPF_LD + BPD_ABS and BPF_LD + BPF_IND insns are
-		 * only appearing in the programs where ctx ==
-		 * skb. All programs keep 'ctx' in regs[BPF_REG_CTX]
-		 * == BPF_R6, bpf_convert_filter() saves it in BPF_R6,
-		 * internal BPF verifier will check that BPF_R6 ==
-		 * ctx.
-		 *
-		 * BPF_ABS and BPF_IND are wrappers of function calls,
-		 * so they scratch BPF_R1-BPF_R5 registers, preserve
-		 * BPF_R6-BPF_R9, and store return value into BPF_R0.
-		 *
-		 * Implicit input:
-		 *   ctx == skb == BPF_R6 == CTX
-		 *
-		 * Explicit input:
-		 *   SRC == any register
-		 *   IMM == 32-bit immediate
-		 *
-		 * Output:
-		 *   BPF_R0 - 8/16/32-bit skb data converted to cpu endianness
-		 */
-
-		ptr = bpf_load_pointer((struct sk_buff *) (unsigned long) CTX, off, 4, &tmp);
-		if (likely(ptr != NULL)) {
-			BPF_R0 = get_unaligned_be32(ptr);
-			CONT;
-		}
-
-		return 0;
-	LD_ABS_H: /* BPF_R0 = ntohs(*(u16 *) (skb->data + imm32)) */
-		off = IMM;
-load_half:
-		ptr = bpf_load_pointer((struct sk_buff *) (unsigned long) CTX, off, 2, &tmp);
-		if (likely(ptr != NULL)) {
-			BPF_R0 = get_unaligned_be16(ptr);
-			CONT;
-		}
-
-		return 0;
-	LD_ABS_B: /* BPF_R0 = *(u8 *) (skb->data + imm32) */
-		off = IMM;
-load_byte:
-		ptr = bpf_load_pointer((struct sk_buff *) (unsigned long) CTX, off, 1, &tmp);
-		if (likely(ptr != NULL)) {
-			BPF_R0 = *(u8 *)ptr;
-			CONT;
-		}
-
-		return 0;
-	LD_IND_W: /* BPF_R0 = ntohl(*(u32 *) (skb->data + src_reg + imm32)) */
-		off = IMM + SRC;
-		goto load_word;
-	LD_IND_H: /* BPF_R0 = ntohs(*(u16 *) (skb->data + src_reg + imm32)) */
-		off = IMM + SRC;
-		goto load_half;
-	LD_IND_B: /* BPF_R0 = *(u8 *) (skb->data + src_reg + imm32) */
-		off = IMM + SRC;
-		goto load_byte;
-
-	default_label:
-		/* If we ever reach this, we have a bug somewhere. */
-		WARN_RATELIMIT(1, "unknown opcode %02x\n", insn->code);
-		return 0;
-}
-STACK_FRAME_NON_STANDARD(__bpf_prog_run); /* jump table */
-
 bool bpf_prog_array_compatible(struct bpf_array *array,
 			       const struct bpf_prog *fp)
 {
diff --git a/kernel/bpf/vm.c b/kernel/bpf/vm.c
new file mode 100644
index 0000000..45a2880
--- /dev/null
+++ b/kernel/bpf/vm.c
@@ -0,0 +1,492 @@
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include <asm/unaligned.h>
+#include <linux/byteorder/generic.h>
+#include <linux/ratelimit.h>
+#include <linux/compiler.h>
+#include <linux/export.h>
+#include <linux/filter.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
+#include <linux/frame.h>
+#include <linux/bpf.h>
+
+/* Registers */
+#define BPF_R0	regs[BPF_REG_0]
+#define BPF_R1	regs[BPF_REG_1]
+#define BPF_R2	regs[BPF_REG_2]
+#define BPF_R3	regs[BPF_REG_3]
+#define BPF_R4	regs[BPF_REG_4]
+#define BPF_R5	regs[BPF_REG_5]
+#define BPF_R6	regs[BPF_REG_6]
+#define BPF_R7	regs[BPF_REG_7]
+#define BPF_R8	regs[BPF_REG_8]
+#define BPF_R9	regs[BPF_REG_9]
+#define BPF_R10	regs[BPF_REG_10]
+
+/* Named registers */
+#define DST	regs[insn->dst_reg]
+#define SRC	regs[insn->src_reg]
+#define FP	regs[BPF_REG_FP]
+#define ARG1	regs[BPF_REG_ARG1]
+#define CTX	regs[BPF_REG_CTX]
+#define IMM	insn->imm
+
+unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn)
+{
+	u64 stack[MAX_BPF_STACK / sizeof(u64)];
+	u64 regs[MAX_BPF_REG], tmp;
+	static const void *jumptable[256] = {
+		[0 ... 255] = &&default_label,
+		/* Now overwrite non-defaults ... */
+		/* 32 bit ALU operations */
+		[BPF_ALU | BPF_ADD | BPF_X] = &&ALU_ADD_X,
+		[BPF_ALU | BPF_ADD | BPF_K] = &&ALU_ADD_K,
+		[BPF_ALU | BPF_SUB | BPF_X] = &&ALU_SUB_X,
+		[BPF_ALU | BPF_SUB | BPF_K] = &&ALU_SUB_K,
+		[BPF_ALU | BPF_AND | BPF_X] = &&ALU_AND_X,
+		[BPF_ALU | BPF_AND | BPF_K] = &&ALU_AND_K,
+		[BPF_ALU | BPF_OR | BPF_X]  = &&ALU_OR_X,
+		[BPF_ALU | BPF_OR | BPF_K]  = &&ALU_OR_K,
+		[BPF_ALU | BPF_LSH | BPF_X] = &&ALU_LSH_X,
+		[BPF_ALU | BPF_LSH | BPF_K] = &&ALU_LSH_K,
+		[BPF_ALU | BPF_RSH | BPF_X] = &&ALU_RSH_X,
+		[BPF_ALU | BPF_RSH | BPF_K] = &&ALU_RSH_K,
+		[BPF_ALU | BPF_XOR | BPF_X] = &&ALU_XOR_X,
+		[BPF_ALU | BPF_XOR | BPF_K] = &&ALU_XOR_K,
+		[BPF_ALU | BPF_MUL | BPF_X] = &&ALU_MUL_X,
+		[BPF_ALU | BPF_MUL | BPF_K] = &&ALU_MUL_K,
+		[BPF_ALU | BPF_MOV | BPF_X] = &&ALU_MOV_X,
+		[BPF_ALU | BPF_MOV | BPF_K] = &&ALU_MOV_K,
+		[BPF_ALU | BPF_DIV | BPF_X] = &&ALU_DIV_X,
+		[BPF_ALU | BPF_DIV | BPF_K] = &&ALU_DIV_K,
+		[BPF_ALU | BPF_MOD | BPF_X] = &&ALU_MOD_X,
+		[BPF_ALU | BPF_MOD | BPF_K] = &&ALU_MOD_K,
+		[BPF_ALU | BPF_NEG] = &&ALU_NEG,
+		[BPF_ALU | BPF_END | BPF_TO_BE] = &&ALU_END_TO_BE,
+		[BPF_ALU | BPF_END | BPF_TO_LE] = &&ALU_END_TO_LE,
+		/* 64 bit ALU operations */
+		[BPF_ALU64 | BPF_ADD | BPF_X] = &&ALU64_ADD_X,
+		[BPF_ALU64 | BPF_ADD | BPF_K] = &&ALU64_ADD_K,
+		[BPF_ALU64 | BPF_SUB | BPF_X] = &&ALU64_SUB_X,
+		[BPF_ALU64 | BPF_SUB | BPF_K] = &&ALU64_SUB_K,
+		[BPF_ALU64 | BPF_AND | BPF_X] = &&ALU64_AND_X,
+		[BPF_ALU64 | BPF_AND | BPF_K] = &&ALU64_AND_K,
+		[BPF_ALU64 | BPF_OR | BPF_X] = &&ALU64_OR_X,
+		[BPF_ALU64 | BPF_OR | BPF_K] = &&ALU64_OR_K,
+		[BPF_ALU64 | BPF_LSH | BPF_X] = &&ALU64_LSH_X,
+		[BPF_ALU64 | BPF_LSH | BPF_K] = &&ALU64_LSH_K,
+		[BPF_ALU64 | BPF_RSH | BPF_X] = &&ALU64_RSH_X,
+		[BPF_ALU64 | BPF_RSH | BPF_K] = &&ALU64_RSH_K,
+		[BPF_ALU64 | BPF_XOR | BPF_X] = &&ALU64_XOR_X,
+		[BPF_ALU64 | BPF_XOR | BPF_K] = &&ALU64_XOR_K,
+		[BPF_ALU64 | BPF_MUL | BPF_X] = &&ALU64_MUL_X,
+		[BPF_ALU64 | BPF_MUL | BPF_K] = &&ALU64_MUL_K,
+		[BPF_ALU64 | BPF_MOV | BPF_X] = &&ALU64_MOV_X,
+		[BPF_ALU64 | BPF_MOV | BPF_K] = &&ALU64_MOV_K,
+		[BPF_ALU64 | BPF_ARSH | BPF_X] = &&ALU64_ARSH_X,
+		[BPF_ALU64 | BPF_ARSH | BPF_K] = &&ALU64_ARSH_K,
+		[BPF_ALU64 | BPF_DIV | BPF_X] = &&ALU64_DIV_X,
+		[BPF_ALU64 | BPF_DIV | BPF_K] = &&ALU64_DIV_K,
+		[BPF_ALU64 | BPF_MOD | BPF_X] = &&ALU64_MOD_X,
+		[BPF_ALU64 | BPF_MOD | BPF_K] = &&ALU64_MOD_K,
+		[BPF_ALU64 | BPF_NEG] = &&ALU64_NEG,
+		/* Call instruction */
+		[BPF_JMP | BPF_CALL] = &&JMP_CALL,
+		[BPF_JMP | BPF_CALL | BPF_X] = &&JMP_TAIL_CALL,
+		/* Jumps */
+		[BPF_JMP | BPF_JA] = &&JMP_JA,
+		[BPF_JMP | BPF_JEQ | BPF_X] = &&JMP_JEQ_X,
+		[BPF_JMP | BPF_JEQ | BPF_K] = &&JMP_JEQ_K,
+		[BPF_JMP | BPF_JNE | BPF_X] = &&JMP_JNE_X,
+		[BPF_JMP | BPF_JNE | BPF_K] = &&JMP_JNE_K,
+		[BPF_JMP | BPF_JGT | BPF_X] = &&JMP_JGT_X,
+		[BPF_JMP | BPF_JGT | BPF_K] = &&JMP_JGT_K,
+		[BPF_JMP | BPF_JGE | BPF_X] = &&JMP_JGE_X,
+		[BPF_JMP | BPF_JGE | BPF_K] = &&JMP_JGE_K,
+		[BPF_JMP | BPF_JSGT | BPF_X] = &&JMP_JSGT_X,
+		[BPF_JMP | BPF_JSGT | BPF_K] = &&JMP_JSGT_K,
+		[BPF_JMP | BPF_JSGE | BPF_X] = &&JMP_JSGE_X,
+		[BPF_JMP | BPF_JSGE | BPF_K] = &&JMP_JSGE_K,
+		[BPF_JMP | BPF_JSET | BPF_X] = &&JMP_JSET_X,
+		[BPF_JMP | BPF_JSET | BPF_K] = &&JMP_JSET_K,
+		/* Program return */
+		[BPF_JMP | BPF_EXIT] = &&JMP_EXIT,
+		/* Store instructions */
+		[BPF_STX | BPF_MEM | BPF_B] = &&STX_MEM_B,
+		[BPF_STX | BPF_MEM | BPF_H] = &&STX_MEM_H,
+		[BPF_STX | BPF_MEM | BPF_W] = &&STX_MEM_W,
+		[BPF_STX | BPF_MEM | BPF_DW] = &&STX_MEM_DW,
+		[BPF_STX | BPF_XADD | BPF_W] = &&STX_XADD_W,
+		[BPF_STX | BPF_XADD | BPF_DW] = &&STX_XADD_DW,
+		[BPF_ST | BPF_MEM | BPF_B] = &&ST_MEM_B,
+		[BPF_ST | BPF_MEM | BPF_H] = &&ST_MEM_H,
+		[BPF_ST | BPF_MEM | BPF_W] = &&ST_MEM_W,
+		[BPF_ST | BPF_MEM | BPF_DW] = &&ST_MEM_DW,
+		/* Load instructions */
+		[BPF_LDX | BPF_MEM | BPF_B] = &&LDX_MEM_B,
+		[BPF_LDX | BPF_MEM | BPF_H] = &&LDX_MEM_H,
+		[BPF_LDX | BPF_MEM | BPF_W] = &&LDX_MEM_W,
+		[BPF_LDX | BPF_MEM | BPF_DW] = &&LDX_MEM_DW,
+		[BPF_LD | BPF_ABS | BPF_W] = &&LD_ABS_W,
+		[BPF_LD | BPF_ABS | BPF_H] = &&LD_ABS_H,
+		[BPF_LD | BPF_ABS | BPF_B] = &&LD_ABS_B,
+		[BPF_LD | BPF_IND | BPF_W] = &&LD_IND_W,
+		[BPF_LD | BPF_IND | BPF_H] = &&LD_IND_H,
+		[BPF_LD | BPF_IND | BPF_B] = &&LD_IND_B,
+		[BPF_LD | BPF_IMM | BPF_DW] = &&LD_IMM_DW,
+	};
+	u32 tail_call_cnt = 0;
+	void *ptr;
+	int off;
+
+#define CONT	 ({ insn++; goto select_insn; })
+#define CONT_JMP ({ insn++; goto select_insn; })
+
+	FP = (u64) (unsigned long) &stack[ARRAY_SIZE(stack)];
+	ARG1 = (u64) (unsigned long) ctx;
+
+select_insn:
+	goto *jumptable[insn->code];
+
+	/* ALU */
+#define ALU(OPCODE, OP)			\
+	ALU64_##OPCODE##_X:		\
+		DST = DST OP SRC;	\
+		CONT;			\
+	ALU_##OPCODE##_X:		\
+		DST = (u32) DST OP (u32) SRC;	\
+		CONT;			\
+	ALU64_##OPCODE##_K:		\
+		DST = DST OP IMM;		\
+		CONT;			\
+	ALU_##OPCODE##_K:		\
+		DST = (u32) DST OP (u32) IMM;	\
+		CONT;
+
+	ALU(ADD,  +)
+	ALU(SUB,  -)
+	ALU(AND,  &)
+	ALU(OR,   |)
+	ALU(LSH, <<)
+	ALU(RSH, >>)
+	ALU(XOR,  ^)
+	ALU(MUL,  *)
+#undef ALU
+	ALU_NEG:
+		DST = (u32) -DST;
+		CONT;
+	ALU64_NEG:
+		DST = -DST;
+		CONT;
+	ALU_MOV_X:
+		DST = (u32) SRC;
+		CONT;
+	ALU_MOV_K:
+		DST = (u32) IMM;
+		CONT;
+	ALU64_MOV_X:
+		DST = SRC;
+		CONT;
+	ALU64_MOV_K:
+		DST = IMM;
+		CONT;
+	LD_IMM_DW:
+		DST = (u64) (u32) insn[0].imm | ((u64) (u32) insn[1].imm) << 32;
+		insn++;
+		CONT;
+	ALU64_ARSH_X:
+		(*(s64 *) &DST) >>= SRC;
+		CONT;
+	ALU64_ARSH_K:
+		(*(s64 *) &DST) >>= IMM;
+		CONT;
+	ALU64_MOD_X:
+		if (unlikely(SRC == 0))
+			return 0;
+		div64_u64_rem(DST, SRC, &tmp);
+		DST = tmp;
+		CONT;
+	ALU_MOD_X:
+		if (unlikely(SRC == 0))
+			return 0;
+		tmp = (u32) DST;
+		DST = do_div(tmp, (u32) SRC);
+		CONT;
+	ALU64_MOD_K:
+		div64_u64_rem(DST, IMM, &tmp);
+		DST = tmp;
+		CONT;
+	ALU_MOD_K:
+		tmp = (u32) DST;
+		DST = do_div(tmp, (u32) IMM);
+		CONT;
+	ALU64_DIV_X:
+		if (unlikely(SRC == 0))
+			return 0;
+		DST = div64_u64(DST, SRC);
+		CONT;
+	ALU_DIV_X:
+		if (unlikely(SRC == 0))
+			return 0;
+		tmp = (u32) DST;
+		do_div(tmp, (u32) SRC);
+		DST = (u32) tmp;
+		CONT;
+	ALU64_DIV_K:
+		DST = div64_u64(DST, IMM);
+		CONT;
+	ALU_DIV_K:
+		tmp = (u32) DST;
+		do_div(tmp, (u32) IMM);
+		DST = (u32) tmp;
+		CONT;
+	ALU_END_TO_BE:
+		switch (IMM) {
+		case 16:
+			DST = (__force u16) cpu_to_be16(DST);
+			break;
+		case 32:
+			DST = (__force u32) cpu_to_be32(DST);
+			break;
+		case 64:
+			DST = (__force u64) cpu_to_be64(DST);
+			break;
+		}
+		CONT;
+	ALU_END_TO_LE:
+		switch (IMM) {
+		case 16:
+			DST = (__force u16) cpu_to_le16(DST);
+			break;
+		case 32:
+			DST = (__force u32) cpu_to_le32(DST);
+			break;
+		case 64:
+			DST = (__force u64) cpu_to_le64(DST);
+			break;
+		}
+		CONT;
+
+	/* CALL */
+	JMP_CALL:
+		/* Function call scratches BPF_R1-BPF_R5 registers,
+		 * preserves BPF_R6-BPF_R9, and stores return value
+		 * into BPF_R0.
+		 */
+		BPF_R0 = (__bpf_call_base + insn->imm)(BPF_R1, BPF_R2, BPF_R3,
+						       BPF_R4, BPF_R5);
+		CONT;
+
+	JMP_TAIL_CALL: {
+		struct bpf_map *map = (struct bpf_map *) (unsigned long) BPF_R2;
+		struct bpf_array *array = container_of(map, struct bpf_array, map);
+		struct bpf_prog *prog;
+		u64 index = BPF_R3;
+
+		if (unlikely(index >= array->map.max_entries))
+			goto out;
+
+		if (unlikely(tail_call_cnt > MAX_TAIL_CALL_CNT))
+			goto out;
+
+		tail_call_cnt++;
+
+		prog = READ_ONCE(array->ptrs[index]);
+		if (unlikely(!prog))
+			goto out;
+
+		/* ARG1 at this point is guaranteed to point to CTX from
+		 * the verifier side due to the fact that the tail call is
+		 * handeled like a helper, that is, bpf_tail_call_proto,
+		 * where arg1_type is ARG_PTR_TO_CTX.
+		 */
+		insn = prog->insnsi;
+		goto select_insn;
+out:
+		CONT;
+	}
+	/* JMP */
+	JMP_JA:
+		insn += insn->off;
+		CONT;
+	JMP_JEQ_X:
+		if (DST == SRC) {
+			insn += insn->off;
+			CONT_JMP;
+		}
+		CONT;
+	JMP_JEQ_K:
+		if (DST == IMM) {
+			insn += insn->off;
+			CONT_JMP;
+		}
+		CONT;
+	JMP_JNE_X:
+		if (DST != SRC) {
+			insn += insn->off;
+			CONT_JMP;
+		}
+		CONT;
+	JMP_JNE_K:
+		if (DST != IMM) {
+			insn += insn->off;
+			CONT_JMP;
+		}
+		CONT;
+	JMP_JGT_X:
+		if (DST > SRC) {
+			insn += insn->off;
+			CONT_JMP;
+		}
+		CONT;
+	JMP_JGT_K:
+		if (DST > IMM) {
+			insn += insn->off;
+			CONT_JMP;
+		}
+		CONT;
+	JMP_JGE_X:
+		if (DST >= SRC) {
+			insn += insn->off;
+			CONT_JMP;
+		}
+		CONT;
+	JMP_JGE_K:
+		if (DST >= IMM) {
+			insn += insn->off;
+			CONT_JMP;
+		}
+		CONT;
+	JMP_JSGT_X:
+		if (((s64) DST) > ((s64) SRC)) {
+			insn += insn->off;
+			CONT_JMP;
+		}
+		CONT;
+	JMP_JSGT_K:
+		if (((s64) DST) > ((s64) IMM)) {
+			insn += insn->off;
+			CONT_JMP;
+		}
+		CONT;
+	JMP_JSGE_X:
+		if (((s64) DST) >= ((s64) SRC)) {
+			insn += insn->off;
+			CONT_JMP;
+		}
+		CONT;
+	JMP_JSGE_K:
+		if (((s64) DST) >= ((s64) IMM)) {
+			insn += insn->off;
+			CONT_JMP;
+		}
+		CONT;
+	JMP_JSET_X:
+		if (DST & SRC) {
+			insn += insn->off;
+			CONT_JMP;
+		}
+		CONT;
+	JMP_JSET_K:
+		if (DST & IMM) {
+			insn += insn->off;
+			CONT_JMP;
+		}
+		CONT;
+	JMP_EXIT:
+		return BPF_R0;
+
+	/* STX and ST and LDX*/
+#define LDST(SIZEOP, SIZE)						\
+	STX_MEM_##SIZEOP:						\
+		*(SIZE *)(unsigned long) (DST + insn->off) = SRC;	\
+		CONT;							\
+	ST_MEM_##SIZEOP:						\
+		*(SIZE *)(unsigned long) (DST + insn->off) = IMM;	\
+		CONT;							\
+	LDX_MEM_##SIZEOP:						\
+		DST = *(SIZE *)(unsigned long) (SRC + insn->off);	\
+		CONT;
+
+	LDST(B,   u8)
+	LDST(H,  u16)
+	LDST(W,  u32)
+	LDST(DW, u64)
+#undef LDST
+	STX_XADD_W: /* lock xadd *(u32 *)(dst_reg + off16) += src_reg */
+		atomic_add((u32) SRC, (atomic_t *)(unsigned long)
+			   (DST + insn->off));
+		CONT;
+	STX_XADD_DW: /* lock xadd *(u64 *)(dst_reg + off16) += src_reg */
+		atomic64_add((u64) SRC, (atomic64_t *)(unsigned long)
+			     (DST + insn->off));
+		CONT;
+	LD_ABS_W: /* BPF_R0 = ntohl(*(u32 *) (skb->data + imm32)) */
+		off = IMM;
+load_word:
+		/* BPF_LD + BPD_ABS and BPF_LD + BPF_IND insns are
+		 * only appearing in the programs where ctx ==
+		 * skb. All programs keep 'ctx' in regs[BPF_REG_CTX]
+		 * == BPF_R6, bpf_convert_filter() saves it in BPF_R6,
+		 * internal BPF verifier will check that BPF_R6 ==
+		 * ctx.
+		 *
+		 * BPF_ABS and BPF_IND are wrappers of function calls,
+		 * so they scratch BPF_R1-BPF_R5 registers, preserve
+		 * BPF_R6-BPF_R9, and store return value into BPF_R0.
+		 *
+		 * Implicit input:
+		 *   ctx == skb == BPF_R6 == CTX
+		 *
+		 * Explicit input:
+		 *   SRC == any register
+		 *   IMM == 32-bit immediate
+		 *
+		 * Output:
+		 *   BPF_R0 - 8/16/32-bit skb data converted to cpu endianness
+		 */
+
+		ptr = bpf_load_pointer((struct sk_buff *) (unsigned long) CTX, off, 4, &tmp);
+		if (likely(ptr != NULL)) {
+			BPF_R0 = get_unaligned_be32(ptr);
+			CONT;
+		}
+
+		return 0;
+	LD_ABS_H: /* BPF_R0 = ntohs(*(u16 *) (skb->data + imm32)) */
+		off = IMM;
+load_half:
+		ptr = bpf_load_pointer((struct sk_buff *) (unsigned long) CTX, off, 2, &tmp);
+		if (likely(ptr != NULL)) {
+			BPF_R0 = get_unaligned_be16(ptr);
+			CONT;
+		}
+
+		return 0;
+	LD_ABS_B: /* BPF_R0 = *(u8 *) (skb->data + imm32) */
+		off = IMM;
+load_byte:
+		ptr = bpf_load_pointer((struct sk_buff *) (unsigned long) CTX, off, 1, &tmp);
+		if (likely(ptr != NULL)) {
+			BPF_R0 = *(u8 *)ptr;
+			CONT;
+		}
+
+		return 0;
+	LD_IND_W: /* BPF_R0 = ntohl(*(u32 *) (skb->data + src_reg + imm32)) */
+		off = IMM + SRC;
+		goto load_word;
+	LD_IND_H: /* BPF_R0 = ntohs(*(u16 *) (skb->data + src_reg + imm32)) */
+		off = IMM + SRC;
+		goto load_half;
+	LD_IND_B: /* BPF_R0 = *(u8 *) (skb->data + src_reg + imm32) */
+		off = IMM + SRC;
+		goto load_byte;
+
+	default_label:
+		/* If we ever reach this, we have a bug somewhere. */
+		WARN_RATELIMIT(1, "unknown opcode %02x\n", insn->code);
+		return 0;
+}
+STACK_FRAME_NON_STANDARD(__bpf_prog_run); /* jump table */
-- 
1.8.5.2

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

* [RFC PATCH v2 04/26] bpf: extract jmp and default handler and introduce UBPF_BUILD flag
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
                   ` (2 preceding siblings ...)
  2016-06-26 11:20 ` [RFC PATCH v2 03/26] bpf: split __bpf_prog_run code into new file He Kuang
@ 2016-06-26 11:20 ` He Kuang
  2016-06-26 11:20 ` [RFC PATCH v2 05/26] tools include: Sync math64.h and div64.h He Kuang
                   ` (22 subsequent siblings)
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:20 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

This patch is a preparation for compiling bpf vm into external
libraries. Parts of the instruction handlers are wrapped into macros
or functions so that userspace libraries can override them. There's no
functionality change without UBPF_BUILD flag.

Signed-off-by: He Kuang <hekuang@huawei.com>
Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 kernel/bpf/vm.c | 94 ++++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 56 insertions(+), 38 deletions(-)

diff --git a/kernel/bpf/vm.c b/kernel/bpf/vm.c
index 45a2880..add5669 100644
--- a/kernel/bpf/vm.c
+++ b/kernel/bpf/vm.c
@@ -1,8 +1,6 @@
 #include <linux/types.h>
 #include <asm/byteorder.h>
-#include <asm/unaligned.h>
 #include <linux/byteorder/generic.h>
-#include <linux/ratelimit.h>
 #include <linux/compiler.h>
 #include <linux/export.h>
 #include <linux/filter.h>
@@ -11,6 +9,11 @@
 #include <linux/frame.h>
 #include <linux/bpf.h>
 
+#ifndef UBPF_BUILD
+#include <asm/unaligned.h>
+#include <linux/ratelimit.h>
+#endif
+
 /* Registers */
 #define BPF_R0	regs[BPF_REG_0]
 #define BPF_R1	regs[BPF_REG_1]
@@ -32,6 +35,49 @@
 #define CTX	regs[BPF_REG_CTX]
 #define IMM	insn->imm
 
+#ifndef UBPF_BUILD
+/* Function call scratches BPF_R1-BPF_R5 registers,
+ * preserves BPF_R6-BPF_R9, and stores return value
+ * into BPF_R0.
+ */
+#define bpf_vm_jmp_call_handler(regs, ctx, insn)			\
+	(BPF_R0 = (__bpf_call_base + insn->imm)(BPF_R1, BPF_R2, BPF_R3,	\
+						BPF_R4, BPF_R5))
+
+/* If we ever reach this, we have a bug somewhere. */
+#define bpf_vm_default_label_handler(ctx, insn)			\
+	WARN_RATELIMIT(1, "unknown opcode %02x\n", insn->code)
+
+static inline int bpf_vm_jmp_tail_call_handler(u64 *regs, u32 *p_tail_call_cnt,
+					       const struct bpf_insn **p_insn)
+{
+	struct bpf_map *map = (struct bpf_map *) (unsigned long) BPF_R2;
+	struct bpf_array *array = container_of(map, struct bpf_array, map);
+	struct bpf_prog *prog;
+	u64 index = BPF_R3;
+
+	if (unlikely(index >= array->map.max_entries))
+		return -1;
+
+	if (unlikely(*p_tail_call_cnt > MAX_TAIL_CALL_CNT))
+		return -1;
+
+	(*p_tail_call_cnt)++;
+
+	prog = READ_ONCE(array->ptrs[index]);
+	if (unlikely(!prog))
+		return -1;
+
+	/* ARG1 at this point is guaranteed to point to CTX from
+	 * the verifier side due to the fact that the tail call is
+	 * handeled like a helper, that is, bpf_tail_call_proto,
+	 * where arg1_type is ARG_PTR_TO_CTX.
+	 */
+	*p_insn = prog->insnsi;
+	return 0;
+}
+#endif /* UBPF_BUILD */
+
 unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn)
 {
 	u64 stack[MAX_BPF_STACK / sizeof(u64)];
@@ -270,42 +316,15 @@ select_insn:
 
 	/* CALL */
 	JMP_CALL:
-		/* Function call scratches BPF_R1-BPF_R5 registers,
-		 * preserves BPF_R6-BPF_R9, and stores return value
-		 * into BPF_R0.
-		 */
-		BPF_R0 = (__bpf_call_base + insn->imm)(BPF_R1, BPF_R2, BPF_R3,
-						       BPF_R4, BPF_R5);
+		bpf_vm_jmp_call_handler(regs, ctx, insn);
 		CONT;
 
-	JMP_TAIL_CALL: {
-		struct bpf_map *map = (struct bpf_map *) (unsigned long) BPF_R2;
-		struct bpf_array *array = container_of(map, struct bpf_array, map);
-		struct bpf_prog *prog;
-		u64 index = BPF_R3;
-
-		if (unlikely(index >= array->map.max_entries))
-			goto out;
-
-		if (unlikely(tail_call_cnt > MAX_TAIL_CALL_CNT))
-			goto out;
-
-		tail_call_cnt++;
-
-		prog = READ_ONCE(array->ptrs[index]);
-		if (unlikely(!prog))
-			goto out;
-
-		/* ARG1 at this point is guaranteed to point to CTX from
-		 * the verifier side due to the fact that the tail call is
-		 * handeled like a helper, that is, bpf_tail_call_proto,
-		 * where arg1_type is ARG_PTR_TO_CTX.
-		 */
-		insn = prog->insnsi;
-		goto select_insn;
-out:
-		CONT;
-	}
+	JMP_TAIL_CALL:
+		tmp = bpf_vm_jmp_tail_call_handler(regs, &tail_call_cnt, &insn);
+		if (tmp)
+			CONT;
+		else
+			goto select_insn;
 	/* JMP */
 	JMP_JA:
 		insn += insn->off;
@@ -485,8 +504,7 @@ load_byte:
 		goto load_byte;
 
 	default_label:
-		/* If we ever reach this, we have a bug somewhere. */
-		WARN_RATELIMIT(1, "unknown opcode %02x\n", insn->code);
+		bpf_vm_default_label_handler(ctx, insn);
 		return 0;
 }
 STACK_FRAME_NON_STANDARD(__bpf_prog_run); /* jump table */
-- 
1.8.5.2

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

* [RFC PATCH v2 05/26] tools include: Sync math64.h and div64.h
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
                   ` (3 preceding siblings ...)
  2016-06-26 11:20 ` [RFC PATCH v2 04/26] bpf: extract jmp and default handler and introduce UBPF_BUILD flag He Kuang
@ 2016-06-26 11:20 ` He Kuang
  2016-06-26 21:08   ` Nilay Vaish
  2016-06-26 11:20 ` [RFC PATCH v2 06/26] tools include: Add (atomic|atomic64)_add implementation from the kernel sources He Kuang
                   ` (21 subsequent siblings)
  26 siblings, 1 reply; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:20 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

From: Wang Nan <wangnan0@huawei.com>

This patch copies "include/linux/math64.h" into
"tools/include/linux/math64.h" and copies
"include/asm-generic/div64.h" into
"tools/include/asm-generic/div64.h", to enable other libraries use
arithmetic operation defined in them.

tools/perf/MANIFEST is also updated for 'make perf-*-src-pkg'.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Signed-off-by: He Kuang <hekuang@huawei.com>
---
 tools/include/asm-generic/div64.h | 234 ++++++++++++++++++++++++++++++++++++
 tools/include/linux/math64.h      | 247 ++++++++++++++++++++++++++++++++++++++
 tools/perf/MANIFEST               |   2 +
 3 files changed, 483 insertions(+)
 create mode 100644 tools/include/asm-generic/div64.h
 create mode 100644 tools/include/linux/math64.h

diff --git a/tools/include/asm-generic/div64.h b/tools/include/asm-generic/div64.h
new file mode 100644
index 0000000..be724b2
--- /dev/null
+++ b/tools/include/asm-generic/div64.h
@@ -0,0 +1,234 @@
+#ifndef _TOOLS_LINUX_ASM_GENERIC_DIV64_H
+#define _TOOLS_LINUX_ASM_GENERIC_DIV64_H
+/*
+ * Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com>
+ * Based on former asm-ppc/div64.h and asm-m68knommu/div64.h
+ *
+ * Optimization for constant divisors on 32-bit machines:
+ * Copyright (C) 2006-2015 Nicolas Pitre
+ *
+ * The semantics of do_div() are:
+ *
+ * uint32_t do_div(uint64_t *n, uint32_t base)
+ * {
+ * 	uint32_t remainder = *n % base;
+ * 	*n = *n / base;
+ * 	return remainder;
+ * }
+ *
+ * NOTE: macro parameter n is evaluated multiple times,
+ *       beware of side effects!
+ */
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+
+#if BITS_PER_LONG == 64
+
+# define do_div(n,base) ({					\
+	uint32_t __base = (base);				\
+	uint32_t __rem;						\
+	__rem = ((uint64_t)(n)) % __base;			\
+	(n) = ((uint64_t)(n)) / __base;				\
+	__rem;							\
+ })
+
+#elif BITS_PER_LONG == 32
+
+#include <linux/log2.h>
+
+/*
+ * If the divisor happens to be constant, we determine the appropriate
+ * inverse at compile time to turn the division into a few inline
+ * multiplications which ought to be much faster. And yet only if compiling
+ * with a sufficiently recent gcc version to perform proper 64-bit constant
+ * propagation.
+ *
+ * (It is unfortunate that gcc doesn't perform all this internally.)
+ */
+
+#ifndef __div64_const32_is_OK
+#define __div64_const32_is_OK (__GNUC__ >= 4)
+#endif
+
+#define __div64_const32(n, ___b)					\
+({									\
+	/*								\
+	 * Multiplication by reciprocal of b: n / b = n * (p / b) / p	\
+	 *								\
+	 * We rely on the fact that most of this code gets optimized	\
+	 * away at compile time due to constant propagation and only	\
+	 * a few multiplication instructions should remain.		\
+	 * Hence this monstrous macro (static inline doesn't always	\
+	 * do the trick here).						\
+	 */								\
+	uint64_t ___res, ___x, ___t, ___m, ___n = (n);			\
+	uint32_t ___p, ___bias;						\
+									\
+	/* determine MSB of b */					\
+	___p = 1 << ilog2(___b);					\
+									\
+	/* compute m = ((p << 64) + b - 1) / b */			\
+	___m = (~0ULL / ___b) * ___p;					\
+	___m += (((~0ULL % ___b + 1) * ___p) + ___b - 1) / ___b;	\
+									\
+	/* one less than the dividend with highest result */		\
+	___x = ~0ULL / ___b * ___b - 1;					\
+									\
+	/* test our ___m with res = m * x / (p << 64) */		\
+	___res = ((___m & 0xffffffff) * (___x & 0xffffffff)) >> 32;	\
+	___t = ___res += (___m & 0xffffffff) * (___x >> 32);		\
+	___res += (___x & 0xffffffff) * (___m >> 32);			\
+	___t = (___res < ___t) ? (1ULL << 32) : 0;			\
+	___res = (___res >> 32) + ___t;					\
+	___res += (___m >> 32) * (___x >> 32);				\
+	___res /= ___p;							\
+									\
+	/* Now sanitize and optimize what we've got. */			\
+	if (~0ULL % (___b / (___b & -___b)) == 0) {			\
+		/* special case, can be simplified to ... */		\
+		___n /= (___b & -___b);					\
+		___m = ~0ULL / (___b / (___b & -___b));			\
+		___p = 1;						\
+		___bias = 1;						\
+	} else if (___res != ___x / ___b) {				\
+		/*							\
+		 * We can't get away without a bias to compensate	\
+		 * for bit truncation errors.  To avoid it we'd need an	\
+		 * additional bit to represent m which would overflow	\
+		 * a 64-bit variable.					\
+		 *							\
+		 * Instead we do m = p / b and n / b = (n * m + m) / p.	\
+		 */							\
+		___bias = 1;						\
+		/* Compute m = (p << 64) / b */				\
+		___m = (~0ULL / ___b) * ___p;				\
+		___m += ((~0ULL % ___b + 1) * ___p) / ___b;		\
+	} else {							\
+		/*							\
+		 * Reduce m / p, and try to clear bit 31 of m when	\
+		 * possible, otherwise that'll need extra overflow	\
+		 * handling later.					\
+		 */							\
+		uint32_t ___bits = -(___m & -___m);			\
+		___bits |= ___m >> 32;					\
+		___bits = (~___bits) << 1;				\
+		/*							\
+		 * If ___bits == 0 then setting bit 31 is  unavoidable.	\
+		 * Simply apply the maximum possible reduction in that	\
+		 * case. Otherwise the MSB of ___bits indicates the	\
+		 * best reduction we should apply.			\
+		 */							\
+		if (!___bits) {						\
+			___p /= (___m & -___m);				\
+			___m /= (___m & -___m);				\
+		} else {						\
+			___p >>= ilog2(___bits);			\
+			___m >>= ilog2(___bits);			\
+		}							\
+		/* No bias needed. */					\
+		___bias = 0;						\
+	}								\
+									\
+	/*								\
+	 * Now we have a combination of 2 conditions:			\
+	 *								\
+	 * 1) whether or not we need to apply a bias, and		\
+	 *								\
+	 * 2) whether or not there might be an overflow in the cross	\
+	 *    product determined by (___m & ((1 << 63) | (1 << 31))).	\
+	 *								\
+	 * Select the best way to do (m_bias + m * n) / (1 << 64).	\
+	 * From now on there will be actual runtime code generated.	\
+	 */								\
+	___res = __arch_xprod_64(___m, ___n, ___bias);			\
+									\
+	___res /= ___p;							\
+})
+
+#ifndef __arch_xprod_64
+/*
+ * Default C implementation for __arch_xprod_64()
+ *
+ * Prototype: uint64_t __arch_xprod_64(const uint64_t m, uint64_t n, bool bias)
+ * Semantic:  retval = ((bias ? m : 0) + m * n) >> 64
+ *
+ * The product is a 128-bit value, scaled down to 64 bits.
+ * Assuming constant propagation to optimize away unused conditional code.
+ * Architectures may provide their own optimized assembly implementation.
+ */
+static inline uint64_t __arch_xprod_64(const uint64_t m, uint64_t n, bool bias)
+{
+	uint32_t m_lo = m;
+	uint32_t m_hi = m >> 32;
+	uint32_t n_lo = n;
+	uint32_t n_hi = n >> 32;
+	uint64_t res, tmp;
+
+	if (!bias) {
+		res = ((uint64_t)m_lo * n_lo) >> 32;
+	} else if (!(m & ((1ULL << 63) | (1ULL << 31)))) {
+		/* there can't be any overflow here */
+		res = (m + (uint64_t)m_lo * n_lo) >> 32;
+	} else {
+		res = m + (uint64_t)m_lo * n_lo;
+		tmp = (res < m) ? (1ULL << 32) : 0;
+		res = (res >> 32) + tmp;
+	}
+
+	if (!(m & ((1ULL << 63) | (1ULL << 31)))) {
+		/* there can't be any overflow here */
+		res += (uint64_t)m_lo * n_hi;
+		res += (uint64_t)m_hi * n_lo;
+		res >>= 32;
+	} else {
+		tmp = res += (uint64_t)m_lo * n_hi;
+		res += (uint64_t)m_hi * n_lo;
+		tmp = (res < tmp) ? (1ULL << 32) : 0;
+		res = (res >> 32) + tmp;
+	}
+
+	res += (uint64_t)m_hi * n_hi;
+
+	return res;
+}
+#endif
+
+#ifndef __div64_32
+extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
+#endif
+
+/* The unnecessary pointer compare is there
+ * to check for type safety (n must be 64bit)
+ */
+# define do_div(n,base) ({				\
+	uint32_t __base = (base);			\
+	uint32_t __rem;					\
+	(void)(((typeof((n)) *)0) == ((uint64_t *)0));	\
+	if (__builtin_constant_p(__base) &&		\
+	    is_power_of_2(__base)) {			\
+		__rem = (n) & (__base - 1);		\
+		(n) >>= ilog2(__base);			\
+	} else if (__div64_const32_is_OK &&		\
+		   __builtin_constant_p(__base) &&	\
+		   __base != 0) {			\
+		uint32_t __res_lo, __n_lo = (n);	\
+		(n) = __div64_const32(n, __base);	\
+		/* the remainder can be computed with 32-bit regs */ \
+		__res_lo = (n);				\
+		__rem = __n_lo - __res_lo * __base;	\
+	} else if (likely(((n) >> 32) == 0)) {		\
+		__rem = (uint32_t)(n) % __base;		\
+		(n) = (uint32_t)(n) / __base;		\
+	} else 						\
+		__rem = __div64_32(&(n), __base);	\
+	__rem;						\
+ })
+
+#else /* BITS_PER_LONG == ?? */
+
+# error do_div() does not yet support the C64
+
+#endif /* BITS_PER_LONG */
+
+#endif /* _TOOLS_LINUX_ASM_GENERIC_DIV64_H */
diff --git a/tools/include/linux/math64.h b/tools/include/linux/math64.h
new file mode 100644
index 0000000..e823227
--- /dev/null
+++ b/tools/include/linux/math64.h
@@ -0,0 +1,247 @@
+#ifndef _TOOLS_LINUX_MATH64_H
+#define _TOOLS_LINUX_MATH64_H
+
+#include <linux/types.h>
+#include <linux/bitops.h> // for BITS_PER_LONG
+#include <asm-generic/div64.h>
+
+#if BITS_PER_LONG == 64
+
+#define div64_long(x, y) div64_s64((x), (y))
+#define div64_ul(x, y)   div64_u64((x), (y))
+
+/**
+ * div_u64_rem - unsigned 64bit divide with 32bit divisor with remainder
+ *
+ * This is commonly provided by 32bit archs to provide an optimized 64bit
+ * divide.
+ */
+static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
+{
+	*remainder = dividend % divisor;
+	return dividend / divisor;
+}
+
+/**
+ * div_s64_rem - signed 64bit divide with 32bit divisor with remainder
+ */
+static inline s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
+{
+	*remainder = dividend % divisor;
+	return dividend / divisor;
+}
+
+/**
+ * div64_u64_rem - unsigned 64bit divide with 64bit divisor and remainder
+ */
+static inline u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder)
+{
+	*remainder = dividend % divisor;
+	return dividend / divisor;
+}
+
+/**
+ * div64_u64 - unsigned 64bit divide with 64bit divisor
+ */
+static inline u64 div64_u64(u64 dividend, u64 divisor)
+{
+	return dividend / divisor;
+}
+
+/**
+ * div64_s64 - signed 64bit divide with 64bit divisor
+ */
+static inline s64 div64_s64(s64 dividend, s64 divisor)
+{
+	return dividend / divisor;
+}
+
+#elif BITS_PER_LONG == 32
+
+#define div64_long(x, y) div_s64((x), (y))
+#define div64_ul(x, y)   div_u64((x), (y))
+
+#ifndef div_u64_rem
+static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
+{
+	*remainder = do_div(dividend, divisor);
+	return dividend;
+}
+#endif
+
+#ifndef div_s64_rem
+extern s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder);
+#endif
+
+#ifndef div64_u64_rem
+extern u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder);
+#endif
+
+#ifndef div64_u64
+extern u64 div64_u64(u64 dividend, u64 divisor);
+#endif
+
+#ifndef div64_s64
+extern s64 div64_s64(s64 dividend, s64 divisor);
+#endif
+
+#endif /* BITS_PER_LONG */
+
+/**
+ * div_u64 - unsigned 64bit divide with 32bit divisor
+ *
+ * This is the most common 64bit divide and should be used if possible,
+ * as many 32bit archs can optimize this variant better than a full 64bit
+ * divide.
+ */
+#ifndef div_u64
+static inline u64 div_u64(u64 dividend, u32 divisor)
+{
+	u32 remainder;
+	return div_u64_rem(dividend, divisor, &remainder);
+}
+#endif
+
+/**
+ * div_s64 - signed 64bit divide with 32bit divisor
+ */
+#ifndef div_s64
+static inline s64 div_s64(s64 dividend, s32 divisor)
+{
+	s32 remainder;
+	return div_s64_rem(dividend, divisor, &remainder);
+}
+#endif
+
+u32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder);
+
+static __always_inline u32
+__iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder)
+{
+	u32 ret = 0;
+
+	while (dividend >= divisor) {
+		/* The following asm() prevents the compiler from
+		   optimising this loop into a modulo operation.  */
+		asm("" : "+rm"(dividend));
+
+		dividend -= divisor;
+		ret++;
+	}
+
+	*remainder = dividend;
+
+	return ret;
+}
+
+#if defined(CONFIG_ARCH_SUPPORTS_INT128) && defined(__SIZEOF_INT128__)
+
+#ifndef mul_u64_u32_shr
+static inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift)
+{
+	return (u64)(((unsigned __int128)a * mul) >> shift);
+}
+#endif /* mul_u64_u32_shr */
+
+#ifndef mul_u64_u64_shr
+static inline u64 mul_u64_u64_shr(u64 a, u64 mul, unsigned int shift)
+{
+	return (u64)(((unsigned __int128)a * mul) >> shift);
+}
+#endif /* mul_u64_u64_shr */
+
+#else
+
+#ifndef mul_u64_u32_shr
+static inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift)
+{
+	u32 ah, al;
+	u64 ret;
+
+	al = a;
+	ah = a >> 32;
+
+	ret = ((u64)al * mul) >> shift;
+	if (ah)
+		ret += ((u64)ah * mul) << (32 - shift);
+
+	return ret;
+}
+#endif /* mul_u64_u32_shr */
+
+#ifndef mul_u64_u64_shr
+static inline u64 mul_u64_u64_shr(u64 a, u64 b, unsigned int shift)
+{
+	union {
+		u64 ll;
+		struct {
+#ifdef __BIG_ENDIAN
+			u32 high, low;
+#else
+			u32 low, high;
+#endif
+		} l;
+	} rl, rm, rn, rh, a0, b0;
+	u64 c;
+
+	a0.ll = a;
+	b0.ll = b;
+
+	rl.ll = (u64)a0.l.low * b0.l.low;
+	rm.ll = (u64)a0.l.low * b0.l.high;
+	rn.ll = (u64)a0.l.high * b0.l.low;
+	rh.ll = (u64)a0.l.high * b0.l.high;
+
+	/*
+	 * Each of these lines computes a 64-bit intermediate result into "c",
+	 * starting at bits 32-95.  The low 32-bits go into the result of the
+	 * multiplication, the high 32-bits are carried into the next step.
+	 */
+	rl.l.high = c = (u64)rl.l.high + rm.l.low + rn.l.low;
+	rh.l.low = c = (c >> 32) + rm.l.high + rn.l.high + rh.l.low;
+	rh.l.high = (c >> 32) + rh.l.high;
+
+	/*
+	 * The 128-bit result of the multiplication is in rl.ll and rh.ll,
+	 * shift it right and throw away the high part of the result.
+	 */
+	if (shift == 0)
+		return rl.ll;
+	if (shift < 64)
+		return (rl.ll >> shift) | (rh.ll << (64 - shift));
+	return rh.ll >> (shift & 63);
+}
+#endif /* mul_u64_u64_shr */
+
+#endif
+
+#ifndef mul_u64_u32_div
+static inline u64 mul_u64_u32_div(u64 a, u32 mul, u32 divisor)
+{
+	union {
+		u64 ll;
+		struct {
+#ifdef __BIG_ENDIAN
+			u32 high, low;
+#else
+			u32 low, high;
+#endif
+		} l;
+	} u, rl, rh;
+
+	u.ll = a;
+	rl.ll = (u64)u.l.low * mul;
+	rh.ll = (u64)u.l.high * mul + rl.l.high;
+
+	/* Bits 32-63 of the result will be in rh.l.low. */
+	rl.l.high = do_div(rh.ll, divisor);
+
+	/* Bits 0-31 of the result will be in rl.l.low.	*/
+	do_div(rl.ll, divisor);
+
+	rl.l.high = rh.l.low;
+	return rl.ll;
+}
+#endif /* mul_u64_u32_div */
+
+#endif /* _TOOLS_LINUX_MATH64_H */
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 80ac3d4..5386e9d 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -44,6 +44,7 @@ tools/include/asm-generic/bitops/fls64.h
 tools/include/asm-generic/bitops/fls.h
 tools/include/asm-generic/bitops/hweight.h
 tools/include/asm-generic/bitops.h
+tools/include/asm-generic/div64.h
 tools/include/linux/atomic.h
 tools/include/linux/bitops.h
 tools/include/linux/byteorder/generic.h
@@ -53,6 +54,7 @@ tools/include/linux/hash.h
 tools/include/linux/kernel.h
 tools/include/linux/list.h
 tools/include/linux/log2.h
+tools/include/linux/math64.h
 tools/include/linux/poison.h
 tools/include/linux/rbtree.h
 tools/include/linux/rbtree_augmented.h
-- 
1.8.5.2

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

* [RFC PATCH v2 06/26] tools include: Add (atomic|atomic64)_add implementation from the kernel sources
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
                   ` (4 preceding siblings ...)
  2016-06-26 11:20 ` [RFC PATCH v2 05/26] tools include: Sync math64.h and div64.h He Kuang
@ 2016-06-26 11:20 ` He Kuang
  2016-06-26 11:20 ` [RFC PATCH v2 07/26] perf bpf: Add map related BPF helper He Kuang
                   ` (20 subsequent siblings)
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:20 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

Uses the arch/x86/ kernel code for x86_64/i386, fallbacking to a gcc
intrinsics implementation.

Signed-off-by: He Kuang <hekuang@huawei.com>
Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/arch/x86/include/asm/atomic.h    | 28 ++++++++++++++++++++++++++++
 tools/include/asm-generic/atomic-gcc.h | 10 ++++++++++
 tools/include/linux/types.h            |  4 ++++
 3 files changed, 42 insertions(+)

diff --git a/tools/arch/x86/include/asm/atomic.h b/tools/arch/x86/include/asm/atomic.h
index 059e33e..41f814e 100644
--- a/tools/arch/x86/include/asm/atomic.h
+++ b/tools/arch/x86/include/asm/atomic.h
@@ -62,4 +62,32 @@ static inline int atomic_dec_and_test(atomic_t *v)
 	GEN_UNARY_RMWcc(LOCK_PREFIX "decl", v->counter, "%0", "e");
 }
 
+/**
+ * atomic_add - add integer to atomic variable
+ * @i: integer value to add
+ * @v: pointer of type atomic_t
+ *
+ * Atomically adds @i to @v.
+ */
+static __always_inline void atomic_add(int i, atomic_t *v)
+{
+	asm volatile(LOCK_PREFIX "addl %1,%0"
+		     : "+m" (v->counter)
+		     : "ir" (i));
+}
+
+/**
+ * atomic64_add - add integer to atomic64 variable
+ * @i: integer value to add
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically adds @i to @v.
+ */
+static __always_inline void atomic64_add(long i, atomic64_t *v)
+{
+	asm volatile(LOCK_PREFIX "addq %1,%0"
+		     : "=m" (v->counter)
+		     : "er" (i), "m" (v->counter));
+}
+
 #endif /* _TOOLS_LINUX_ASM_X86_ATOMIC_H */
diff --git a/tools/include/asm-generic/atomic-gcc.h b/tools/include/asm-generic/atomic-gcc.h
index 2ba78c9..b615907 100644
--- a/tools/include/asm-generic/atomic-gcc.h
+++ b/tools/include/asm-generic/atomic-gcc.h
@@ -60,4 +60,14 @@ static inline int atomic_dec_and_test(atomic_t *v)
 	return __sync_sub_and_fetch(&v->counter, 1) == 0;
 }
 
+static inline void atomic_add(int i, atomic_t *v)
+{
+	__sync_add_and_fetch(&v->counter, i);
+}
+
+static inline void atomic64_add(long i, atomic64_t *v)
+{
+	__sync_add_and_fetch(&v->counter, i);
+}
+
 #endif /* __TOOLS_ASM_GENERIC_ATOMIC_H */
diff --git a/tools/include/linux/types.h b/tools/include/linux/types.h
index 8ebf627..09b325f 100644
--- a/tools/include/linux/types.h
+++ b/tools/include/linux/types.h
@@ -64,6 +64,10 @@ typedef struct {
 	int counter;
 } atomic_t;
 
+typedef struct {
+	long counter;
+} atomic64_t;
+
 #ifndef __aligned_u64
 # define __aligned_u64 __u64 __attribute__((aligned(8)))
 #endif
-- 
1.8.5.2

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

* [RFC PATCH v2 07/26] perf bpf: Add map related BPF helper
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
                   ` (5 preceding siblings ...)
  2016-06-26 11:20 ` [RFC PATCH v2 06/26] tools include: Add (atomic|atomic64)_add implementation from the kernel sources He Kuang
@ 2016-06-26 11:20 ` He Kuang
  2016-06-26 11:21 ` [RFC PATCH v2 08/26] perf bpf: Add UBPF flags and makefile options He Kuang
                   ` (19 subsequent siblings)
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:20 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

From: Wang Nan <wangnan0@huawei.com>

Add BPF map helpers so user can read from bpf map in user space.
Following commits will introduce user space BPF, bpf_map will be
used to pass information between kernel and user BPF programs.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Li Zefan <lizefan@huawei.com>
Signed-off-by: He Kuang <hekuang@huawei.com>
---
 tools/lib/bpf/bpf.c | 24 ++++++++++++++++++++++++
 tools/lib/bpf/bpf.h |  2 ++
 2 files changed, 26 insertions(+)

diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 1f91cc9..337d9dc 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -97,3 +97,27 @@ int bpf_map_update_elem(int fd, void *key, void *value,
 
 	return sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
 }
+
+int bpf_map_lookup_elem(int fd, void *key, void *value)
+{
+	union bpf_attr attr;
+
+	bzero(&attr, sizeof(attr));
+	attr.map_fd = fd;
+	attr.key = ptr_to_u64(key);
+	attr.value = ptr_to_u64(value);
+
+	return sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
+}
+
+int bpf_map_get_next_key(int fd, void *key, void *next_key)
+{
+	union bpf_attr attr;
+
+	bzero(&attr, sizeof(attr));
+	attr.map_fd = fd;
+	attr.key = ptr_to_u64(key);
+	attr.next_key = ptr_to_u64(next_key);
+
+	return sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));
+}
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index a764655..c06ea21 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -22,4 +22,6 @@ int bpf_load_program(enum bpf_prog_type type, struct bpf_insn *insns,
 
 int bpf_map_update_elem(int fd, void *key, void *value,
 			u64 flags);
+int bpf_map_lookup_elem(int fd, void *key, void *value);
+int bpf_map_get_next_key(int fd, void *key, void *next_key);
 #endif
-- 
1.8.5.2

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

* [RFC PATCH v2 08/26] perf bpf: Add UBPF flags and makefile options
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
                   ` (6 preceding siblings ...)
  2016-06-26 11:20 ` [RFC PATCH v2 07/26] perf bpf: Add map related BPF helper He Kuang
@ 2016-06-26 11:21 ` He Kuang
  2016-06-26 11:21 ` [RFC PATCH v2 09/26] perf bpf: Implement empty instruction handler and build bpf-vm He Kuang
                   ` (18 subsequent siblings)
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:21 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

From: Wang Nan <wangnan0@huawei.com>

UBPF are not built by default, unless user explicitly build perf with
UBPF defined.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Signed-off-by: He Kuang <hekuang@huawei.com>
---
 tools/lib/bpf/Makefile     | 4 ++++
 tools/perf/Makefile.perf   | 2 ++
 tools/perf/config/Makefile | 4 ++++
 3 files changed, 10 insertions(+)

diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile
index fc1bc75..1fb098d 100644
--- a/tools/lib/bpf/Makefile
+++ b/tools/lib/bpf/Makefile
@@ -120,6 +120,10 @@ ifeq ($(feature-libelf-getphdrnum), 1)
   override CFLAGS += -DHAVE_ELF_GETPHDRNUM_SUPPORT
 endif
 
+ifdef UBPF
+    override CFLAGS += -DHAVE_UBPF_SUPPORT
+endif
+
 # Append required CFLAGS
 override CFLAGS += $(EXTRA_WARNINGS)
 override CFLAGS += -Werror -Wall
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index d0a2cb1..114a719 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -81,6 +81,8 @@ include ../scripts/utilities.mak
 #
 # Define NO_LIBBPF if you do not want BPF support
 #
+# Define UBPF if you DO want user space BPF support
+#
 # Define FEATURES_DUMP to provide features detection dump file
 # and bypass the feature detection
 
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 534c811..2a64534 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -329,6 +329,10 @@ ifndef NO_LIBELF
     ifeq ($(feature-bpf), 1)
       CFLAGS += -DHAVE_LIBBPF_SUPPORT
       $(call detected,CONFIG_LIBBPF)
+      ifdef UBPF
+        CFLAGS += -DHAVE_UBPF_SUPPORT
+        $(call detected,CONFIG_UBPF)
+      endif
     endif
 
     ifndef NO_DWARF
-- 
1.8.5.2

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

* [RFC PATCH v2 09/26] perf bpf: Implement empty instruction handler and build bpf-vm
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
                   ` (7 preceding siblings ...)
  2016-06-26 11:21 ` [RFC PATCH v2 08/26] perf bpf: Add UBPF flags and makefile options He Kuang
@ 2016-06-26 11:21 ` He Kuang
  2016-06-26 11:21 ` [RFC PATCH v2 10/26] perf bpf: Remove unused code in libbpf He Kuang
                   ` (17 subsequent siblings)
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:21 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

This patch includes the existing code in "kernel/bpf/vm.c", and uses
empty handlers for building the userspace version of bpf-vm
code. Userspace bpf programs won't deal with 'struct skb' data so an
empty bpf_load_pointer() is placed here to help save us from including
too much kernel structures and headers.

CFLAGS are modified for supressing warnings of the existing bpf code.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Signed-off-by: He Kuang <hekuang@huawei.com>
---
 tools/perf/util/Build    |  2 ++
 tools/perf/util/bpf-vm.c | 34 ++++++++++++++++++++++++++++++++++
 tools/perf/util/bpf-vm.h |  7 +++++++
 3 files changed, 43 insertions(+)
 create mode 100644 tools/perf/util/bpf-vm.c
 create mode 100644 tools/perf/util/bpf-vm.h

diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index fced833..1d24d94 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -90,6 +90,7 @@ libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
 libperf-$(CONFIG_LIBELF) += symbol-elf.o
 libperf-$(CONFIG_LIBELF) += probe-file.o
 libperf-$(CONFIG_LIBELF) += probe-event.o
+libperf-$(CONFIG_UBPF)   += bpf-vm.o
 
 ifndef CONFIG_LIBELF
 libperf-y += symbol-minimal.o
@@ -152,6 +153,7 @@ CFLAGS_rbtree.o        += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ET
 CFLAGS_libstring.o     += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
 CFLAGS_hweight.o       += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
 CFLAGS_parse-events.o  += -Wno-redundant-decls
+CFLAGS_bpf-vm.o        += -Wno-override-init -Wno-switch-default -Wno-sign-compare
 
 $(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c FORCE
 	$(call rule_mkdir)
diff --git a/tools/perf/util/bpf-vm.c b/tools/perf/util/bpf-vm.c
new file mode 100644
index 0000000..23ac784
--- /dev/null
+++ b/tools/perf/util/bpf-vm.c
@@ -0,0 +1,34 @@
+#include <linux/atomic.h>
+#include "util.h"
+#include "tools/be_byteshift.h"
+#include "bpf-vm.h"
+
+static inline void
+bpf_vm_jmp_call_handler(u64 *regs __maybe_unused, void *ctx __maybe_unused,
+			const struct bpf_insn *insn __maybe_unused) {}
+
+static inline int
+bpf_vm_jmp_tail_call_handler(u64 *regs __maybe_unused,
+			     u32 *p_tail_call_cnt __maybe_unused,
+			     const struct bpf_insn **p_insn __maybe_unused) {
+	return 0;
+}
+
+static inline void
+bpf_vm_default_label_handler(void *ctx __maybe_unused,
+			     const struct bpf_insn *insn __maybe_unused) {}
+
+/* instructions for dealing with socket data use this function,
+ * userspace bpf don't use it now so leave it blank here, which saves
+ * us from including too much kernel structures.
+ */
+static inline void *bpf_load_pointer(const void *skb __maybe_unused,
+				     int k __maybe_unused,
+				     unsigned int size __maybe_unused,
+				     void *buffer __maybe_unused)
+{
+	return NULL;
+}
+
+#define UBPF_BUILD
+#include <../../../kernel/bpf/vm.c>
diff --git a/tools/perf/util/bpf-vm.h b/tools/perf/util/bpf-vm.h
new file mode 100644
index 0000000..bf96caa
--- /dev/null
+++ b/tools/perf/util/bpf-vm.h
@@ -0,0 +1,7 @@
+#ifndef _BPF_VM_H
+#define _BPF_VM_H
+
+struct bpf_insn;
+unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn);
+
+#endif /* _BPF_VM_H */
-- 
1.8.5.2

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

* [RFC PATCH v2 10/26] perf bpf: Remove unused code in libbpf
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
                   ` (8 preceding siblings ...)
  2016-06-26 11:21 ` [RFC PATCH v2 09/26] perf bpf: Implement empty instruction handler and build bpf-vm He Kuang
@ 2016-06-26 11:21 ` He Kuang
  2016-06-26 11:21 ` [RFC PATCH v2 11/26] perf bpf: Store arbitrary entries instread fd array in bpf_program He Kuang
                   ` (16 subsequent siblings)
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:21 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

Clean up unnecessary assignments to local variable 'result.pfd', and
remove 'pfd' field in 'struct bpf_prog_prep_result' since no one else
uses it.

Signed-off-by: He Kuang <hekuang@huawei.com>
---
 tools/lib/bpf/libbpf.c       | 4 ----
 tools/lib/bpf/libbpf.h       | 3 ---
 tools/perf/util/bpf-loader.c | 1 -
 3 files changed, 8 deletions(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 462e526..754e460 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -979,8 +979,6 @@ bpf_program__load(struct bpf_program *prog,
 			pr_debug("Skip loading the %dth instance of program '%s'\n",
 				 i, prog->section_name);
 			prog->instances.fds[i] = -1;
-			if (result.pfd)
-				*result.pfd = -1;
 			continue;
 		}
 
@@ -994,8 +992,6 @@ bpf_program__load(struct bpf_program *prog,
 			goto out;
 		}
 
-		if (result.pfd)
-			*result.pfd = fd;
 		prog->instances.fds[i] = fd;
 	}
 out:
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 722f46b..55f65de 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -125,9 +125,6 @@ struct bpf_prog_prep_result {
 	 */
 	struct bpf_insn *new_insn_ptr;
 	int new_insn_cnt;
-
-	/* If not NULL, result fd is set to it */
-	int *pfd;
 };
 
 /*
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index dcc8845..2ac73e3 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -429,7 +429,6 @@ preproc_gen_prologue(struct bpf_program *prog, int n,
 
 	res->new_insn_ptr = buf;
 	res->new_insn_cnt = prologue_cnt + orig_insns_cnt;
-	res->pfd = NULL;
 	return 0;
 
 errout:
-- 
1.8.5.2

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

* [RFC PATCH v2 11/26] perf bpf: Store arbitrary entries instread fd array in bpf_program
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
                   ` (9 preceding siblings ...)
  2016-06-26 11:21 ` [RFC PATCH v2 10/26] perf bpf: Remove unused code in libbpf He Kuang
@ 2016-06-26 11:21 ` He Kuang
  2016-06-26 11:21 ` [RFC PATCH v2 12/26] perf bpf: Add libbpf-internal.h header file He Kuang
                   ` (15 subsequent siblings)
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:21 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

The bpf progs loaded into kernel are represented by fd, but we need
new types for storing the entity of userspace bpf progs. This patch
uses a void pointer to make it more generic so we can store any new
types and cast back to its original type when used.

Signed-off-by: He Kuang <hekuang@huawei.com>
Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/lib/bpf/libbpf.c | 41 +++++++++++++++++++++--------------------
 1 file changed, 21 insertions(+), 20 deletions(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 754e460..97f72b2 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -154,7 +154,7 @@ struct bpf_program {
 
 	struct {
 		int nr;
-		int *fds;
+		void *entries;
 	} instances;
 	bpf_program_prep_t preprocessor;
 
@@ -226,14 +226,14 @@ static void bpf_program__unload(struct bpf_program *prog)
 	 */
 	if (prog->instances.nr > 0) {
 		for (i = 0; i < prog->instances.nr; i++)
-			zclose(prog->instances.fds[i]);
+			zclose(((int *)prog->instances.entries)[i]);
 	} else if (prog->instances.nr != -1) {
 		pr_warning("Internal error: instances.nr is %d\n",
 			   prog->instances.nr);
 	}
 
 	prog->instances.nr = -1;
-	zfree(&prog->instances.fds);
+	zfree(&prog->instances.entries);
 }
 
 static void bpf_program__exit(struct bpf_program *prog)
@@ -284,7 +284,7 @@ bpf_program__init(void *data, size_t size, char *name, int idx,
 	memcpy(prog->insns, data,
 	       prog->insns_cnt * sizeof(struct bpf_insn));
 	prog->idx = idx;
-	prog->instances.fds = NULL;
+	prog->instances.entries = NULL;
 	prog->instances.nr = -1;
 
 	return 0;
@@ -934,20 +934,21 @@ bpf_program__load(struct bpf_program *prog,
 {
 	int err = 0, fd, i;
 
-	if (prog->instances.nr < 0 || !prog->instances.fds) {
+	if (prog->instances.nr < 0 || !prog->instances.entries) {
 		if (prog->preprocessor) {
 			pr_warning("Internal error: can't load program '%s'\n",
 				   prog->section_name);
 			return -LIBBPF_ERRNO__INTERNAL;
 		}
 
-		prog->instances.fds = malloc(sizeof(int));
-		if (!prog->instances.fds) {
-			pr_warning("Not enough memory for BPF fds\n");
+		prog->instances.entries = malloc(sizeof(int));
+		if (!prog->instances.entries) {
+			pr_warning("Not enough memory for BPF entries\n");
 			return -ENOMEM;
 		}
+
 		prog->instances.nr = 1;
-		prog->instances.fds[0] = -1;
+		((int *)prog->instances.entries)[0] = -1;
 	}
 
 	if (!prog->preprocessor) {
@@ -958,7 +959,7 @@ bpf_program__load(struct bpf_program *prog,
 		err = load_program(prog->insns, prog->insns_cnt,
 				   license, kern_version, &fd);
 		if (!err)
-			prog->instances.fds[0] = fd;
+			((int *)prog->instances.entries)[0] = fd;
 		goto out;
 	}
 
@@ -978,7 +979,7 @@ bpf_program__load(struct bpf_program *prog,
 		if (!result.new_insn_ptr || !result.new_insn_cnt) {
 			pr_debug("Skip loading the %dth instance of program '%s'\n",
 				 i, prog->section_name);
-			prog->instances.fds[i] = -1;
+			((int *)prog->instances.entries)[i] = -1;
 			continue;
 		}
 
@@ -992,7 +993,7 @@ bpf_program__load(struct bpf_program *prog,
 			goto out;
 		}
 
-		prog->instances.fds[i] = fd;
+		((int *)prog->instances.entries)[i] = fd;
 	}
 out:
 	if (err)
@@ -1254,27 +1255,27 @@ int bpf_program__fd(struct bpf_program *prog)
 int bpf_program__set_prep(struct bpf_program *prog, int nr_instances,
 			  bpf_program_prep_t prep)
 {
-	int *instances_fds;
+	int *instances_entries;
 
 	if (nr_instances <= 0 || !prep)
 		return -EINVAL;
 
-	if (prog->instances.nr > 0 || prog->instances.fds) {
+	if (prog->instances.nr > 0 || prog->instances.entries) {
 		pr_warning("Can't set pre-processor after loading\n");
 		return -EINVAL;
 	}
 
-	instances_fds = malloc(sizeof(int) * nr_instances);
-	if (!instances_fds) {
-		pr_warning("alloc memory failed for fds\n");
+	instances_entries = malloc(sizeof(int) * nr_instances);
+	if (!instances_entries) {
+		pr_warning("alloc memory failed for entries\n");
 		return -ENOMEM;
 	}
 
 	/* fill all fd with -1 */
-	memset(instances_fds, -1, sizeof(int) * nr_instances);
+	memset(instances_entries, -1, sizeof(int) * nr_instances);
 
 	prog->instances.nr = nr_instances;
-	prog->instances.fds = instances_fds;
+	prog->instances.entries = instances_entries;
 	prog->preprocessor = prep;
 	return 0;
 }
@@ -1289,7 +1290,7 @@ int bpf_program__nth_fd(struct bpf_program *prog, int n)
 		return -EINVAL;
 	}
 
-	fd = prog->instances.fds[n];
+	fd = ((int *)prog->instances.entries)[n];
 	if (fd < 0) {
 		pr_warning("%dth instance of program '%s' is invalid\n",
 			   n, prog->section_name);
-- 
1.8.5.2

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

* [RFC PATCH v2 12/26] perf bpf: Add libbpf-internal.h header file
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
                   ` (10 preceding siblings ...)
  2016-06-26 11:21 ` [RFC PATCH v2 11/26] perf bpf: Store arbitrary entries instread fd array in bpf_program He Kuang
@ 2016-06-26 11:21 ` He Kuang
  2016-06-26 11:21 ` [RFC PATCH v2 13/26] perf bpf: Add abstraction for bpf program methods He Kuang
                   ` (14 subsequent siblings)
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:21 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

Split part of codes in libbpf.c out for internal usage, debug print
functions are changed to non-static for other files to use.

Signed-off-by: He Kuang <hekuang@huawei.com>
---
 tools/lib/bpf/libbpf-internal.h | 65 +++++++++++++++++++++++++++++++++++++++
 tools/lib/bpf/libbpf.c          | 68 +++++------------------------------------
 2 files changed, 72 insertions(+), 61 deletions(-)
 create mode 100644 tools/lib/bpf/libbpf-internal.h

diff --git a/tools/lib/bpf/libbpf-internal.h b/tools/lib/bpf/libbpf-internal.h
new file mode 100644
index 0000000..1c1619c
--- /dev/null
+++ b/tools/lib/bpf/libbpf-internal.h
@@ -0,0 +1,65 @@
+#ifndef _LIBBPF_INTERNAL_H
+#define _LIBBPF_INTERNAL_H
+
+#include "libbpf.h"
+
+#define __printf(a, b)	__attribute__((format(printf, a, b)))
+
+#define __pr(func, fmt, ...)	\
+do {				\
+	if ((func))		\
+		(func)("libbpf: " fmt, ##__VA_ARGS__); \
+} while (0)
+
+extern libbpf_print_fn_t __pr_bpf_warning;
+extern libbpf_print_fn_t __pr_bpf_info;
+extern libbpf_print_fn_t __pr_bpf_debug;
+
+#define pr_warning(fmt, ...)	__pr(__pr_bpf_warning, fmt, ##__VA_ARGS__)
+#define pr_info(fmt, ...)	__pr(__pr_bpf_info, fmt, ##__VA_ARGS__)
+#define pr_debug(fmt, ...)	__pr(__pr_bpf_debug, fmt, ##__VA_ARGS__)
+
+/* Copied from tools/perf/util/util.h */
+#ifndef zfree
+# define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
+#endif
+
+#ifndef zclose
+# define zclose(fd) ({			\
+	int ___err = 0;			\
+	if ((fd) >= 0)			\
+		___err = close((fd));	\
+	fd = -1;			\
+	___err; })
+#endif
+
+/*
+ * bpf_prog should be a better name but it has been used in
+ * linux/filter.h.
+ */
+struct bpf_program {
+	/* Index in elf obj file, for relocation use. */
+	int idx;
+	char *section_name;
+	struct bpf_insn *insns;
+	size_t insns_cnt;
+
+	struct {
+		int insn_idx;
+		int map_idx;
+	} *reloc_desc;
+	int nr_reloc;
+
+	struct bpf_engine *engine;
+	struct {
+		int nr;
+		void *entries;
+	} instances;
+	bpf_program_prep_t preprocessor;
+
+	struct bpf_object *obj;
+	void *priv;
+	bpf_program_clear_priv_t clear_priv;
+};
+
+#endif /* _LIBBPF_INTERNAL_H */
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 97f72b2..0ad6c9e 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -23,8 +23,7 @@
 
 #include "libbpf.h"
 #include "bpf.h"
-
-#define __printf(a, b)	__attribute__((format(printf, a, b)))
+#include "libbpf-internal.h"
 
 __printf(1, 2)
 static int __base_pr(const char *format, ...)
@@ -38,27 +37,17 @@ static int __base_pr(const char *format, ...)
 	return err;
 }
 
-static __printf(1, 2) libbpf_print_fn_t __pr_warning = __base_pr;
-static __printf(1, 2) libbpf_print_fn_t __pr_info = __base_pr;
-static __printf(1, 2) libbpf_print_fn_t __pr_debug;
-
-#define __pr(func, fmt, ...)	\
-do {				\
-	if ((func))		\
-		(func)("libbpf: " fmt, ##__VA_ARGS__); \
-} while (0)
-
-#define pr_warning(fmt, ...)	__pr(__pr_warning, fmt, ##__VA_ARGS__)
-#define pr_info(fmt, ...)	__pr(__pr_info, fmt, ##__VA_ARGS__)
-#define pr_debug(fmt, ...)	__pr(__pr_debug, fmt, ##__VA_ARGS__)
+__printf(1, 2) libbpf_print_fn_t __pr_bpf_warning = __base_pr;
+__printf(1, 2) libbpf_print_fn_t __pr_bpf_info = __base_pr;
+__printf(1, 2) libbpf_print_fn_t __pr_bpf_debug;
 
 void libbpf_set_print(libbpf_print_fn_t warn,
 		      libbpf_print_fn_t info,
 		      libbpf_print_fn_t debug)
 {
-	__pr_warning = warn;
-	__pr_info = info;
-	__pr_debug = debug;
+	__pr_bpf_warning = warn;
+	__pr_bpf_info = info;
+	__pr_bpf_debug = debug;
 }
 
 #define STRERR_BUFSIZE  128
@@ -114,55 +103,12 @@ int libbpf_strerror(int err, char *buf, size_t size)
 		goto out;		\
 } while(0)
 
-
-/* Copied from tools/perf/util/util.h */
-#ifndef zfree
-# define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
-#endif
-
-#ifndef zclose
-# define zclose(fd) ({			\
-	int ___err = 0;			\
-	if ((fd) >= 0)			\
-		___err = close((fd));	\
-	fd = -1;			\
-	___err; })
-#endif
-
 #ifdef HAVE_LIBELF_MMAP_SUPPORT
 # define LIBBPF_ELF_C_READ_MMAP ELF_C_READ_MMAP
 #else
 # define LIBBPF_ELF_C_READ_MMAP ELF_C_READ
 #endif
 
-/*
- * bpf_prog should be a better name but it has been used in
- * linux/filter.h.
- */
-struct bpf_program {
-	/* Index in elf obj file, for relocation use. */
-	int idx;
-	char *section_name;
-	struct bpf_insn *insns;
-	size_t insns_cnt;
-
-	struct {
-		int insn_idx;
-		int map_idx;
-	} *reloc_desc;
-	int nr_reloc;
-
-	struct {
-		int nr;
-		void *entries;
-	} instances;
-	bpf_program_prep_t preprocessor;
-
-	struct bpf_object *obj;
-	void *priv;
-	bpf_program_clear_priv_t clear_priv;
-};
-
 struct bpf_map {
 	int fd;
 	char *name;
-- 
1.8.5.2

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

* [RFC PATCH v2 13/26] perf bpf: Add abstraction for bpf program methods
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
                   ` (11 preceding siblings ...)
  2016-06-26 11:21 ` [RFC PATCH v2 12/26] perf bpf: Add libbpf-internal.h header file He Kuang
@ 2016-06-26 11:21 ` He Kuang
  2016-06-26 11:21 ` [RFC PATCH v2 14/26] perf bpf: Add -Wextra to cflags for more warnings and fix them He Kuang
                   ` (13 subsequent siblings)
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:21 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

Supporting different bpf program types loaded into kernel and
userspace, this patch abstracts the operations to related to bpf
program into bpf_engine. The methods set for bpf loaded into kernel
are included in engine-kbpf.c, which is used as the default value.

Signed-off-by: He Kuang <hekuang@huawei.com>
Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/lib/bpf/Build             |   1 +
 tools/lib/bpf/engine-kbpf.c     | 131 ++++++++++++++++++++++++++++++++++++++++
 tools/lib/bpf/libbpf-internal.h |  11 ++++
 tools/lib/bpf/libbpf.c          | 115 ++++-------------------------------
 4 files changed, 156 insertions(+), 102 deletions(-)
 create mode 100644 tools/lib/bpf/engine-kbpf.c

diff --git a/tools/lib/bpf/Build b/tools/lib/bpf/Build
index d874975..567dcfd 100644
--- a/tools/lib/bpf/Build
+++ b/tools/lib/bpf/Build
@@ -1 +1,2 @@
 libbpf-y := libbpf.o bpf.o
+libbpf-y += engine-kbpf.o
diff --git a/tools/lib/bpf/engine-kbpf.c b/tools/lib/bpf/engine-kbpf.c
new file mode 100644
index 0000000..7d81e16
--- /dev/null
+++ b/tools/lib/bpf/engine-kbpf.c
@@ -0,0 +1,131 @@
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <linux/bpf.h>
+
+#include "bpf.h"
+#include "libbpf-internal.h"
+
+static int engine__init(struct bpf_program *prog)
+{
+	int *instances_entries;
+	int nr_instances = prog->instances.nr;
+
+	instances_entries = malloc(sizeof(int) * nr_instances);
+	if (!instances_entries) {
+		pr_warning("alloc memory failed for instances\n");
+		return -ENOMEM;
+	}
+
+	/* fill all fd with -1 */
+	memset(instances_entries, -1, sizeof(int) * nr_instances);
+
+	prog->instances.entries = instances_entries;
+
+	return 0;
+}
+
+static int engine__get_nth(struct bpf_program *prog, int n, void *ret)
+{
+	int *pfd = (int *)ret;
+
+	if (n >= prog->instances.nr || n < 0) {
+		pr_warning("Can't get the %dth fd from program %s: only %d instances\n",
+			   n, prog->section_name, prog->instances.nr);
+		return -EINVAL;
+	}
+
+	*pfd = ((int *)prog->instances.entries)[n];
+	if (*pfd < 0) {
+		pr_warning("%dth instance of program '%s' is invalid\n",
+			   n, prog->section_name);
+		return -ENOENT;
+	}
+
+	return 0;
+}
+
+static void engine__unload(struct bpf_program *prog, int index)
+{
+	zclose(((int *)prog->instances.entries)[index]);
+}
+
+static int
+load_program(struct bpf_insn *insns, int insns_cnt,
+	     char *license, u32 kern_version, int *pfd)
+{
+	int ret;
+	char *log_buf;
+
+	if (!insns || !insns_cnt)
+		return -EINVAL;
+
+	log_buf = malloc(BPF_LOG_BUF_SIZE);
+	if (!log_buf)
+		pr_warning("Alloc log buffer for bpf loader error, continue without log\n");
+
+	ret = bpf_load_program(BPF_PROG_TYPE_KPROBE, insns,
+			       insns_cnt, license, kern_version,
+			       log_buf, BPF_LOG_BUF_SIZE);
+
+	if (ret >= 0) {
+		*pfd = ret;
+		ret = 0;
+		goto out;
+	}
+
+	ret = -LIBBPF_ERRNO__LOAD;
+	pr_warning("load bpf program failed: %s\n", strerror(errno));
+
+	if (log_buf && log_buf[0] != '\0') {
+		ret = -LIBBPF_ERRNO__VERIFY;
+		pr_warning("-- BEGIN DUMP LOG ---\n");
+		pr_warning("\n%s\n", log_buf);
+		pr_warning("-- END LOG --\n");
+	} else {
+		if (insns_cnt >= BPF_MAXINSNS) {
+			pr_warning("Program too large (%d insns), at most %d insns\n",
+				   insns_cnt, BPF_MAXINSNS);
+			ret = -LIBBPF_ERRNO__PROG2BIG;
+		} else if (log_buf) {
+			pr_warning("log buffer is empty\n");
+			ret = -LIBBPF_ERRNO__KVER;
+		}
+	}
+
+out:
+	free(log_buf);
+	return ret;
+}
+
+static int engine__load(struct bpf_program *prog, struct bpf_insn *insns,
+			int insns_cnt, char *license,
+			u32 kern_version, int index)
+{
+	int err = 0;
+	int fd;
+
+	if (!insns || !insns_cnt) {
+		((int *)prog->instances.entries)[index] = -1;
+		pr_debug("Skip loading the %dth instance of program '%s'\n",
+			 index, prog->section_name);
+		return err;
+	}
+
+	err = load_program(insns, insns_cnt, license, kern_version, &fd);
+	if (!err)
+		((int *)prog->instances.entries)[index] = fd;
+	else
+		pr_warning("Loading the %dth instance of program '%s' failed\n",
+			   index, prog->section_name);
+
+	return err;
+}
+
+struct bpf_engine kengine = {
+	.init		= engine__init,
+	.load		= engine__load,
+	.unload		= engine__unload,
+	.get_nth	= engine__get_nth,
+};
diff --git a/tools/lib/bpf/libbpf-internal.h b/tools/lib/bpf/libbpf-internal.h
index 1c1619c..60b2f68 100644
--- a/tools/lib/bpf/libbpf-internal.h
+++ b/tools/lib/bpf/libbpf-internal.h
@@ -62,4 +62,15 @@ struct bpf_program {
 	bpf_program_clear_priv_t clear_priv;
 };
 
+struct bpf_engine {
+	int (*init)(struct bpf_program *prog);
+	int (*load)(struct bpf_program *prog, struct bpf_insn *insns,
+		    int insns_cnt, char *license,
+		    u32 kern_version, int index);
+	void (*unload)(struct bpf_program *prog, int index);
+	int (*get_nth)(struct bpf_program *prog, int index, void *ret);
+};
+
+extern struct bpf_engine kengine;
+
 #endif /* _LIBBPF_INTERNAL_H */
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 0ad6c9e..a53cb579 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -172,7 +172,7 @@ static void bpf_program__unload(struct bpf_program *prog)
 	 */
 	if (prog->instances.nr > 0) {
 		for (i = 0; i < prog->instances.nr; i++)
-			zclose(((int *)prog->instances.entries)[i]);
+			prog->engine->unload(prog, i);
 	} else if (prog->instances.nr != -1) {
 		pr_warning("Internal error: instances.nr is %d\n",
 			   prog->instances.nr);
@@ -230,6 +230,7 @@ bpf_program__init(void *data, size_t size, char *name, int idx,
 	memcpy(prog->insns, data,
 	       prog->insns_cnt * sizeof(struct bpf_insn));
 	prog->idx = idx;
+	prog->engine = &kengine;
 	prog->instances.entries = NULL;
 	prog->instances.nr = -1;
 
@@ -827,58 +828,10 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
 }
 
 static int
-load_program(struct bpf_insn *insns, int insns_cnt,
-	     char *license, u32 kern_version, int *pfd)
-{
-	int ret;
-	char *log_buf;
-
-	if (!insns || !insns_cnt)
-		return -EINVAL;
-
-	log_buf = malloc(BPF_LOG_BUF_SIZE);
-	if (!log_buf)
-		pr_warning("Alloc log buffer for bpf loader error, continue without log\n");
-
-	ret = bpf_load_program(BPF_PROG_TYPE_KPROBE, insns,
-			       insns_cnt, license, kern_version,
-			       log_buf, BPF_LOG_BUF_SIZE);
-
-	if (ret >= 0) {
-		*pfd = ret;
-		ret = 0;
-		goto out;
-	}
-
-	ret = -LIBBPF_ERRNO__LOAD;
-	pr_warning("load bpf program failed: %s\n", strerror(errno));
-
-	if (log_buf && log_buf[0] != '\0') {
-		ret = -LIBBPF_ERRNO__VERIFY;
-		pr_warning("-- BEGIN DUMP LOG ---\n");
-		pr_warning("\n%s\n", log_buf);
-		pr_warning("-- END LOG --\n");
-	} else {
-		if (insns_cnt >= BPF_MAXINSNS) {
-			pr_warning("Program too large (%d insns), at most %d insns\n",
-				   insns_cnt, BPF_MAXINSNS);
-			ret = -LIBBPF_ERRNO__PROG2BIG;
-		} else if (log_buf) {
-			pr_warning("log buffer is empty\n");
-			ret = -LIBBPF_ERRNO__KVER;
-		}
-	}
-
-out:
-	free(log_buf);
-	return ret;
-}
-
-static int
 bpf_program__load(struct bpf_program *prog,
 		  char *license, u32 kern_version)
 {
-	int err = 0, fd, i;
+	int err = 0, i;
 
 	if (prog->instances.nr < 0 || !prog->instances.entries) {
 		if (prog->preprocessor) {
@@ -887,14 +840,8 @@ bpf_program__load(struct bpf_program *prog,
 			return -LIBBPF_ERRNO__INTERNAL;
 		}
 
-		prog->instances.entries = malloc(sizeof(int));
-		if (!prog->instances.entries) {
-			pr_warning("Not enough memory for BPF entries\n");
-			return -ENOMEM;
-		}
-
 		prog->instances.nr = 1;
-		((int *)prog->instances.entries)[0] = -1;
+		prog->engine->init(prog);
 	}
 
 	if (!prog->preprocessor) {
@@ -902,10 +849,8 @@ bpf_program__load(struct bpf_program *prog,
 			pr_warning("Program '%s' is inconsistent: nr(%d) != 1\n",
 				   prog->section_name, prog->instances.nr);
 		}
-		err = load_program(prog->insns, prog->insns_cnt,
-				   license, kern_version, &fd);
-		if (!err)
-			((int *)prog->instances.entries)[0] = fd;
+		prog->engine->load(prog, prog->insns, prog->insns_cnt,
+				   license, kern_version, 0);
 		goto out;
 	}
 
@@ -922,24 +867,11 @@ bpf_program__load(struct bpf_program *prog,
 			goto out;
 		}
 
-		if (!result.new_insn_ptr || !result.new_insn_cnt) {
-			pr_debug("Skip loading the %dth instance of program '%s'\n",
-				 i, prog->section_name);
-			((int *)prog->instances.entries)[i] = -1;
-			continue;
-		}
-
-		err = load_program(result.new_insn_ptr,
-				   result.new_insn_cnt,
-				   license, kern_version, &fd);
-
-		if (err) {
-			pr_warning("Loading the %dth instance of program '%s' failed\n",
-					i, prog->section_name);
+		err = prog->engine->load(prog, result.new_insn_ptr,
+					 result.new_insn_cnt, license,
+					 kern_version, i);
+		if (err)
 			goto out;
-		}
-
-		((int *)prog->instances.entries)[i] = fd;
 	}
 out:
 	if (err)
@@ -1201,8 +1133,6 @@ int bpf_program__fd(struct bpf_program *prog)
 int bpf_program__set_prep(struct bpf_program *prog, int nr_instances,
 			  bpf_program_prep_t prep)
 {
-	int *instances_entries;
-
 	if (nr_instances <= 0 || !prep)
 		return -EINVAL;
 
@@ -1211,17 +1141,9 @@ int bpf_program__set_prep(struct bpf_program *prog, int nr_instances,
 		return -EINVAL;
 	}
 
-	instances_entries = malloc(sizeof(int) * nr_instances);
-	if (!instances_entries) {
-		pr_warning("alloc memory failed for entries\n");
-		return -ENOMEM;
-	}
-
-	/* fill all fd with -1 */
-	memset(instances_entries, -1, sizeof(int) * nr_instances);
-
 	prog->instances.nr = nr_instances;
-	prog->instances.entries = instances_entries;
+	prog->engine->init(prog);
+
 	prog->preprocessor = prep;
 	return 0;
 }
@@ -1230,18 +1152,7 @@ int bpf_program__nth_fd(struct bpf_program *prog, int n)
 {
 	int fd;
 
-	if (n >= prog->instances.nr || n < 0) {
-		pr_warning("Can't get the %dth fd from program %s: only %d instances\n",
-			   n, prog->section_name, prog->instances.nr);
-		return -EINVAL;
-	}
-
-	fd = ((int *)prog->instances.entries)[n];
-	if (fd < 0) {
-		pr_warning("%dth instance of program '%s' is invalid\n",
-			   n, prog->section_name);
-		return -ENOENT;
-	}
+	prog->engine->get_nth(prog, n, &fd);
 
 	return fd;
 }
-- 
1.8.5.2

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

* [RFC PATCH v2 14/26] perf bpf: Add -Wextra to cflags for more warnings and fix them
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
                   ` (12 preceding siblings ...)
  2016-06-26 11:21 ` [RFC PATCH v2 13/26] perf bpf: Add abstraction for bpf program methods He Kuang
@ 2016-06-26 11:21 ` He Kuang
  2016-06-26 11:21 ` [RFC PATCH v2 15/26] perf bpf: Introduce the entity and engine for userspace bpf He Kuang
                   ` (12 subsequent siblings)
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:21 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

Since -Wextra is used in perf tools, this patch adopts this cflags
into lib/bpf. It also fixes 'comparison between signed and unsigned
integer' errors reported afterward.

Signed-off-by: He Kuang <hekuang@huawei.com>
---
 tools/lib/bpf/Makefile | 2 +-
 tools/lib/bpf/libbpf.c | 7 ++++---
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile
index 1fb098d..65a64d8 100644
--- a/tools/lib/bpf/Makefile
+++ b/tools/lib/bpf/Makefile
@@ -126,7 +126,7 @@ endif
 
 # Append required CFLAGS
 override CFLAGS += $(EXTRA_WARNINGS)
-override CFLAGS += -Werror -Wall
+override CFLAGS += -Werror -Wall -Wextra
 override CFLAGS += -fPIC
 override CFLAGS += $(INCLUDES)
 
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index a53cb579..ddbba35 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -443,7 +443,7 @@ bpf_object__init_maps(struct bpf_object *obj, void *data,
 		      size_t size)
 {
 	size_t nr_maps;
-	int i;
+	unsigned int i;
 
 	nr_maps = size / sizeof(struct bpf_map_def);
 	if (!data || !nr_maps) {
@@ -480,7 +480,7 @@ bpf_object__init_maps(struct bpf_object *obj, void *data,
 static int
 bpf_object__init_maps_name(struct bpf_object *obj)
 {
-	int i;
+	unsigned int i;
 	Elf_Data *symbols = obj->efile.symbols;
 
 	if (!symbols || obj->efile.maps_shndx < 0)
@@ -521,7 +521,8 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
 	Elf *elf = obj->efile.elf;
 	GElf_Ehdr *ep = &obj->efile.ehdr;
 	Elf_Scn *scn = NULL;
-	int idx = 0, err = 0;
+	unsigned int idx = 0;
+	int err = 0;
 
 	/* Elf is corrupted/truncated, avoid calling elf_strptr. */
 	if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) {
-- 
1.8.5.2

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

* [RFC PATCH v2 15/26] perf bpf: Introduce the entity and engine for userspace bpf
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
                   ` (13 preceding siblings ...)
  2016-06-26 11:21 ` [RFC PATCH v2 14/26] perf bpf: Add -Wextra to cflags for more warnings and fix them He Kuang
@ 2016-06-26 11:21 ` He Kuang
  2016-06-26 11:21 ` [RFC PATCH v2 16/26] perf bpf: Add method for fetching nth ubpf vm He Kuang
                   ` (11 subsequent siblings)
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:21 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

Different from bpf for kernel which is loaded into kernel and
represented by the fd handle returned, userspace bpf prgrams should be
loaded each time we run it. The field 'insns' is stored in ubpf entry
since the vm execute interface __bpf_prog_run() needs that to run the
bpf prog.

Signed-off-by: He Kuang <hekuang@huawei.com>
Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/lib/bpf/Build         |  1 +
 tools/lib/bpf/engine-ubpf.c | 97 +++++++++++++++++++++++++++++++++++++++++++++
 tools/lib/bpf/libbpf.c      |  1 +
 tools/lib/bpf/libbpf.h      |  6 +++
 4 files changed, 105 insertions(+)
 create mode 100644 tools/lib/bpf/engine-ubpf.c

diff --git a/tools/lib/bpf/Build b/tools/lib/bpf/Build
index 567dcfd..2f7e64c 100644
--- a/tools/lib/bpf/Build
+++ b/tools/lib/bpf/Build
@@ -1,2 +1,3 @@
 libbpf-y := libbpf.o bpf.o
 libbpf-y += engine-kbpf.o
+libbpf-$(CONFIG_UBPF) += engine-ubpf.o
diff --git a/tools/lib/bpf/engine-ubpf.c b/tools/lib/bpf/engine-ubpf.c
new file mode 100644
index 0000000..0ab3310
--- /dev/null
+++ b/tools/lib/bpf/engine-ubpf.c
@@ -0,0 +1,97 @@
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <linux/bpf.h>
+
+#include "bpf.h"
+#include "libbpf-internal.h"
+
+static int engine__init(struct bpf_program *prog)
+{
+	struct ubpf_entry *instances_entries;
+	int nr_instances = prog->instances.nr;
+
+	instances_entries = malloc(sizeof(struct ubpf_entry) * nr_instances);
+	if (!instances_entries) {
+		pr_warning("alloc memory failed for instances\n");
+		return -ENOMEM;
+	}
+
+	/* fill all entries with NULL */
+	memset(instances_entries, 0,
+	       sizeof(instances_entries[0]) * nr_instances);
+
+	prog->instances.entries = instances_entries;
+
+	return 0;
+}
+
+static int engine__get_nth(struct bpf_program *prog, int n, void *ret)
+{
+	struct ubpf_entry **p_vm = (struct ubpf_entry **)ret;
+
+	if (n >= prog->instances.nr || n < 0) {
+		pr_warning("Can't get the %dth vm from program %s: only %d instances\n",
+			   n, prog->section_name, prog->instances.nr);
+		return -EINVAL;
+	}
+
+	*p_vm = &((struct ubpf_entry *)prog->instances.entries)[n];
+
+	return 0;
+}
+
+static void engine__unload(struct bpf_program *prog, int index)
+{
+	struct ubpf_entry *v =
+		&((struct ubpf_entry *)prog->instances.entries)[index];
+
+	free(v->insns);
+}
+
+static int
+load_ubpf_program(struct bpf_insn *insns, int insns_cnt,
+		  struct ubpf_entry *entry)
+{
+	entry->insns = malloc(insns_cnt * sizeof(struct bpf_insn));
+	if (!entry->insns) {
+		pr_warning("Failed to create ubpf entry\n");
+		return -LIBBPF_ERRNO__LOADUBPF;
+	}
+
+	memcpy(entry->insns, &insns->code, insns_cnt * sizeof(struct bpf_insn));
+
+	return 0;
+}
+
+static int engine__load(struct bpf_program *prog, struct bpf_insn *insns,
+			int insns_cnt, char *license __maybe_unused,
+			u32 kern_version __maybe_unused, int index)
+{
+	int err = 0;
+	struct ubpf_entry entry;
+
+	if (!insns || !insns_cnt) {
+		((struct ubpf_entry **)prog->instances.entries)[index] = NULL;
+		pr_debug("Skip loading the %dth instance of program '%s'\n",
+			 index, prog->section_name);
+		return err;
+	}
+
+	err = load_ubpf_program(insns, insns_cnt, &entry);
+	if (!err)
+		((struct ubpf_entry *)prog->instances.entries)[index] = entry;
+	else
+		pr_warning("Loading the %dth instance of program '%s' failed\n",
+			   index, prog->section_name);
+
+	return err;
+}
+
+struct bpf_engine uengine = {
+	.init		= engine__init,
+	.load		= engine__load,
+	.unload		= engine__unload,
+	.get_nth	= engine__get_nth,
+};
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index ddbba35..b738ef2 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -66,6 +66,7 @@ static const char *libbpf_strerror_table[NR_ERRNO] = {
 	[ERRCODE_OFFSET(VERIFY)]	= "Kernel verifier blocks program loading",
 	[ERRCODE_OFFSET(PROG2BIG)]	= "Program too big",
 	[ERRCODE_OFFSET(KVER)]		= "Incorrect kernel version",
+	[ERRCODE_OFFSET(LOADUBPF)]	= "Failed to load user space BPF program",
 };
 
 int libbpf_strerror(int err, char *buf, size_t size)
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 55f65de..996862f 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -26,6 +26,7 @@ enum libbpf_errno {
 	LIBBPF_ERRNO__VERIFY,	/* Kernel verifier blocks program loading */
 	LIBBPF_ERRNO__PROG2BIG,	/* Program too big */
 	LIBBPF_ERRNO__KVER,	/* Incorrect kernel version */
+	LIBBPF_ERRNO__LOADUBPF, /* Failed to load user space BPF program */
 	__LIBBPF_ERRNO__END,
 };
 
@@ -185,4 +186,9 @@ int bpf_map__set_priv(struct bpf_map *map, void *priv,
 		      bpf_map_clear_priv_t clear_priv);
 void *bpf_map__priv(struct bpf_map *map);
 
+/* The entity of ubpf program */
+struct ubpf_entry {
+	struct bpf_insn *insns;
+};
+
 #endif
-- 
1.8.5.2

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

* [RFC PATCH v2 16/26] perf bpf: Add method for fetching nth ubpf vm
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
                   ` (14 preceding siblings ...)
  2016-06-26 11:21 ` [RFC PATCH v2 15/26] perf bpf: Introduce the entity and engine for userspace bpf He Kuang
@ 2016-06-26 11:21 ` He Kuang
  2016-06-26 11:21 ` [RFC PATCH v2 17/26] perf bpf: Add methods to set/check ubpf engine for bpf programs He Kuang
                   ` (10 subsequent siblings)
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:21 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

Same as bpf_program__fd() and bpf_program__nth_fd(), add methods for
fetching the nth ubpf entry.

Signed-off-by: He Kuang <hekuang@huawei.com>
Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/lib/bpf/libbpf.c | 14 ++++++++++++++
 tools/lib/bpf/libbpf.h |  1 +
 2 files changed, 15 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index b738ef2..7e77cc2 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -1132,6 +1132,20 @@ int bpf_program__fd(struct bpf_program *prog)
 	return bpf_program__nth_fd(prog, 0);
 }
 
+static void *bpf_program__nth_vm(struct bpf_program *prog, int n)
+{
+	void *ret;
+
+	prog->engine->get_nth(prog, n, &ret);
+
+	return ret;
+}
+
+void *bpf_program__vm(struct bpf_program *prog)
+{
+	return bpf_program__nth_vm(prog, 0);
+}
+
 int bpf_program__set_prep(struct bpf_program *prog, int nr_instances,
 			  bpf_program_prep_t prep)
 {
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 996862f..b0e6c68 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -87,6 +87,7 @@ void *bpf_program__priv(struct bpf_program *prog);
 const char *bpf_program__title(struct bpf_program *prog, bool needs_copy);
 
 int bpf_program__fd(struct bpf_program *prog);
+void *bpf_program__vm(struct bpf_program *prog);
 
 struct bpf_insn;
 
-- 
1.8.5.2

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

* [RFC PATCH v2 17/26] perf bpf: Add methods to set/check ubpf engine for bpf programs
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
                   ` (15 preceding siblings ...)
  2016-06-26 11:21 ` [RFC PATCH v2 16/26] perf bpf: Add method for fetching nth ubpf vm He Kuang
@ 2016-06-26 11:21 ` He Kuang
  2016-06-26 11:21 ` [RFC PATCH v2 18/26] perf bpf: Add ubpf helper function slots and set/get methods He Kuang
                   ` (9 subsequent siblings)
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:21 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

Add methods to set ubpf engine for a bpf program and to check whether
a program's engine is ubpf.

Signed-off-by: He Kuang <hekuang@huawei.com>
Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/lib/bpf/engine-ubpf.c | 12 ++++++++++++
 tools/lib/bpf/libbpf.h      | 17 +++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/tools/lib/bpf/engine-ubpf.c b/tools/lib/bpf/engine-ubpf.c
index 0ab3310..9a0b425 100644
--- a/tools/lib/bpf/engine-ubpf.c
+++ b/tools/lib/bpf/engine-ubpf.c
@@ -95,3 +95,15 @@ struct bpf_engine uengine = {
 	.unload		= engine__unload,
 	.get_nth	= engine__get_nth,
 };
+
+int bpf_program__set_ubpf(struct bpf_program *prog)
+{
+	prog->engine = &uengine;
+
+	return 0;
+}
+
+bool bpf_program__is_ubpf(struct bpf_program *prog)
+{
+	return prog->engine == &uengine;
+}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index b0e6c68..e01ab8e 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -27,6 +27,7 @@ enum libbpf_errno {
 	LIBBPF_ERRNO__PROG2BIG,	/* Program too big */
 	LIBBPF_ERRNO__KVER,	/* Incorrect kernel version */
 	LIBBPF_ERRNO__LOADUBPF, /* Failed to load user space BPF program */
+	LIBBPF_ERRNO__NOUBPF,/* UBPF support is not compiled */
 	__LIBBPF_ERRNO__END,
 };
 
@@ -192,4 +193,20 @@ struct ubpf_entry {
 	struct bpf_insn *insns;
 };
 
+#ifdef HAVE_UBPF_SUPPORT
+int bpf_program__set_ubpf(struct bpf_program *prog);
+bool bpf_program__is_ubpf(struct bpf_program *prog);
+#else
+static inline int
+bpf_program__set_ubpf(struct bpf_program *prog __maybe_unused)
+{
+	return -LIBBPF_ERRNO__NOUBPF;
+}
+static inline bool
+bpf_program__is_ubpf(struct bpf_program *prog __maybe_unused)
+{
+	return false;
+}
+#endif
+
 #endif
-- 
1.8.5.2

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

* [RFC PATCH v2 18/26] perf bpf: Add ubpf helper function slots and set/get methods
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
                   ` (16 preceding siblings ...)
  2016-06-26 11:21 ` [RFC PATCH v2 17/26] perf bpf: Add methods to set/check ubpf engine for bpf programs He Kuang
@ 2016-06-26 11:21 ` He Kuang
  2016-06-26 11:21 ` [RFC PATCH v2 19/26] perf tools: Register basic uBPF helpers He Kuang
                   ` (8 subsequent siblings)
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:21 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

Userspace bpf program has the ability to invoke helper functions
provided externally, this patch stores the helper functions in array
and adds methods for set/get functions in it. Theoretically the
function index can be up to UINT32_MAX, here we simply use an array
contains 64 function pointer slots.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Signed-off-by: He Kuang <hekuang@huawei.com>
---
 tools/lib/bpf/engine-ubpf.c | 25 +++++++++++++++++++++++++
 tools/lib/bpf/libbpf.h      | 16 ++++++++++++++++
 2 files changed, 41 insertions(+)

diff --git a/tools/lib/bpf/engine-ubpf.c b/tools/lib/bpf/engine-ubpf.c
index 9a0b425..e63a267 100644
--- a/tools/lib/bpf/engine-ubpf.c
+++ b/tools/lib/bpf/engine-ubpf.c
@@ -7,6 +7,31 @@
 #include "bpf.h"
 #include "libbpf-internal.h"
 
+static struct {
+	const char *name;
+	void *func;
+} ubpf_funcs[MAX_UBPF_FUNC];
+
+const void *libbpf_get_ubpf_func(unsigned int func_id)
+{
+	if (func_id >= MAX_UBPF_FUNC)
+		return NULL;
+
+	return ubpf_funcs[func_id].func;
+}
+
+int libbpf_set_ubpf_func(unsigned int idx, const char *name, void *func)
+{
+	if (idx >= MAX_UBPF_FUNC)
+		return -E2BIG;
+	if (!func)
+		return -EINVAL;
+
+	ubpf_funcs[idx].name = name;
+	ubpf_funcs[idx].func = func;
+	return 0;
+}
+
 static int engine__init(struct bpf_program *prog)
 {
 	struct ubpf_entry *instances_entries;
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index e01ab8e..19c92bd 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -188,6 +188,8 @@ int bpf_map__set_priv(struct bpf_map *map, void *priv,
 		      bpf_map_clear_priv_t clear_priv);
 void *bpf_map__priv(struct bpf_map *map);
 
+#define MAX_UBPF_FUNC	64
+
 /* The entity of ubpf program */
 struct ubpf_entry {
 	struct bpf_insn *insns;
@@ -196,6 +198,8 @@ struct ubpf_entry {
 #ifdef HAVE_UBPF_SUPPORT
 int bpf_program__set_ubpf(struct bpf_program *prog);
 bool bpf_program__is_ubpf(struct bpf_program *prog);
+const void *libbpf_get_ubpf_func(unsigned int func_id);
+int libbpf_set_ubpf_func(unsigned int idx, const char *name, void *func);
 #else
 static inline int
 bpf_program__set_ubpf(struct bpf_program *prog __maybe_unused)
@@ -207,6 +211,18 @@ bpf_program__is_ubpf(struct bpf_program *prog __maybe_unused)
 {
 	return false;
 }
+static inline
+const void *libbpf_get_ubpf_func(unsigned int func_id __maybe_unused)
+{
+	return NULL;
+}
+static inline int
+libbpf_set_ubpf_func(unsigned int idx __maybe_unused,
+		     const char *name __maybe_unused,
+		     void *func __maybe_unused)
+{
+	return -LIBBPF_ERRNO__NOUBPF;
+}
 #endif
 
 #endif
-- 
1.8.5.2

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

* [RFC PATCH v2 19/26] perf tools: Register basic uBPF helpers
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
                   ` (17 preceding siblings ...)
  2016-06-26 11:21 ` [RFC PATCH v2 18/26] perf bpf: Add ubpf helper function slots and set/get methods He Kuang
@ 2016-06-26 11:21 ` He Kuang
  2016-06-26 11:21 ` [RFC PATCH v2 20/26] perf bpf: Accept uBPF programs He Kuang
                   ` (7 subsequent siblings)
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:21 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

From: Wang Nan <wangnan0@huawei.com>

Reigster basic extern functions for uBPF programs.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Li Zefan <lizefan@huawei.com>
Signed-off-by: He Kuang <hekuang@huawei.com>
---
 tools/perf/perf.c                   |  3 ++
 tools/perf/util/Build               |  1 +
 tools/perf/util/ubpf-helpers-list.h | 11 ++++++
 tools/perf/util/ubpf-helpers.c      | 73 +++++++++++++++++++++++++++++++++++++
 tools/perf/util/ubpf-helpers.h      | 21 +++++++++++
 5 files changed, 109 insertions(+)
 create mode 100644 tools/perf/util/ubpf-helpers-list.h
 create mode 100644 tools/perf/util/ubpf-helpers.c
 create mode 100644 tools/perf/util/ubpf-helpers.h

diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 8f21922..f4c93c0 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -16,6 +16,7 @@
 #include "util/parse-events.h"
 #include <subcmd/parse-options.h>
 #include "util/bpf-loader.h"
+#include "util/ubpf-helpers.h"
 #include "util/debug.h"
 #include <api/fs/fs.h>
 #include <api/fs/tracing_path.h>
@@ -594,6 +595,8 @@ int main(int argc, const char **argv)
 
 	perf_debug_setup();
 
+	register_ubpf_helpers();
+
 	while (1) {
 		static int done_help;
 		int was_alias = run_argv(&argc, &argv);
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 1d24d94..d12ef7d 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -87,6 +87,7 @@ libperf-y += mem-events.o
 
 libperf-$(CONFIG_LIBBPF) += bpf-loader.o
 libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
+libperf-$(CONFIG_UBPF) += ubpf-helpers.o
 libperf-$(CONFIG_LIBELF) += symbol-elf.o
 libperf-$(CONFIG_LIBELF) += probe-file.o
 libperf-$(CONFIG_LIBELF) += probe-event.o
diff --git a/tools/perf/util/ubpf-helpers-list.h b/tools/perf/util/ubpf-helpers-list.h
new file mode 100644
index 0000000..02ad517
--- /dev/null
+++ b/tools/perf/util/ubpf-helpers-list.h
@@ -0,0 +1,11 @@
+DEF_UBPF_HELPER(int, ubpf_memcmp, (void *s1, void *s2, unsigned int n))
+DEF_UBPF_HELPER(void, ubpf_memcpy, (void *d, void *s, unsigned int size))
+DEF_UBPF_HELPER(int, ubpf_strcmp, (char *s1, char *s2))
+DEF_UBPF_HELPER(int, ubpf_printf, (char *fmt, ...))
+DEF_UBPF_HELPER(int, ubpf_map_lookup_elem,
+		(void *map_desc, void *key, void *value))
+DEF_UBPF_HELPER(int, ubpf_map_update_elem,
+		(void *map_desc, void *key, void *value,
+		 unsigned long long flags))
+DEF_UBPF_HELPER(int, ubpf_map_get_next_key,
+		(void *map_desc, void *key, void *next_key))
diff --git a/tools/perf/util/ubpf-helpers.c b/tools/perf/util/ubpf-helpers.c
new file mode 100644
index 0000000..8b83fc8
--- /dev/null
+++ b/tools/perf/util/ubpf-helpers.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016, Wang Nan <wangnan0@huawei.com>
+ * Copyright (C) 2016, Huawei Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include <bpf/libbpf.h>
+#include <bpf/bpf.h>
+#include <ubpf.h>
+
+#include "ubpf-helpers.h"
+
+static int __maybe_unused
+ubpf_memcmp(void *s1, void *s2, unsigned int n)
+{
+	return memcmp(s1, s2, n);
+}
+
+static void __maybe_unused
+ubpf_memcpy(void *d, void *s, unsigned int n)
+{
+	memcpy(d, s, n);
+}
+
+static int __maybe_unused
+ubpf_strcmp(char *s1, char *s2)
+{
+	return strcmp(s1, s2);
+}
+
+static int __maybe_unused
+ubpf_printf(char *fmt, ...)
+{
+	int ret;
+	va_list ap;
+
+	va_start(ap, fmt);
+	ret = vprintf(fmt, ap);
+	va_end(ap);
+
+	return ret;
+}
+
+static int __maybe_unused
+ubpf_map_lookup_elem(int map_fd, void *key, void *value)
+{
+	return bpf_map_lookup_elem(map_fd, key, value);
+}
+
+static int __maybe_unused
+ubpf_map_update_elem(int map_fd, void *key, void *value,
+				unsigned long long flags)
+{
+	return bpf_map_update_elem(map_fd, key, value, (u64)flags);
+}
+
+static int __maybe_unused
+ubpf_map_get_next_key(int map_fd, void *key, void *next_key)
+{
+	return bpf_map_get_next_key(map_fd, key, next_key);
+}
+
+void register_ubpf_helpers(void)
+{
+#define DEF_UBPF_HELPER(type, name, param)			\
+	libbpf_set_ubpf_func(UBPF_FUNC_##name, #name, name);
+#include "ubpf-helpers-list.h"
+#undef DEF_UBPF_HELPER
+}
diff --git a/tools/perf/util/ubpf-helpers.h b/tools/perf/util/ubpf-helpers.h
new file mode 100644
index 0000000..7432715
--- /dev/null
+++ b/tools/perf/util/ubpf-helpers.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016, Wang Nan <wangnan0@huawei.com>
+ * Copyright (C) 2016, Huawei Inc.
+ */
+#ifndef __UBPF_HELPERS_H
+#define __UBPF_HELPERS_H
+
+#define DEF_UBPF_HELPER(type, name, param) UBPF_FUNC_##name,
+enum {
+	UBPF_FUNC_unspec = 0,
+#include "ubpf-helpers-list.h"
+	UBPF_FUNC_MAX
+};
+#undef DEF_UBPF_HELPER
+
+#ifdef HAVE_UBPF_SUPPORT
+void register_ubpf_helpers(void);
+#else
+static inline void register_ubpf_helpers(void) {};
+#endif
+#endif
-- 
1.8.5.2

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

* [RFC PATCH v2 20/26] perf bpf: Accept uBPF programs
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
                   ` (18 preceding siblings ...)
  2016-06-26 11:21 ` [RFC PATCH v2 19/26] perf tools: Register basic uBPF helpers He Kuang
@ 2016-06-26 11:21 ` He Kuang
  2016-06-26 11:21 ` [RFC PATCH v2 21/26] bpf: Support bpf load/store boundary check for ubpf He Kuang
                   ` (6 subsequent siblings)
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:21 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

From: Wang Nan <wangnan0@huawei.com>

This patch allows user passing a uBPF function through bpf file with
section name leading with 'UBPF;'. For example:

 #define SEC(NAME) __attribute__((section(NAME), used))
 SEC("UBPF;perf_record_exit")
 void record_exit(int *samples)
 {
    char fmt[] = "Hello! receive %d samples\n";
    ubpf_printf(fmt, *samples);
 }

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Li Zefan <lizefan@huawei.com>
Signed-off-by: He Kuang <hekuang@huawei.com>
---
 tools/perf/util/bpf-loader.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 2ac73e3..288b941 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -305,6 +305,19 @@ config_bpf_program(struct bpf_program *prog)
 		return PTR_ERR(config_str);
 	}
 
+	if (strncmp(config_str, "UBPF;", 5) == 0) {
+		pr_debug("bpf: load a UBPF program %s\n", config_str);
+		err = bpf_program__set_ubpf(prog);
+		if (err) {
+			char errbuf[BUFSIZ];
+
+			libbpf_strerror(err, errbuf, sizeof(errbuf));
+			pr_warning("Set %s to ubpf failed: %s\n", config_str, errbuf);
+			return err;
+		}
+		return 0;
+	}
+
 	priv = calloc(sizeof(*priv), 1);
 	if (!priv) {
 		pr_debug("bpf: failed to alloc priv\n");
@@ -604,6 +617,9 @@ int bpf__probe(struct bpf_object *obj)
 		if (err)
 			goto out;
 
+		if (bpf_program__is_ubpf(prog))
+			continue;
+
 		priv = bpf_program__priv(prog);
 		if (IS_ERR(priv) || !priv) {
 			err = PTR_ERR(priv);
@@ -649,6 +665,9 @@ int bpf__unprobe(struct bpf_object *obj)
 		struct bpf_prog_priv *priv = bpf_program__priv(prog);
 		int i;
 
+		if (bpf_program__is_ubpf(prog))
+			continue;
+
 		if (IS_ERR(priv) || !priv)
 			continue;
 
@@ -705,6 +724,9 @@ int bpf__foreach_tev(struct bpf_object *obj,
 		struct perf_probe_event *pev;
 		int i, fd;
 
+		if (bpf_program__is_ubpf(prog))
+			continue;
+
 		if (IS_ERR(priv) || !priv) {
 			pr_debug("bpf: failed to get private field\n");
 			return -BPF_LOADER_ERRNO__INTERNAL;
-- 
1.8.5.2

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

* [RFC PATCH v2 21/26] bpf: Support bpf load/store boundary check for ubpf
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
                   ` (19 preceding siblings ...)
  2016-06-26 11:21 ` [RFC PATCH v2 20/26] perf bpf: Accept uBPF programs He Kuang
@ 2016-06-26 11:21 ` He Kuang
  2016-06-26 11:21 ` [RFC PATCH v2 22/26] perf bpf: Implement boundary check code in ubpf He Kuang
                   ` (5 subsequent siblings)
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:21 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

A boundary check is added before each store/load instruction, since we
don't have a verifier in userspace bpf. There's no functionality
change without UBPF_BUILD flag.

Signed-off-by: He Kuang <hekuang@huawei.com>
---
 kernel/bpf/vm.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/kernel/bpf/vm.c b/kernel/bpf/vm.c
index add5669..0ddb592 100644
--- a/kernel/bpf/vm.c
+++ b/kernel/bpf/vm.c
@@ -76,9 +76,13 @@ static inline int bpf_vm_jmp_tail_call_handler(u64 *regs, u32 *p_tail_call_cnt,
 	*p_insn = prog->insnsi;
 	return 0;
 }
-#endif /* UBPF_BUILD */
-
+#define BOUNDS_CHECK_STORE(size)
+#define BOUNDS_CHECK_LOAD(size)
 unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn)
+#else
+unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn,
+			    size_t ctx_len)
+#endif /* UBPF_BUILD */
 {
 	u64 stack[MAX_BPF_STACK / sizeof(u64)];
 	u64 regs[MAX_BPF_REG], tmp;
@@ -419,12 +423,15 @@ select_insn:
 	/* STX and ST and LDX*/
 #define LDST(SIZEOP, SIZE)						\
 	STX_MEM_##SIZEOP:						\
+		BOUNDS_CHECK_STORE(sizeof(SIZE));			\
 		*(SIZE *)(unsigned long) (DST + insn->off) = SRC;	\
 		CONT;							\
 	ST_MEM_##SIZEOP:						\
+		BOUNDS_CHECK_STORE(sizeof(SIZE));			\
 		*(SIZE *)(unsigned long) (DST + insn->off) = IMM;	\
 		CONT;							\
 	LDX_MEM_##SIZEOP:						\
+		BOUNDS_CHECK_LOAD(sizeof(SIZE));			\
 		DST = *(SIZE *)(unsigned long) (SRC + insn->off);	\
 		CONT;
 
-- 
1.8.5.2

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

* [RFC PATCH v2 22/26] perf bpf: Implement boundary check code in ubpf
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
                   ` (20 preceding siblings ...)
  2016-06-26 11:21 ` [RFC PATCH v2 21/26] bpf: Support bpf load/store boundary check for ubpf He Kuang
@ 2016-06-26 11:21 ` He Kuang
  2016-06-26 11:21 ` [RFC PATCH v2 23/26] perf record: Add uBPF hooks at beginning and end of perf record He Kuang
                   ` (4 subsequent siblings)
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:21 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

Make sure that ubpf load/store instructions only access the context
and stack region.

Signed-off-by: He Kuang <hekuang@huawei.com>
---
 tools/perf/util/bpf-vm.c | 35 +++++++++++++++++++++++++++++++++++
 tools/perf/util/bpf-vm.h |  3 ++-
 2 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/bpf-vm.c b/tools/perf/util/bpf-vm.c
index 23ac784..191ed42 100644
--- a/tools/perf/util/bpf-vm.c
+++ b/tools/perf/util/bpf-vm.c
@@ -2,6 +2,11 @@
 #include "util.h"
 #include "tools/be_byteshift.h"
 #include "bpf-vm.h"
+#include "debug.h"
+#include <linux/filter.h>
+
+#define DST	regs[insn->dst_reg]
+#define SRC	regs[insn->src_reg]
 
 static inline void
 bpf_vm_jmp_call_handler(u64 *regs __maybe_unused, void *ctx __maybe_unused,
@@ -30,5 +35,35 @@ static inline void *bpf_load_pointer(const void *skb __maybe_unused,
 	return NULL;
 }
 
+static bool
+bounds_check(void *addr, int size, void *ctx, size_t ctx_len, void *stack)
+{
+	if (ctx && (addr >= ctx && (addr + size) <= (ctx + ctx_len))) {
+		/* Context access */
+		return true;
+	} else if (addr >= stack && (addr + size) <= (stack + MAX_BPF_STACK)) {
+		/* Stack access */
+		return true;
+	}
+
+	pr_debug("bpf: bounds_check failed\n");
+	return false;
+}
+
+#define BOUNDS_CHECK_LOAD(size)						\
+	do {								\
+		if (!bounds_check((void *)SRC + insn->off, size,	\
+				  ctx, ctx_len, stack)) {		\
+			return -1;					\
+		}							\
+	} while (0)
+#define BOUNDS_CHECK_STORE(size)					\
+	do {								\
+		if (!bounds_check((void *)DST + insn->off, size,	\
+				  ctx, ctx_len, stack)) {		\
+			return -1;					\
+		}							\
+	} while (0)
+
 #define UBPF_BUILD
 #include <../../../kernel/bpf/vm.c>
diff --git a/tools/perf/util/bpf-vm.h b/tools/perf/util/bpf-vm.h
index bf96caa..66956fbb 100644
--- a/tools/perf/util/bpf-vm.h
+++ b/tools/perf/util/bpf-vm.h
@@ -2,6 +2,7 @@
 #define _BPF_VM_H
 
 struct bpf_insn;
-unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn);
+unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn,
+			    size_t ctx_len);
 
 #endif /* _BPF_VM_H */
-- 
1.8.5.2

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

* [RFC PATCH v2 23/26] perf record: Add uBPF hooks at beginning and end of perf record
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
                   ` (21 preceding siblings ...)
  2016-06-26 11:21 ` [RFC PATCH v2 22/26] perf bpf: Implement boundary check code in ubpf He Kuang
@ 2016-06-26 11:21 ` He Kuang
  2016-06-26 11:21 ` [RFC PATCH v2 24/26] perf bpf: Fillup bpf jmp_call handler He Kuang
                   ` (3 subsequent siblings)
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:21 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

Like tracepoint in kernel code, uBPF hooks can be added in perf code and
trigger uBPF programs passed by BPF scripts. The first two uBPF hooks
added are record start/end. uBPF scripts can initial BPF maps in
record start, and report result when record finished.

Signed-off-by: He Kuang <hekuang@huawei.com>
Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/perf/builtin-record.c       |  4 +++
 tools/perf/util/Build             |  2 +-
 tools/perf/util/ubpf-hooks-list.h | 34 ++++++++++++++++++++
 tools/perf/util/ubpf-hooks.c      | 68 +++++++++++++++++++++++++++++++++++++++
 tools/perf/util/ubpf-hooks.h      | 41 +++++++++++++++++++++++
 5 files changed, 148 insertions(+), 1 deletion(-)
 create mode 100644 tools/perf/util/ubpf-hooks-list.h
 create mode 100644 tools/perf/util/ubpf-hooks.c
 create mode 100644 tools/perf/util/ubpf-hooks.h

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 81411b1..c956d57 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -36,6 +36,7 @@
 #include "util/llvm-utils.h"
 #include "util/bpf-loader.h"
 #include "util/trigger.h"
+#include "util/ubpf-hooks.h"
 #include "asm/bug.h"
 
 #include <unistd.h>
@@ -893,6 +894,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 
 	trigger_ready(&auxtrace_snapshot_trigger);
 	trigger_ready(&switch_output_trigger);
+	ubpf_hook_perf_record_start(0);
 	for (;;) {
 		unsigned long long hits = rec->samples;
 
@@ -957,6 +959,8 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 			disabled = true;
 		}
 	}
+	ubpf_hook_perf_record_end(rec->samples, 0);
+
 	trigger_off(&auxtrace_snapshot_trigger);
 	trigger_off(&switch_output_trigger);
 
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index d12ef7d..80f3c20 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -87,7 +87,7 @@ libperf-y += mem-events.o
 
 libperf-$(CONFIG_LIBBPF) += bpf-loader.o
 libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
-libperf-$(CONFIG_UBPF) += ubpf-helpers.o
+libperf-$(CONFIG_UBPF) += ubpf-helpers.o ubpf-hooks.o
 libperf-$(CONFIG_LIBELF) += symbol-elf.o
 libperf-$(CONFIG_LIBELF) += probe-file.o
 libperf-$(CONFIG_LIBELF) += probe-event.o
diff --git a/tools/perf/util/ubpf-hooks-list.h b/tools/perf/util/ubpf-hooks-list.h
new file mode 100644
index 0000000..b796334
--- /dev/null
+++ b/tools/perf/util/ubpf-hooks-list.h
@@ -0,0 +1,34 @@
+UBPF_HOOK(perf_record_start,
+	  __UBPF_HOOK_PROTO(
+		  __proto(int dummy)
+		  ),
+
+	  __UBPF_HOOK_ARGS(dummy),
+
+	  __UBPF_HOOK_STRUCT__entry(
+		  __field(int,	dummy)
+		  ),
+
+	  __UBPF_HOOK_ASSIGN(
+		  __entry.dummy = dummy;
+		  )
+	);
+
+UBPF_HOOK(perf_record_end,
+	  __UBPF_HOOK_PROTO(
+		  __proto(int samples),
+		  __proto(int dummy)
+		  ),
+
+	  __UBPF_HOOK_ARGS(samples, dummy),
+
+	  __UBPF_HOOK_STRUCT__entry(
+		  __field(int,	samples)
+		  __field(int,	dummy)
+		  ),
+
+	  __UBPF_HOOK_ASSIGN(
+		  __entry.samples = samples;
+		  __entry.dummy = dummy;
+		  )
+	);
diff --git a/tools/perf/util/ubpf-hooks.c b/tools/perf/util/ubpf-hooks.c
new file mode 100644
index 0000000..6ffe344
--- /dev/null
+++ b/tools/perf/util/ubpf-hooks.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016, Wang Nan <wangnan0@huawei.com>
+ * Copyright (C) 2016, He Kuang <hekuang@huawei.com>
+ * Copyright (C) 2016, Huawei Inc.
+ */
+
+#include <bpf/libbpf.h>
+#include <asm/bug.h>
+#include <ubpf.h>
+#include "ubpf-hooks.h"
+#include "debug.h"
+
+static int run_ubpf_program(struct bpf_program *prog __maybe_unused,
+			    void *mem __maybe_unused, size_t len __maybe_unused)
+{
+	return 0;
+}
+
+static int
+run_ubpf_programs(const char *expect_title, void *mem, size_t len)
+{
+
+	struct bpf_object *obj, *tmp;
+	struct bpf_program *prog;
+	const char *title;
+	int err;
+
+	bpf_object__for_each_safe(obj, tmp) {
+		bpf_object__for_each_program(prog, obj) {
+			if (bpf_program__is_ubpf(prog)) {
+				title = bpf_program__title(prog, false);
+				if (!title)
+					continue;
+				if (strcmp(title, expect_title) != 0)
+					continue;
+				err = run_ubpf_program(prog, mem, len);
+				if (err)
+					return err;
+			}
+		}
+	}
+
+	return 0;
+}
+
+#define __UBPF_HOOK_PROTO(args...) args
+#define __UBPF_HOOK_ARG(args...) args
+#define __UBPF_HOOK_STRUCT__entry(args...) args
+#define __proto(args) args
+#define __field(type, item)		type	item;
+
+#define UBPF_HOOK(name, proto, args, tstruct, assign)	\
+	struct ubpf_hook_##name##_proto {tstruct}
+#include "ubpf-hooks-list.h"
+#undef UBPF_HOOK
+
+#define __UBPF_HOOK_ASSIGN(code...) code
+
+#define UBPF_HOOK(name, proto, args, tstruct, assign)			\
+	int ubpf_hook_##name(proto)					\
+	{								\
+		struct ubpf_hook_##name##_proto __entry;		\
+		assign;							\
+		return run_ubpf_programs("UBPF;"#name,			\
+					 &__entry, sizeof(__entry));	\
+	}
+#include "ubpf-hooks-list.h"
+#undef UBPF_HOOK
diff --git a/tools/perf/util/ubpf-hooks.h b/tools/perf/util/ubpf-hooks.h
new file mode 100644
index 0000000..4d2f23e
--- /dev/null
+++ b/tools/perf/util/ubpf-hooks.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2016, Wang Nan <wangnan0@huawei.com>
+ * Copyright (C) 2016, He Kuang <hekuang@huawei.com>
+ * Copyright (C) 2016, Huawei Inc.
+ */
+#ifndef __PERF_UBPF_HOOKS_H
+#define __PERF_UBPF_HOOKS_H
+
+#include <linux/compiler.h>
+
+#define UBPF_HOOK_BREAKABLE	1
+
+#define __UBPF_HOOK_PROTO(args...) args
+#define __UBPF_HOOK_ARG(args...) args
+#define __UBPF_HOOK_STRUCT__entry(args...) args
+#define __field(type, item)		type	item;
+
+#ifdef HAVE_UBPF_SUPPORT
+
+#define __proto(args) args
+#define UBPF_HOOK(name, proto, args, struct, assign) int ubpf_hook_##name(proto)
+
+#include "ubpf-hooks-list.h"
+
+#else
+
+#define __proto(args) args __maybe_unused
+#define UBPF_HOOK(name, proto, args, struct, assign)		\
+	static inline int ubpf_hook_##name(proto) {return 0; }	\
+
+#include "ubpf-hooks-list.h"
+#endif
+
+#undef UBPF_HOOK
+#undef __UBPF_HOOK_PROTO
+#undef __UBPF_HOOK_ARG
+#undef __UBPF_HOOK_STRUCT__entry
+#undef __field
+#undef __proto
+
+#endif /* __PERF_UBPF_HOOKS_H */
-- 
1.8.5.2

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

* [RFC PATCH v2 24/26] perf bpf: Fillup bpf jmp_call handler
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
                   ` (22 preceding siblings ...)
  2016-06-26 11:21 ` [RFC PATCH v2 23/26] perf record: Add uBPF hooks at beginning and end of perf record He Kuang
@ 2016-06-26 11:21 ` He Kuang
  2016-06-26 11:21 ` [RFC PATCH v2 25/26] perf bpf: Implement run_ubpf_program He Kuang
                   ` (2 subsequent siblings)
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:21 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

Let ubpf invoke function calls. The function index is stored in
insns->imm, use it to fetch the corresponding functions in libbpf and
make the function call.

Signed-off-by: He Kuang <hekuang@huawei.com>
---
 tools/perf/util/bpf-vm.c | 24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/bpf-vm.c b/tools/perf/util/bpf-vm.c
index 191ed42..bbe58be 100644
--- a/tools/perf/util/bpf-vm.c
+++ b/tools/perf/util/bpf-vm.c
@@ -4,13 +4,33 @@
 #include "bpf-vm.h"
 #include "debug.h"
 #include <linux/filter.h>
+#include "bpf/libbpf.h"
+#include <linux/bpf.h>
+
+#define BPF_R0	regs[BPF_REG_0]
+#define BPF_R1	regs[BPF_REG_1]
+#define BPF_R2	regs[BPF_REG_2]
+#define BPF_R3	regs[BPF_REG_3]
+#define BPF_R4	regs[BPF_REG_4]
+#define BPF_R5	regs[BPF_REG_5]
 
 #define DST	regs[insn->dst_reg]
 #define SRC	regs[insn->src_reg]
 
 static inline void
-bpf_vm_jmp_call_handler(u64 *regs __maybe_unused, void *ctx __maybe_unused,
-			const struct bpf_insn *insn __maybe_unused) {}
+bpf_vm_jmp_call_handler(u64 *regs, void *ctx __maybe_unused,
+			const struct bpf_insn *insn)
+{
+	const void *xfunc;
+	u64 (*func)(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5);
+
+	xfunc = libbpf_get_ubpf_func(insn->imm);
+	if (xfunc) {
+		func = xfunc;
+		BPF_R0 = func(BPF_R1, BPF_R2, BPF_R3,
+			      BPF_R4, BPF_R5);
+	}
+}
 
 static inline int
 bpf_vm_jmp_tail_call_handler(u64 *regs __maybe_unused,
-- 
1.8.5.2

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

* [RFC PATCH v2 25/26] perf bpf: Implement run_ubpf_program
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
                   ` (23 preceding siblings ...)
  2016-06-26 11:21 ` [RFC PATCH v2 24/26] perf bpf: Fillup bpf jmp_call handler He Kuang
@ 2016-06-26 11:21 ` He Kuang
  2016-06-26 11:21 ` [RFC PATCH v2 26/26] perf tests: Add uBPF test case He Kuang
  2016-06-26 20:48 ` [RFC PATCH v2 00/26] perf tools: Support uBPF script Alexei Starovoitov
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:21 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

Fill up the run_ubpf_program slot by fetching the ubpf entry and call
__bpf_prog_run().

Signed-off-by: He Kuang <hekuang@huawei.com>
Signed-off-by: Wang Nan <wangnan0@huawei.com>
---
 tools/perf/util/ubpf-hooks.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/ubpf-hooks.c b/tools/perf/util/ubpf-hooks.c
index 6ffe344..da19fab 100644
--- a/tools/perf/util/ubpf-hooks.c
+++ b/tools/perf/util/ubpf-hooks.c
@@ -8,12 +8,25 @@
 #include <asm/bug.h>
 #include <ubpf.h>
 #include "ubpf-hooks.h"
+#include "bpf-vm.h"
 #include "debug.h"
 
-static int run_ubpf_program(struct bpf_program *prog __maybe_unused,
-			    void *mem __maybe_unused, size_t len __maybe_unused)
+static int
+run_ubpf_program(struct bpf_program *prog, void *mem, size_t len)
 {
-	return 0;
+	struct ubpf_entry *entry;
+	int ret;
+
+	entry = bpf_program__vm(prog);
+	if (!entry) {
+		WARN_ONCE(!entry, "Unable to fetch entry from UBPF program\n");
+		return -EINVAL;
+	}
+
+	ret = __bpf_prog_run(mem, entry->insns, len);
+	pr_debug("program %s returns %d\n",
+		 bpf_program__title(prog, false), ret);
+	return ret;
 }
 
 static int
-- 
1.8.5.2

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

* [RFC PATCH v2 26/26] perf tests: Add uBPF test case
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
                   ` (24 preceding siblings ...)
  2016-06-26 11:21 ` [RFC PATCH v2 25/26] perf bpf: Implement run_ubpf_program He Kuang
@ 2016-06-26 11:21 ` He Kuang
  2016-06-26 20:48 ` [RFC PATCH v2 00/26] perf tools: Support uBPF script Alexei Starovoitov
  26 siblings, 0 replies; 38+ messages in thread
From: He Kuang @ 2016-06-26 11:21 UTC (permalink / raw)
  To: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, hekuang
  Cc: linux-kernel

From: Wang Nan <wangnan0@huawei.com>

Introduce a BPF script use uBPF, test compiling, helper and hook.
Validate passing information through helper and hooks.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Signed-off-by: He Kuang <hekuang@huawei.com>
---
 tools/perf/tests/Build                  |  8 +++
 tools/perf/tests/bpf-script-test-ubpf.c | 88 +++++++++++++++++++++++++++++++++
 tools/perf/tests/bpf.c                  | 78 ++++++++++++++++++++++++++++-
 tools/perf/tests/llvm.c                 |  4 ++
 tools/perf/tests/llvm.h                 |  2 +
 5 files changed, 178 insertions(+), 2 deletions(-)
 create mode 100644 tools/perf/tests/bpf-script-test-ubpf.c

diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 66a2898..74da237 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -32,6 +32,7 @@ perf-y += parse-no-sample-id-all.o
 perf-y += kmod-path.o
 perf-y += thread-map.o
 perf-y += llvm.o llvm-src-base.o llvm-src-kbuild.o llvm-src-prologue.o llvm-src-relocation.o
+perf-y += llvm-src-ubpf.o
 perf-y += bpf.o
 perf-y += topology.o
 perf-y += cpumap.o
@@ -68,6 +69,13 @@ $(OUTPUT)tests/llvm-src-relocation.c: tests/bpf-script-test-relocation.c tests/B
 	$(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
 	$(Q)echo ';' >> $@
 
+$(OUTPUT)tests/llvm-src-ubpf.c: tests/bpf-script-test-ubpf.c tests/Build
+	$(call rule_mkdir)
+	$(Q)echo '#include <tests/llvm.h>' > $@
+	$(Q)echo 'const char test_llvm__bpf_test_ubpf[] =' >> $@
+	$(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
+	$(Q)echo ';' >> $@
+
 ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64))
 perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
 endif
diff --git a/tools/perf/tests/bpf-script-test-ubpf.c b/tools/perf/tests/bpf-script-test-ubpf.c
new file mode 100644
index 0000000..5064ee9
--- /dev/null
+++ b/tools/perf/tests/bpf-script-test-ubpf.c
@@ -0,0 +1,88 @@
+/*
+ * bpf-script-test-ubpf.c
+ * Test user space BPF
+ */
+
+#ifndef LINUX_VERSION_CODE
+# error Need LINUX_VERSION_CODE
+# error Example: for 4.2 kernel, put 'clang-opt="-DLINUX_VERSION_CODE=0x40200" into llvm section of ~/.perfconfig'
+#endif
+#define BPF_ANY 0
+#define BPF_MAP_TYPE_ARRAY 2
+#define BPF_FUNC_map_lookup_elem 1
+#define BPF_FUNC_map_update_elem 2
+
+static void *(*bpf_map_lookup_elem)(void *map, void *key) =
+	(void *) BPF_FUNC_map_lookup_elem;
+static
+void *(*bpf_map_update_elem)(void *map, void *key, void *value, int flags) =
+	(void *) BPF_FUNC_map_update_elem;
+
+struct bpf_map_def {
+	unsigned int type;
+	unsigned int key_size;
+	unsigned int value_size;
+	unsigned int max_entries;
+};
+
+#define SEC(NAME) __attribute__((section(NAME), used))
+SEC("maps")
+struct bpf_map_def counter = {
+	.type = BPF_MAP_TYPE_ARRAY,
+	.key_size = sizeof(int),
+	.value_size = sizeof(int),
+	.max_entries = 1,
+};
+
+SEC("func=sys_epoll_pwait")
+int bpf_func__sys_epoll_pwait(void *ctx)
+{
+	int ind = 0;
+	int *flag = bpf_map_lookup_elem(&counter, &ind);
+
+	if (!flag)
+		return 0;
+	__sync_fetch_and_add(flag, 1);
+	return 0;
+}
+char _license[] SEC("license") = "GPL";
+int _version SEC("version") = LINUX_VERSION_CODE;
+
+#define UBPF_FUNC_printf		4
+#define UBPF_FUNC_map_lookup_elem	5
+#define UBPF_FUNC_map_update_elem	6
+#define UBPF_FUNC_test_report		63
+
+static int (*ubpf_printf)(char *fmt, ...) = (void *)UBPF_FUNC_printf;
+static void
+(*ubpf_map_lookup_elem)(struct bpf_map_def *, void *, void *) =
+	(void *)UBPF_FUNC_map_lookup_elem;
+static void
+(*ubpf_map_update_elem)(struct bpf_map_def *, void *, void *, int flags) =
+	(void *)UBPF_FUNC_map_update_elem;
+static void (*ubpf_test_report)(int) = (void *)UBPF_FUNC_test_report;
+
+struct perf_record_end_ctx {
+	int samples;
+	int dummy;
+};
+
+SEC("UBPF;perf_record_start")
+int perf_record_start(void)
+{
+	int idx = 0, val = 1000;
+
+	ubpf_map_update_elem(&counter, &idx, &val, 0);
+	return 0;
+}
+
+SEC("UBPF;perf_record_end")
+int perf_record_end(struct perf_record_end_ctx *ctx)
+{
+	int idx = 0, val;
+
+	ubpf_map_lookup_elem(&counter, &idx, &val);
+	ubpf_test_report(val + ctx->samples);
+
+	return 0;
+}
diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
index f31eed3..0c094e6 100644
--- a/tools/perf/tests/bpf.c
+++ b/tools/perf/tests/bpf.c
@@ -5,10 +5,13 @@
 #include <util/evlist.h>
 #include <linux/bpf.h>
 #include <linux/filter.h>
+#include <bpf/libbpf.h>
 #include <bpf/bpf.h>
 #include "tests.h"
 #include "llvm.h"
 #include "debug.h"
+#include "ubpf-helpers.h"
+#include "ubpf-hooks.h"
 #define NR_ITERS       111
 
 #ifdef HAVE_LIBBPF_SUPPORT
@@ -46,6 +49,35 @@ static int llseek_loop(void)
 
 #endif
 
+union testcase_context {
+	void *ptr;
+	unsigned long num;
+};
+
+#ifdef HAVE_UBPF_SUPPORT
+static int __ubpf_report_val;
+
+static void test_report(int val)
+{
+	printf("test_report val = %d\n", val);
+	__ubpf_report_val = val;
+}
+
+static int ubpf_prepare(union testcase_context *ctx __maybe_unused)
+{
+	ubpf_hook_perf_record_start(0);
+	return 0;
+}
+
+static int ubpf_verify(union testcase_context *ctx __maybe_unused)
+{
+	ubpf_hook_perf_record_end(1234, 0);
+	if (__ubpf_report_val != 1234 + NR_ITERS + 1000)
+		return TEST_FAIL;
+	return TEST_OK;
+}
+#endif
+
 static struct {
 	enum test_llvm__testcase prog_id;
 	const char *desc;
@@ -54,6 +86,10 @@ static struct {
 	const char *msg_load_fail;
 	int (*target_func)(void);
 	int expect_result;
+
+	union testcase_context context;
+	int (*prepare)(union testcase_context *);
+	int (*verify)(union testcase_context *);
 } bpf_testcase_table[] = {
 	{
 		LLVM_TESTCASE_BASE,
@@ -63,6 +99,7 @@ static struct {
 		"load bpf object failed",
 		&epoll_pwait_loop,
 		(NR_ITERS + 1) / 2,
+		{0}, NULL, NULL
 	},
 #ifdef HAVE_BPF_PROLOGUE
 	{
@@ -73,6 +110,7 @@ static struct {
 		"check your vmlinux setting?",
 		&llseek_loop,
 		(NR_ITERS + 1) / 4,
+		{0}, NULL, NULL
 	},
 #endif
 	{
@@ -83,11 +121,27 @@ static struct {
 		"libbpf error when dealing with relocation",
 		NULL,
 		0,
+		{0}, NULL, NULL
 	},
+#ifdef HAVE_UBPF_SUPPORT
+	{
+		LLVM_TESTCASE_BPF_UBPF,
+		"Test UBPF support",
+		"[bpf_ubpf_test]",
+		"fix 'perf test LLVM' first",
+		"failed to load UBPF",
+		&epoll_pwait_loop,
+		0,
+		{0}, ubpf_prepare, ubpf_verify,
+	}
+#endif
 };
 
 static int do_test(struct bpf_object *obj, int (*func)(void),
-		   int expect)
+		   int expect,
+		   int (*prepare)(union testcase_context *),
+		   int (*verify)(union testcase_context *),
+		   union testcase_context *ctx)
 {
 	struct record_opts opts = {
 		.target = {
@@ -154,6 +208,14 @@ static int do_test(struct bpf_object *obj, int (*func)(void),
 		goto out_delete_evlist;
 	}
 
+	if (prepare) {
+		err = prepare(ctx);
+		if (err < 0) {
+			pr_debug("prepare fail\n");
+			goto out_delete_evlist;
+		}
+	}
+
 	perf_evlist__enable(evlist);
 	(*func)();
 	perf_evlist__disable(evlist);
@@ -176,6 +238,8 @@ static int do_test(struct bpf_object *obj, int (*func)(void),
 
 	ret = TEST_OK;
 
+	if (verify)
+		ret = verify(ctx);
 out_delete_evlist:
 	perf_evlist__delete(evlist);
 	return ret;
@@ -201,6 +265,13 @@ static int __test__bpf(int idx)
 	size_t obj_buf_sz;
 	struct bpf_object *obj;
 
+#ifdef HAVE_UBPF_SUPPORT
+	ret = libbpf_set_ubpf_func(63, "test_report", test_report);
+	if (ret) {
+		pr_debug("Unable to set UBPF helper function\n");
+		return TEST_FAIL;
+	}
+#endif
 	ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
 				       bpf_testcase_table[idx].prog_id,
 				       true, NULL);
@@ -229,7 +300,10 @@ static int __test__bpf(int idx)
 	if (obj)
 		ret = do_test(obj,
 			      bpf_testcase_table[idx].target_func,
-			      bpf_testcase_table[idx].expect_result);
+			      bpf_testcase_table[idx].expect_result,
+			      bpf_testcase_table[idx].prepare,
+			      bpf_testcase_table[idx].verify,
+			      &bpf_testcase_table[idx].context);
 out:
 	bpf__clear();
 	return ret;
diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c
index cff564f..92b0a42 100644
--- a/tools/perf/tests/llvm.c
+++ b/tools/perf/tests/llvm.c
@@ -48,6 +48,10 @@ static struct {
 		.desc = "Compile source for BPF relocation test",
 		.should_load_fail = true,
 	},
+	[LLVM_TESTCASE_BPF_UBPF] = {
+		.source = test_llvm__bpf_test_ubpf,
+		.desc = "Compile source for UBPF test",
+	},
 };
 
 int
diff --git a/tools/perf/tests/llvm.h b/tools/perf/tests/llvm.h
index 0eaa604..8ae4aae 100644
--- a/tools/perf/tests/llvm.h
+++ b/tools/perf/tests/llvm.h
@@ -8,12 +8,14 @@ extern const char test_llvm__bpf_base_prog[];
 extern const char test_llvm__bpf_test_kbuild_prog[];
 extern const char test_llvm__bpf_test_prologue_prog[];
 extern const char test_llvm__bpf_test_relocation[];
+extern const char test_llvm__bpf_test_ubpf[];
 
 enum test_llvm__testcase {
 	LLVM_TESTCASE_BASE,
 	LLVM_TESTCASE_KBUILD,
 	LLVM_TESTCASE_BPF_PROLOGUE,
 	LLVM_TESTCASE_BPF_RELOCATION,
+	LLVM_TESTCASE_BPF_UBPF,
 	__LLVM_TESTCASE_MAX,
 };
 
-- 
1.8.5.2

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

* Re: [RFC PATCH v2 00/26] perf tools: Support uBPF script
  2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
                   ` (25 preceding siblings ...)
  2016-06-26 11:21 ` [RFC PATCH v2 26/26] perf tests: Add uBPF test case He Kuang
@ 2016-06-26 20:48 ` Alexei Starovoitov
  2016-06-27  2:10   ` Hekuang
  2016-06-28 11:47   ` Hekuang
  26 siblings, 2 replies; 38+ messages in thread
From: Alexei Starovoitov @ 2016-06-26 20:48 UTC (permalink / raw)
  To: He Kuang
  Cc: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, linux-kernel

On Sun, Jun 26, 2016 at 11:20:52AM +0000, He Kuang wrote:
> This patchset is based on Wang Nan's v1:
>      http://thread.gmane.org/gmane.linux.kernel/2203717/focus=2203707
> 
> """ 
>   This patch set allows to perf invoke some user space BPF scripts on
>   some point. uBPF scripts and kernel BPF scripts reside in one BPF
>   object.  They communicate with each other with BPF maps. uBPF
>   scripts can invoke helper functions provided by perf.
>   
>   At least following new features can be achieved based on uBPF
>   support:
>   
>    1) Report statistical result:
> 
>       Like DTrace, perf print statistical report before quit. No need
>       to extract data using 'perf report'. Statistical method is
>       controled by user.
>   
>    2) Control perf's behavior:
> 
>       Dynamically adjust period of different events. Policy is defined
>       by user.
> """
> 
> and modified by following the reviewers' suggestions.
> 
> v1-v2:
> 
>   - Split bpf vm part out of kernel/bpf/core.c and link to it instead
>     of using ubpf library(Suggested by Alexei Starovoitov). And add
>     runtime bounds check just like ubpf library does.

hmm. I don't think I suggested to hack bpf/core.c into separate file
and compile it for userspace...
Also I think the prior experience taught us that sharing code between
kernel and user space will have lots of headaches long term.
I think it makes more sense to use bcc approach. Just have c+py
or c+lua or c+c. llvm has x86 backend too. If you integrate
clang/llvm (bcc approach) you can compile different functions with
different backends... if you don't want to embed the compiler,
have two .c files. Compile one for bpf target and another for native.

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

* Re: [RFC PATCH v2 05/26] tools include: Sync math64.h and div64.h
  2016-06-26 11:20 ` [RFC PATCH v2 05/26] tools include: Sync math64.h and div64.h He Kuang
@ 2016-06-26 21:08   ` Nilay Vaish
  2016-06-27  2:21     ` Hekuang
  0 siblings, 1 reply; 38+ messages in thread
From: Nilay Vaish @ 2016-06-26 21:08 UTC (permalink / raw)
  To: He Kuang
  Cc: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, Linux Kernel list

On 26 June 2016 at 06:20, He Kuang <hekuang@huawei.com> wrote:
> From: Wang Nan <wangnan0@huawei.com>
>
> This patch copies "include/linux/math64.h" into
> "tools/include/linux/math64.h" and copies
> "include/asm-generic/div64.h" into
> "tools/include/asm-generic/div64.h", to enable other libraries use
> arithmetic operation defined in them.

This probably is a newbie question.  What prevents us from using the
header files directly?

--
Nilay

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

* Re: [RFC PATCH v2 00/26] perf tools: Support uBPF script
  2016-06-26 20:48 ` [RFC PATCH v2 00/26] perf tools: Support uBPF script Alexei Starovoitov
@ 2016-06-27  2:10   ` Hekuang
  2016-06-28 11:47   ` Hekuang
  1 sibling, 0 replies; 38+ messages in thread
From: Hekuang @ 2016-06-27  2:10 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, linux-kernel

hi

在 2016/6/27 4:48, Alexei Starovoitov 写道:
> On Sun, Jun 26, 2016 at 11:20:52AM +0000, He Kuang wrote:
>> This patchset is based on Wang Nan's v1:
>>       http://thread.gmane.org/gmane.linux.kernel/2203717/focus=2203707
>>
>> """
>>    This patch set allows to perf invoke some user space BPF scripts on
>>    some point. uBPF scripts and kernel BPF scripts reside in one BPF
>>    object.  They communicate with each other with BPF maps. uBPF
>>    scripts can invoke helper functions provided by perf.
>>    
>>    At least following new features can be achieved based on uBPF
>>    support:
>>    
>>     1) Report statistical result:
>>
>>        Like DTrace, perf print statistical report before quit. No need
>>        to extract data using 'perf report'. Statistical method is
>>        controled by user.
>>    
>>     2) Control perf's behavior:
>>
>>        Dynamically adjust period of different events. Policy is defined
>>        by user.
>> """
>>
>> and modified by following the reviewers' suggestions.
>>
>> v1-v2:
>>
>>    - Split bpf vm part out of kernel/bpf/core.c and link to it instead
>>      of using ubpf library(Suggested by Alexei Starovoitov). And add
>>      runtime bounds check just like ubpf library does.
> hmm. I don't think I suggested to hack bpf/core.c into separate file
> and compile it for userspace...
"""

Also ubpf was written from scratch with apache2, while perf is gpl,
so you can just link kernel/bpf/core.o directly instead of using external
libraries.
"""
This is your comment on ubpf v1 thread.

I thought you was suggesting to use code in kernel/bpf/core.o,
but because there're difference in __bpf_prog_run() between userspace
and kernel, for example the __bpf_call_base is used in kernel,
in userspace we get funcs from ubpf function list, we have to modify
the existing code in kernel/bpf/core.c.

I've got the source code of 'bcc' project, but it seems that bcc does not
involve bpf virtual machine, so if we do not use 'kernel/bpf/core.o' solution,
and can't use 'ubpf' because of the license reason, any other choices?

Thank you.

> Also I think the prior experience taught us that sharing code between
> kernel and user space will have lots of headaches long term.
> I think it makes more sense to use bcc approach. Just have c+py
> or c+lua or c+c. llvm has x86 backend too. If you integrate
> clang/llvm (bcc approach) you can compile different functions with
> different backends... if you don't want to embed the compiler,
> have two .c files. Compile one for bpf target and another for native.
>
>

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

* Re: [RFC PATCH v2 05/26] tools include: Sync math64.h and div64.h
  2016-06-26 21:08   ` Nilay Vaish
@ 2016-06-27  2:21     ` Hekuang
  2016-06-27 18:13       ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 38+ messages in thread
From: Hekuang @ 2016-06-27  2:21 UTC (permalink / raw)
  To: Nilay Vaish
  Cc: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, Linux Kernel list

hi

在 2016/6/27 5:08, Nilay Vaish 写道:
> On 26 June 2016 at 06:20, He Kuang <hekuang@huawei.com> wrote:
>> From: Wang Nan <wangnan0@huawei.com>
>>
>> This patch copies "include/linux/math64.h" into
>> "tools/include/linux/math64.h" and copies
>> "include/asm-generic/div64.h" into
>> "tools/include/asm-generic/div64.h", to enable other libraries use
>> arithmetic operation defined in them.
> This probably is a newbie question.  What prevents us from using the
> header files directly?
>
> --
> Nilay

For not being influenced by kernel headers update too much, perf adopts
the header files in its own folder.

Thank you.
>

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

* Re: [RFC PATCH v2 05/26] tools include: Sync math64.h and div64.h
  2016-06-27  2:21     ` Hekuang
@ 2016-06-27 18:13       ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 38+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-06-27 18:13 UTC (permalink / raw)
  To: Hekuang
  Cc: Nilay Vaish, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, Linux Kernel list

Em Mon, Jun 27, 2016 at 10:21:10AM +0800, Hekuang escreveu:
> 在 2016/6/27 5:08, Nilay Vaish 写道:
> > On 26 June 2016 at 06:20, He Kuang <hekuang@huawei.com> wrote:
> > > From: Wang Nan <wangnan0@huawei.com>
> > > This patch copies "include/linux/math64.h" into
> > > "tools/include/linux/math64.h" and copies
> > > "include/asm-generic/div64.h" into
> > > "tools/include/asm-generic/div64.h", to enable other libraries use
> > > arithmetic operation defined in them.
> > This probably is a newbie question.  What prevents us from using the
> > header files directly?
 
> For not being influenced by kernel headers update too much, perf adopts
> the header files in its own folder.

yeah, we used to include them directly, but then, changes in the kernel
sometimes broke the tools/ build, so we instead copy it and check for
changes using diff as part of the build process, flagging changes, like
the one I'm investigating now:

[acme@jouet linux]$ diff -u tools/perf/arch/x86/entry/syscalls/syscall_64.tbl arch/x86/entry/syscalls/syscall_64.tbl 
--- tools/perf/arch/x86/entry/syscalls/syscall_64.tbl	2016-06-06 11:06:31.423335774 -0300
+++ arch/x86/entry/syscalls/syscall_64.tbl	2016-06-06 11:06:30.511345336 -0300
@@ -374,3 +374,5 @@
 543	x32	io_setup		compat_sys_io_setup
 544	x32	io_submit		compat_sys_io_submit
 545	x32	execveat		compat_sys_execveat/ptregs
+534	x32	preadv2			compat_sys_preadv2
+535	x32	pwritev2		compat_sys_pwritev2
[acme@jouet linux]$

Flagged in the build process:

<SNIP>
...                     get_cpuid: [ on  ]
...                           bpf: [ on  ]

  GEN      /tmp/build/perf/common-cmds.h
Warning: x86_64's syscall_64.tbl differs from kernel
  CC       /tmp/build/perf/fixdep.o
  LD       /tmp/build/perf/fixdep-in
<SNIP>

- Arnaldo

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

* Re: [RFC PATCH v2 00/26] perf tools: Support uBPF script
  2016-06-26 20:48 ` [RFC PATCH v2 00/26] perf tools: Support uBPF script Alexei Starovoitov
  2016-06-27  2:10   ` Hekuang
@ 2016-06-28 11:47   ` Hekuang
  2016-06-28 14:57     ` Alexei Starovoitov
  1 sibling, 1 reply; 38+ messages in thread
From: Hekuang @ 2016-06-28 11:47 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, linux-kernel



在 2016/6/27 4:48, Alexei Starovoitov 写道:
> On Sun, Jun 26, 2016 at 11:20:52AM +0000, He Kuang wrote:
>>   bounds check just like ubpf library does.
> hmm. I don't think I suggested to hack bpf/core.c into separate file
> and compile it for userspace...

Maybe I misunderstood your suggestion. Now I just let perf check 
bpf/core.o in
kernel output directory, if it exsits, perf will link it. The missing 
functions referenced by
bpf/core.o can be defined empty in perf.

The above way leaves two minor changes in bpf/core.c:

diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index b94a365..0fc6c23 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -452,7 +452,7 @@ struct bpf_prog *bpf_jit_blind_constants(struct 
bpf_prog *prog)
   * therefore keeping it non-static as well; will also be used by JITs
   * anyway later on, so do not let the compiler omit it.
   */
-noinline u64 __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
+noinline u64 __weak __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
  {
         return 0;
  }
@@ -465,7 +465,7 @@ EXPORT_SYMBOL_GPL(__bpf_call_base);
   *
   * Decode and execute eBPF instructions.
   */
-static unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn)
+unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn)
  {
         u64 stack[MAX_BPF_STACK / sizeof(u64)];
         u64 regs[MAX_BPF_REG], tmp;

How about this?

Thank you.

> Also I think the prior experience taught us that sharing code between
> kernel and user space will have lots of headaches long term.
> I think it makes more sense to use bcc approach. Just have c+py
> or c+lua or c+c. llvm has x86 backend too. If you integrate
> clang/llvm (bcc approach) you can compile different functions with
> different backends... if you don't want to embed the compiler,
> have two .c files. Compile one for bpf target and another for native.
>
>

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

* Re: [RFC PATCH v2 00/26] perf tools: Support uBPF script
  2016-06-28 11:47   ` Hekuang
@ 2016-06-28 14:57     ` Alexei Starovoitov
  2016-06-29 10:15       ` Hekuang
  0 siblings, 1 reply; 38+ messages in thread
From: Alexei Starovoitov @ 2016-06-28 14:57 UTC (permalink / raw)
  To: Hekuang
  Cc: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, linux-kernel

On Tue, Jun 28, 2016 at 07:47:53PM +0800, Hekuang wrote:
> 
> 
> 在 2016/6/27 4:48, Alexei Starovoitov 写道:
> >On Sun, Jun 26, 2016 at 11:20:52AM +0000, He Kuang wrote:
> >>  bounds check just like ubpf library does.
> >hmm. I don't think I suggested to hack bpf/core.c into separate file
> >and compile it for userspace...
> 
> Maybe I misunderstood your suggestion. Now I just let perf check bpf/core.o
> in
> kernel output directory, if it exsits, perf will link it. The missing
> functions referenced by
> bpf/core.o can be defined empty in perf.

yes. that's what I meant.
Note that this is still soft dependency on kernel, so things will break
eventually.

> The above way leaves two minor changes in bpf/core.c:
> 
> diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
> index b94a365..0fc6c23 100644
> --- a/kernel/bpf/core.c
> +++ b/kernel/bpf/core.c
> @@ -452,7 +452,7 @@ struct bpf_prog *bpf_jit_blind_constants(struct bpf_prog
> *prog)
>   * therefore keeping it non-static as well; will also be used by JITs
>   * anyway later on, so do not let the compiler omit it.
>   */
> -noinline u64 __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
> +noinline u64 __weak __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)

this part I don't understand. Why do you need to change it?

>  {
>         return 0;
>  }
> @@ -465,7 +465,7 @@ EXPORT_SYMBOL_GPL(__bpf_call_base);
>   *
>   * Decode and execute eBPF instructions.
>   */
> -static unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn)
> +unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn)

yes. that is good.

> >Also I think the prior experience taught us that sharing code between
> >kernel and user space will have lots of headaches long term.
> >I think it makes more sense to use bcc approach. Just have c+py
> >or c+lua or c+c. llvm has x86 backend too. If you integrate
> >clang/llvm (bcc approach) you can compile different functions with
> >different backends... if you don't want to embed the compiler,
> >have two .c files. Compile one for bpf target and another for native.

I still think that what two .c files without embeded llvm or
one .c with embedded is a better way.
You'll have full C that is fast on x86 or arm instead of
executing things in ubpf.
Or use py/lua wrappers. Equally easy.

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

* Re: [RFC PATCH v2 00/26] perf tools: Support uBPF script
  2016-06-28 14:57     ` Alexei Starovoitov
@ 2016-06-29 10:15       ` Hekuang
  2016-06-29 10:35         ` Wangnan (F)
  0 siblings, 1 reply; 38+ messages in thread
From: Hekuang @ 2016-06-29 10:15 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, wangnan0, linux-kernel, pi3orama

hi

在 2016/6/28 22:57, Alexei Starovoitov 写道:
>
>          return 0;
>   }
> @@ -465,7 +465,7 @@ EXPORT_SYMBOL_GPL(__bpf_call_base);
>    *
>    * Decode and execute eBPF instructions.
>    */
> -static unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn)
> +unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn)
> yes. that is good.
>
>>> Also I think the prior experience taught us that sharing code between
>>> kernel and user space will have lots of headaches long term.
>>> I think it makes more sense to use bcc approach. Just have c+py
>>> or c+lua or c+c. llvm has x86 backend too. If you integrate
>>> clang/llvm (bcc approach) you can compile different functions with
>>> different backends... if you don't want to embed the compiler,
>>> have two .c files. Compile one for bpf target and another for native.
> I still think that what two .c files without embeded llvm or
> one .c with embedded is a better way.
> You'll have full C that is fast on x86 or arm instead of
> executing things in ubpf.
> Or use py/lua wrappers. Equally easy.
>
Our goal is the same as you described, that to have one .c file
and embeded llvm into perf for compiling it to bpf target for
kernel and native for userspace.

But there's two problems we may encounter by this way on the
phone, which is the most common scenario our work focus on.

The first one is the size of bcc/llvm library. It's more than
800MB for libbcc.so and I guess the llvm part takes most of
them. Shortly we can run perf as a daemon after the
overwrite/control channel be merged (wangnan's recently patches),
such a huge memory consumption is not acceptable.

Second, I've browsed the bcc source briefly and see that there's
two frontend for loading .b and .c, we have to integrate the x86
backend for compiling bpf to native code. That's possible but we
still need extra works and it is not ready to use for now.

Then we have two other approaches, the first is as 'ubpf v2'
which uses one .c file and introduces bpf vm to perf, the second
is like you said, use two .c files and compile userspace bpf to
native code by using llvm externally.

Both the two ways are easy to implement, but we prefer the first
one between them because it uses one .c file which is the same as
our final approach, and it does not face the huge memory
consumption problem, finally, after we solve problems on embeded
llvm in perf and lower the memory consumption, we can keep the
user interface and replace the bpf vm to llvm
frontend+backend.

So what's your opinion on this?

Thank you.

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

* Re: [RFC PATCH v2 00/26] perf tools: Support uBPF script
  2016-06-29 10:15       ` Hekuang
@ 2016-06-29 10:35         ` Wangnan (F)
  2016-06-29 12:37           ` Alexei Starovoitov
  0 siblings, 1 reply; 38+ messages in thread
From: Wangnan (F) @ 2016-06-29 10:35 UTC (permalink / raw)
  To: Hekuang, Alexei Starovoitov
  Cc: acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, linux-kernel, pi3orama



On 2016/6/29 18:15, Hekuang wrote:
> hi
>
> 在 2016/6/28 22:57, Alexei Starovoitov 写道:
>>
>>          return 0;
>>   }
>> @@ -465,7 +465,7 @@ EXPORT_SYMBOL_GPL(__bpf_call_base);
>>    *
>>    * Decode and execute eBPF instructions.
>>    */
>> -static unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn 
>> *insn)
>> +unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn)
>> yes. that is good.
>>
>>>> Also I think the prior experience taught us that sharing code between
>>>> kernel and user space will have lots of headaches long term.
>>>> I think it makes more sense to use bcc approach. Just have c+py
>>>> or c+lua or c+c. llvm has x86 backend too. If you integrate
>>>> clang/llvm (bcc approach) you can compile different functions with
>>>> different backends... if you don't want to embed the compiler,
>>>> have two .c files. Compile one for bpf target and another for native.
>> I still think that what two .c files without embeded llvm or
>> one .c with embedded is a better way.
>> You'll have full C that is fast on x86 or arm instead of
>> executing things in ubpf.
>> Or use py/lua wrappers. Equally easy.
>>
> Our goal is the same as you described, that to have one .c file
> and embeded llvm into perf for compiling it to bpf target for
> kernel and native for userspace.
>
> But there's two problems we may encounter by this way on the
> phone, which is the most common scenario our work focus on.
>
> The first one is the size of bcc/llvm library. It's more than
> 800MB for libbcc.so and I guess the llvm part takes most of
> them. Shortly we can run perf as a daemon after the
> overwrite/control channel be merged (wangnan's recently patches),
> such a huge memory consumption is not acceptable.
>
> Second, I've browsed the bcc source briefly and see that there's
> two frontend for loading .b and .c, we have to integrate the x86
> backend for compiling bpf to native code. That's possible but we
> still need extra works and it is not ready to use for now.
>
> Then we have two other approaches, the first is as 'ubpf v2'
> which uses one .c file and introduces bpf vm to perf, the second
> is like you said, use two .c files and compile userspace bpf to
> native code by using llvm externally.
>

Not userspace BPF. There would no userspace BPF if we choose two
.c approach. We can compile user space part to a shared library,
then make perf load it like a perf plugin. We can even glue BPF.o
and native.o into one file with linker trick, then let's push it
into smart phone use adb push... Oh, no, not only perf and the
two (or one) objects. a dynamic perf requires more than 30
libraries, we need to push them too.

> Both the two ways are easy to implement, but we prefer the first
> one between them because it uses one .c file which is the same as
> our final approach, and it does not face the huge memory
> consumption problem, finally, after we solve problems on embeded
> llvm in perf and lower the memory consumption, we can keep the
> user interface and replace the bpf vm to llvm
> frontend+backend.
>

Yes. The problem we consider now is interface. Before we can use
llvm library on smartphone, shall we maintain a '.o + .so' interface
separatly?

> So what's your opinion on this?
>
> Thank you.
>

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

* Re: [RFC PATCH v2 00/26] perf tools: Support uBPF script
  2016-06-29 10:35         ` Wangnan (F)
@ 2016-06-29 12:37           ` Alexei Starovoitov
  2016-06-29 13:03             ` pi3orama
  0 siblings, 1 reply; 38+ messages in thread
From: Alexei Starovoitov @ 2016-06-29 12:37 UTC (permalink / raw)
  To: Wangnan (F)
  Cc: Hekuang, acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, linux-kernel, pi3orama

On Wed, Jun 29, 2016 at 06:35:12PM +0800, Wangnan (F) wrote:
> 
> 
> On 2016/6/29 18:15, Hekuang wrote:
> >hi
> >
> >在 2016/6/28 22:57, Alexei Starovoitov 写道:
> >>
> >>         return 0;
> >>  }
> >>@@ -465,7 +465,7 @@ EXPORT_SYMBOL_GPL(__bpf_call_base);
> >>   *
> >>   * Decode and execute eBPF instructions.
> >>   */
> >>-static unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn
> >>*insn)
> >>+unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn)
> >>yes. that is good.
> >>
> >>>>Also I think the prior experience taught us that sharing code between
> >>>>kernel and user space will have lots of headaches long term.
> >>>>I think it makes more sense to use bcc approach. Just have c+py
> >>>>or c+lua or c+c. llvm has x86 backend too. If you integrate
> >>>>clang/llvm (bcc approach) you can compile different functions with
> >>>>different backends... if you don't want to embed the compiler,
> >>>>have two .c files. Compile one for bpf target and another for native.
> >>I still think that what two .c files without embeded llvm or
> >>one .c with embedded is a better way.
> >>You'll have full C that is fast on x86 or arm instead of
> >>executing things in ubpf.
> >>Or use py/lua wrappers. Equally easy.
> >>
> >Our goal is the same as you described, that to have one .c file
> >and embeded llvm into perf for compiling it to bpf target for
> >kernel and native for userspace.
> >
> >But there's two problems we may encounter by this way on the
> >phone, which is the most common scenario our work focus on.
> >
> >The first one is the size of bcc/llvm library. It's more than
> >800MB for libbcc.so and I guess the llvm part takes most of
> >them. Shortly we can run perf as a daemon after the
> >overwrite/control channel be merged (wangnan's recently patches),
> >such a huge memory consumption is not acceptable.

you'll see ~1Gb .so when llvm is compiled with debug info.

$ ls -lh libbcc.so.0.1.8
38M Jun 29 07:40 libbcc.so.0.1.8

and that includes full clang, llvm and two bcc front-ends.
llvm alone is 14M
that is perfectly acceptable even for a phone.

> >
> >Second, I've browsed the bcc source briefly and see that there's
> >two frontend for loading .b and .c, we have to integrate the x86
> >backend for compiling bpf to native code. That's possible but we
> >still need extra works and it is not ready to use for now.
> >
> >Then we have two other approaches, the first is as 'ubpf v2'
> >which uses one .c file and introduces bpf vm to perf, the second
> >is like you said, use two .c files and compile userspace bpf to
> >native code by using llvm externally.
> >
> 
> Not userspace BPF. There would no userspace BPF if we choose two
> .c approach. We can compile user space part to a shared library,
> then make perf load it like a perf plugin. We can even glue BPF.o
> and native.o into one file with linker trick, then let's push it
> into smart phone use adb push... Oh, no, not only perf and the
> two (or one) objects. a dynamic perf requires more than 30
> libraries, we need to push them too.

that's a way as well, but I don't see why you need to combine two .o
loading bpf.o and native.o independently is easier, no?

> >Both the two ways are easy to implement, but we prefer the first
> >one between them because it uses one .c file which is the same as
> >our final approach, and it does not face the huge memory
> >consumption problem, finally, after we solve problems on embeded
> >llvm in perf and lower the memory consumption, we can keep the
> >user interface and replace the bpf vm to llvm
> >frontend+backend.
> >
> 
> Yes. The problem we consider now is interface. Before we can use
> llvm library on smartphone, shall we maintain a '.o + .so' interface
> separatly?

what's stopping using llvm on a phone now?

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

* Re: [RFC PATCH v2 00/26] perf tools: Support uBPF script
  2016-06-29 12:37           ` Alexei Starovoitov
@ 2016-06-29 13:03             ` pi3orama
  0 siblings, 0 replies; 38+ messages in thread
From: pi3orama @ 2016-06-29 13:03 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Wangnan (F),
	Hekuang, acme, peterz, mingo, jolsa, brendan.d.gregg, ast,
	alexander.shishkin, linux-kernel



发自我的 iPhone

> 在 2016年6月29日,下午8:37,Alexei Starovoitov <alexei.starovoitov@gmail.com> 写道:
> 
>> On Wed, Jun 29, 2016 at 06:35:12PM +0800, Wangnan (F) wrote:
>> 
>> 
>>> On 2016/6/29 18:15, Hekuang wrote:
>>> hi
>>> 
>>>> 在 2016/6/28 22:57, Alexei Starovoitov 写道:
>>>> 
>>>>        return 0;
>>>> }
>>>> @@ -465,7 +465,7 @@ EXPORT_SYMBOL_GPL(__bpf_call_base);
>>>>  *
>>>>  * Decode and execute eBPF instructions.
>>>>  */
>>>> -static unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn
>>>> *insn)
>>>> +unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn)
>>>> yes. that is good.
>>>> 
>>>>>> Also I think the prior experience taught us that sharing code between
>>>>>> kernel and user space will have lots of headaches long term.
>>>>>> I think it makes more sense to use bcc approach. Just have c+py
>>>>>> or c+lua or c+c. llvm has x86 backend too. If you integrate
>>>>>> clang/llvm (bcc approach) you can compile different functions with
>>>>>> different backends... if you don't want to embed the compiler,
>>>>>> have two .c files. Compile one for bpf target and another for native.
>>>> I still think that what two .c files without embeded llvm or
>>>> one .c with embedded is a better way.
>>>> You'll have full C that is fast on x86 or arm instead of
>>>> executing things in ubpf.
>>>> Or use py/lua wrappers. Equally easy.
>>> Our goal is the same as you described, that to have one .c file
>>> and embeded llvm into perf for compiling it to bpf target for
>>> kernel and native for userspace.
>>> 
>>> But there's two problems we may encounter by this way on the
>>> phone, which is the most common scenario our work focus on.
>>> 
>>> The first one is the size of bcc/llvm library. It's more than
>>> 800MB for libbcc.so and I guess the llvm part takes most of
>>> them. Shortly we can run perf as a daemon after the
>>> overwrite/control channel be merged (wangnan's recently patches),
>>> such a huge memory consumption is not acceptable.
> 
> you'll see ~1Gb .so when llvm is compiled with debug info.
> 
> $ ls -lh libbcc.so.0.1.8
> 38M Jun 29 07:40 libbcc.so.0.1.8
> 
> and that includes full clang, llvm and two bcc front-ends.
> llvm alone is 14M
> that is perfectly acceptable even for a phone.
> 
>>> 
>>> Second, I've browsed the bcc source briefly and see that there's
>>> two frontend for loading .b and .c, we have to integrate the x86
>>> backend for compiling bpf to native code. That's possible but we
>>> still need extra works and it is not ready to use for now.
>>> 
>>> Then we have two other approaches, the first is as 'ubpf v2'
>>> which uses one .c file and introduces bpf vm to perf, the second
>>> is like you said, use two .c files and compile userspace bpf to
>>> native code by using llvm externally.
>> 
>> Not userspace BPF. There would no userspace BPF if we choose two
>> .c approach. We can compile user space part to a shared library,
>> then make perf load it like a perf plugin. We can even glue BPF.o
>> and native.o into one file with linker trick, then let's push it
>> into smart phone use adb push... Oh, no, not only perf and the
>> two (or one) objects. a dynamic perf requires more than 30
>> libraries, we need to push them too.
> 
> that's a way as well, but I don't see why you need to combine two .o
> loading bpf.o and native.o independently is easier, no?
> 
>>> Both the two ways are easy to implement, but we prefer the first
>>> one between them because it uses one .c file which is the same as
>>> our final approach, and it does not face the huge memory
>>> consumption problem, finally, after we solve problems on embeded
>>> llvm in perf and lower the memory consumption, we can keep the
>>> user interface and replace the bpf vm to llvm
>>> frontend+backend.
>> 
>> Yes. The problem we consider now is interface. Before we can use
>> llvm library on smartphone, shall we maintain a '.o + .so' interface
>> separatly?
> 
> what's stopping using llvm on a phone now?

Size is the only consideration now. If we can
shrink LLVM library to less than 20MB then
embedding libLLVM is really worth a try.

We'll try to compile to arm64 tomorrow.
I have seen some discussions on it so I think
it would not be very hard.

Thank you for your information!

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

end of thread, other threads:[~2016-06-29 13:04 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-26 11:20 [RFC PATCH v2 00/26] perf tools: Support uBPF script He Kuang
2016-06-26 11:20 ` [RFC PATCH v2 01/26] tools include: Adopt byte ordering macros from byteorder/generic.h He Kuang
2016-06-26 11:20 ` [RFC PATCH v2 02/26] tools include: Fix wrong macro definitions for cpu_to_le* for big endian He Kuang
2016-06-26 11:20 ` [RFC PATCH v2 03/26] bpf: split __bpf_prog_run code into new file He Kuang
2016-06-26 11:20 ` [RFC PATCH v2 04/26] bpf: extract jmp and default handler and introduce UBPF_BUILD flag He Kuang
2016-06-26 11:20 ` [RFC PATCH v2 05/26] tools include: Sync math64.h and div64.h He Kuang
2016-06-26 21:08   ` Nilay Vaish
2016-06-27  2:21     ` Hekuang
2016-06-27 18:13       ` Arnaldo Carvalho de Melo
2016-06-26 11:20 ` [RFC PATCH v2 06/26] tools include: Add (atomic|atomic64)_add implementation from the kernel sources He Kuang
2016-06-26 11:20 ` [RFC PATCH v2 07/26] perf bpf: Add map related BPF helper He Kuang
2016-06-26 11:21 ` [RFC PATCH v2 08/26] perf bpf: Add UBPF flags and makefile options He Kuang
2016-06-26 11:21 ` [RFC PATCH v2 09/26] perf bpf: Implement empty instruction handler and build bpf-vm He Kuang
2016-06-26 11:21 ` [RFC PATCH v2 10/26] perf bpf: Remove unused code in libbpf He Kuang
2016-06-26 11:21 ` [RFC PATCH v2 11/26] perf bpf: Store arbitrary entries instread fd array in bpf_program He Kuang
2016-06-26 11:21 ` [RFC PATCH v2 12/26] perf bpf: Add libbpf-internal.h header file He Kuang
2016-06-26 11:21 ` [RFC PATCH v2 13/26] perf bpf: Add abstraction for bpf program methods He Kuang
2016-06-26 11:21 ` [RFC PATCH v2 14/26] perf bpf: Add -Wextra to cflags for more warnings and fix them He Kuang
2016-06-26 11:21 ` [RFC PATCH v2 15/26] perf bpf: Introduce the entity and engine for userspace bpf He Kuang
2016-06-26 11:21 ` [RFC PATCH v2 16/26] perf bpf: Add method for fetching nth ubpf vm He Kuang
2016-06-26 11:21 ` [RFC PATCH v2 17/26] perf bpf: Add methods to set/check ubpf engine for bpf programs He Kuang
2016-06-26 11:21 ` [RFC PATCH v2 18/26] perf bpf: Add ubpf helper function slots and set/get methods He Kuang
2016-06-26 11:21 ` [RFC PATCH v2 19/26] perf tools: Register basic uBPF helpers He Kuang
2016-06-26 11:21 ` [RFC PATCH v2 20/26] perf bpf: Accept uBPF programs He Kuang
2016-06-26 11:21 ` [RFC PATCH v2 21/26] bpf: Support bpf load/store boundary check for ubpf He Kuang
2016-06-26 11:21 ` [RFC PATCH v2 22/26] perf bpf: Implement boundary check code in ubpf He Kuang
2016-06-26 11:21 ` [RFC PATCH v2 23/26] perf record: Add uBPF hooks at beginning and end of perf record He Kuang
2016-06-26 11:21 ` [RFC PATCH v2 24/26] perf bpf: Fillup bpf jmp_call handler He Kuang
2016-06-26 11:21 ` [RFC PATCH v2 25/26] perf bpf: Implement run_ubpf_program He Kuang
2016-06-26 11:21 ` [RFC PATCH v2 26/26] perf tests: Add uBPF test case He Kuang
2016-06-26 20:48 ` [RFC PATCH v2 00/26] perf tools: Support uBPF script Alexei Starovoitov
2016-06-27  2:10   ` Hekuang
2016-06-28 11:47   ` Hekuang
2016-06-28 14:57     ` Alexei Starovoitov
2016-06-29 10:15       ` Hekuang
2016-06-29 10:35         ` Wangnan (F)
2016-06-29 12:37           ` Alexei Starovoitov
2016-06-29 13:03             ` pi3orama

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).