Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751442AbbEXIaJ (ORCPT ); Sun, 24 May 2015 04:30:09 -0400 Received: from szxga01-in.huawei.com ([58.251.152.64]:1555 "EHLO szxga01-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750915AbbEXI2h (ORCPT ); Sun, 24 May 2015 04:28:37 -0400 From: He Kuang To: , , , , , , , , , , , CC: , Subject: [RFC PATCH v2 07/15] bpf tools: Convert arglist to bpf prologue Date: Sun, 24 May 2015 08:28:03 +0000 Message-ID: <1432456091-73384-8-git-send-email-hekuang@huawei.com> X-Mailer: git-send-email 1.8.3.4 In-Reply-To: <1432456091-73384-1-git-send-email-hekuang@huawei.com> References: <1432456091-73384-1-git-send-email-hekuang@huawei.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.107.197.210] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4542 Lines: 171 When all arguments in bpf config section are collected in register and offset form, this patch will fetch them from bpf context register and place them as bpf input parameters. By bpf calling convention, we restrict the max fetched arg number to 4. Bpf prologue is generated as the following steps: 1. alloc dst address in stack -> r1 2. set size -> r2 3. fetch base register and offset -> r3 4. call BPF_FUNC_probe_read 5. loop 1 6. save intermediate result and process next arg 7. restore intermediate result to arg2~5 Signed-off-by: He Kuang --- tools/lib/bpf/Build | 2 +- tools/lib/bpf/gen_prologue.c | 108 +++++++++++++++++++++++++++++++++++++++++++ tools/lib/bpf/libbpf.h | 10 ++++ 3 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 tools/lib/bpf/gen_prologue.c diff --git a/tools/lib/bpf/Build b/tools/lib/bpf/Build index d874975..c910805 100644 --- a/tools/lib/bpf/Build +++ b/tools/lib/bpf/Build @@ -1 +1 @@ -libbpf-y := libbpf.o bpf.o +libbpf-y := libbpf.o bpf.o gen_prologue.o diff --git a/tools/lib/bpf/gen_prologue.c b/tools/lib/bpf/gen_prologue.c new file mode 100644 index 0000000..ca8aa1c --- /dev/null +++ b/tools/lib/bpf/gen_prologue.c @@ -0,0 +1,108 @@ +#include +#include +#include +#include +#include +#include + +#include "libbpf.h" +#include "bpf.h" + +#define BPF_REG_SIZE (8) + +unsigned int bpf_prologue_arg_deref(int offset, int stack_index, int depth, + char *new_prog, bool last) +{ + struct bpf_insn tmp_insns[6] = {}; + struct bpf_insn *insn = tmp_insns; + unsigned int size; + + if (!depth) { + /* base register */ + if (offset < 0) + return 0; + + /* load ctx to r3 */ + *insn++ = BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_CTX, offset); + + if (!last) { + /* r7 for stack space */ + *insn++ = BPF_MOV64_REG(BPF_REG_7, BPF_REG_FP); + *insn++ = BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, + -BPF_REG_SIZE * stack_index); + /* clear stack */ + *insn++ = BPF_STX_MEM(BPF_DW, BPF_REG_FP, BPF_REG_8, + -BPF_REG_SIZE * stack_index); + } else { + /* store r3 to stack */ + *insn++ = BPF_STX_MEM(BPF_DW, BPF_REG_FP, BPF_REG_3, + -BPF_REG_SIZE * stack_index); + } + } else { + /* refs */ + /* r3 += offset */ + *insn++ = BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, offset); + + /* r2 = size */ + *insn++ = BPF_ALU64_IMM(BPF_MOV, BPF_REG_2, 0x0008); + + /* r1 = r7 */ + *insn++ = BPF_MOV64_REG(BPF_REG_1, BPF_REG_7); + + /* call BPF_FUNC_probe_read + * r1: ptr to stack + * r2: stack size + * r3: unsafe ptr + */ + *insn++ = BPF_EMIT_CALL(BPF_FUNC_probe_read); + + if (!last) + /* fetch stack intermediate to r3 */ + *insn++ = BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_FP, + -BPF_REG_SIZE * stack_index); + } + + size = sizeof(*insn) * (insn - tmp_insns); + if (new_prog) + memcpy(new_prog, tmp_insns, size); + + return size; +} + +unsigned int bpf_prologue_begin(char *new_prog) +{ + struct bpf_insn *new_insn; + + new_insn = (struct bpf_insn *)new_prog; + + if (new_insn) { + /* save arg1 to ctx */ + *new_insn++ = BPF_MOV64_REG(BPF_REG_CTX, BPF_REG_ARG1); + /* set r8 to 0 */ + *new_insn++ = BPF_ALU64_IMM(BPF_MOV, BPF_REG_8, 0); + } else + new_insn += 2; + + return (char *)new_insn - new_prog; +} + +unsigned int bpf_prologue_end(char *new_prog, int nargs) +{ + struct bpf_insn *new_insn; + int i; + + new_insn = (struct bpf_insn *)new_prog; + + nargs = min(BPF_PROLOGUE_NRARGS_MAX, nargs); + for (i = 0; i < nargs; i++) { + /* result in stack, move to r2~r5 */ + if (new_prog) + *new_insn = BPF_LDX_MEM(BPF_DW, + BPF_REG_ARG2 + i, + BPF_REG_FP, + -BPF_REG_SIZE * (i + 1)); + new_insn++; + } + + return (char *)new_insn - new_prog; +} diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index 31ff5d9..cf22a6a 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -63,4 +63,14 @@ struct bpf_map_def { unsigned int max_entries; }; +#define BPF_PROLOGUE_NRARGS_MAX (4) + +unsigned int bpf_prologue_begin(char *new_prog); +unsigned int bpf_prologue_end(char *new_prog, int nargs); +unsigned int bpf_prologue_arg_deref(int offset, + int stack_index, + int depth, + char *new_prog, + bool last); + #endif -- 1.8.5.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/