diff options
Diffstat (limited to 'tools/lib/bpf/gen_loader.c')
| -rw-r--r-- | tools/lib/bpf/gen_loader.c | 47 | 
1 files changed, 30 insertions, 17 deletions
diff --git a/tools/lib/bpf/gen_loader.c b/tools/lib/bpf/gen_loader.c index 502dea53a742..9934851ccde7 100644 --- a/tools/lib/bpf/gen_loader.c +++ b/tools/lib/bpf/gen_loader.c @@ -18,7 +18,7 @@  #define MAX_USED_MAPS	64  #define MAX_USED_PROGS	32  #define MAX_KFUNC_DESCS 256 -#define MAX_FD_ARRAY_SZ (MAX_USED_PROGS + MAX_KFUNC_DESCS) +#define MAX_FD_ARRAY_SZ (MAX_USED_MAPS + MAX_KFUNC_DESCS)  /* The following structure describes the stack layout of the loader program.   * In addition R6 contains the pointer to context. @@ -33,8 +33,8 @@   */  struct loader_stack {  	__u32 btf_fd; -	__u32 prog_fd[MAX_USED_PROGS];  	__u32 inner_map_fd; +	__u32 prog_fd[MAX_USED_PROGS];  };  #define stack_off(field) \ @@ -42,6 +42,11 @@ struct loader_stack {  #define attr_field(attr, field) (attr + offsetof(union bpf_attr, field)) +static int blob_fd_array_off(struct bpf_gen *gen, int index) +{ +	return gen->fd_array + index * sizeof(int); +} +  static int realloc_insn_buf(struct bpf_gen *gen, __u32 size)  {  	size_t off = gen->insn_cur - gen->insn_start; @@ -102,11 +107,15 @@ static void emit2(struct bpf_gen *gen, struct bpf_insn insn1, struct bpf_insn in  	emit(gen, insn2);  } -void bpf_gen__init(struct bpf_gen *gen, int log_level) +static int add_data(struct bpf_gen *gen, const void *data, __u32 size); +static void emit_sys_close_blob(struct bpf_gen *gen, int blob_off); + +void bpf_gen__init(struct bpf_gen *gen, int log_level, int nr_progs, int nr_maps)  { -	size_t stack_sz = sizeof(struct loader_stack); +	size_t stack_sz = sizeof(struct loader_stack), nr_progs_sz;  	int i; +	gen->fd_array = add_data(gen, NULL, MAX_FD_ARRAY_SZ * sizeof(int));  	gen->log_level = log_level;  	/* save ctx pointer into R6 */  	emit(gen, BPF_MOV64_REG(BPF_REG_6, BPF_REG_1)); @@ -118,19 +127,27 @@ void bpf_gen__init(struct bpf_gen *gen, int log_level)  	emit(gen, BPF_MOV64_IMM(BPF_REG_3, 0));  	emit(gen, BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel)); +	/* amount of stack actually used, only used to calculate iterations, not stack offset */ +	nr_progs_sz = offsetof(struct loader_stack, prog_fd[nr_progs]);  	/* jump over cleanup code */  	emit(gen, BPF_JMP_IMM(BPF_JA, 0, 0, -			      /* size of cleanup code below */ -			      (stack_sz / 4) * 3 + 2)); +			      /* size of cleanup code below (including map fd cleanup) */ +			      (nr_progs_sz / 4) * 3 + 2 + +			      /* 6 insns for emit_sys_close_blob, +			       * 6 insns for debug_regs in emit_sys_close_blob +			       */ +			      nr_maps * (6 + (gen->log_level ? 6 : 0))));  	/* remember the label where all error branches will jump to */  	gen->cleanup_label = gen->insn_cur - gen->insn_start;  	/* emit cleanup code: close all temp FDs */ -	for (i = 0; i < stack_sz; i += 4) { +	for (i = 0; i < nr_progs_sz; i += 4) {  		emit(gen, BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_10, -stack_sz + i));  		emit(gen, BPF_JMP_IMM(BPF_JSLE, BPF_REG_1, 0, 1));  		emit(gen, BPF_EMIT_CALL(BPF_FUNC_sys_close));  	} +	for (i = 0; i < nr_maps; i++) +		emit_sys_close_blob(gen, blob_fd_array_off(gen, i));  	/* R7 contains the error code from sys_bpf. Copy it into R0 and exit. */  	emit(gen, BPF_MOV64_REG(BPF_REG_0, BPF_REG_7));  	emit(gen, BPF_EXIT_INSN()); @@ -160,8 +177,6 @@ static int add_data(struct bpf_gen *gen, const void *data, __u32 size)   */  static int add_map_fd(struct bpf_gen *gen)  { -	if (!gen->fd_array) -		gen->fd_array = add_data(gen, NULL, MAX_FD_ARRAY_SZ * sizeof(int));  	if (gen->nr_maps == MAX_USED_MAPS) {  		pr_warn("Total maps exceeds %d\n", MAX_USED_MAPS);  		gen->error = -E2BIG; @@ -174,8 +189,6 @@ static int add_kfunc_btf_fd(struct bpf_gen *gen)  {  	int cur; -	if (!gen->fd_array) -		gen->fd_array = add_data(gen, NULL, MAX_FD_ARRAY_SZ * sizeof(int));  	if (gen->nr_fd_array == MAX_KFUNC_DESCS) {  		cur = add_data(gen, NULL, sizeof(int));  		return (cur - gen->fd_array) / sizeof(int); @@ -183,11 +196,6 @@ static int add_kfunc_btf_fd(struct bpf_gen *gen)  	return MAX_USED_MAPS + gen->nr_fd_array++;  } -static int blob_fd_array_off(struct bpf_gen *gen, int index) -{ -	return gen->fd_array + index * sizeof(int); -} -  static int insn_bytes_to_bpf_size(__u32 sz)  {  	switch (sz) { @@ -359,10 +367,15 @@ static void emit_sys_close_blob(struct bpf_gen *gen, int blob_off)  	__emit_sys_close(gen);  } -int bpf_gen__finish(struct bpf_gen *gen) +int bpf_gen__finish(struct bpf_gen *gen, int nr_progs, int nr_maps)  {  	int i; +	if (nr_progs != gen->nr_progs || nr_maps != gen->nr_maps) { +		pr_warn("progs/maps mismatch\n"); +		gen->error = -EFAULT; +		return gen->error; +	}  	emit_sys_close_stack(gen, stack_off(btf_fd));  	for (i = 0; i < gen->nr_progs; i++)  		move_stack2ctx(gen,  | 
