aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorJakub Kicinski <jakub.kicinski@netronome.com>2019-01-23 01:45:24 -0500
committerAlexei Starovoitov <ast@kernel.org>2019-01-23 20:35:32 -0500
commit08ca90afba255d05dc3253caa44056e7aecbe8c5 (patch)
treecc07e5da7cef8df19e81ea02527656c0560acd4a /kernel
parent9e4c24e7ee7dfd3898269519103e823892b730d8 (diff)
bpf: notify offload JITs about optimizations
Let offload JITs know when instructions are replaced and optimized out, so they can update their state appropriately. The optimizations are best effort, if JIT returns an error from any callback verifier will stop notifying it as state may now be out of sync, but the verifier continues making progress. Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com> Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/bpf/offload.c35
-rw-r--r--kernel/bpf/verifier.c6
2 files changed, 41 insertions, 0 deletions
diff --git a/kernel/bpf/offload.c b/kernel/bpf/offload.c
index 54cf2b9c44a4..39dba8c90331 100644
--- a/kernel/bpf/offload.c
+++ b/kernel/bpf/offload.c
@@ -173,6 +173,41 @@ int bpf_prog_offload_finalize(struct bpf_verifier_env *env)
173 return ret; 173 return ret;
174} 174}
175 175
176void
177bpf_prog_offload_replace_insn(struct bpf_verifier_env *env, u32 off,
178 struct bpf_insn *insn)
179{
180 const struct bpf_prog_offload_ops *ops;
181 struct bpf_prog_offload *offload;
182 int ret = -EOPNOTSUPP;
183
184 down_read(&bpf_devs_lock);
185 offload = env->prog->aux->offload;
186 if (offload) {
187 ops = offload->offdev->ops;
188 if (!offload->opt_failed && ops->replace_insn)
189 ret = ops->replace_insn(env, off, insn);
190 offload->opt_failed |= ret;
191 }
192 up_read(&bpf_devs_lock);
193}
194
195void
196bpf_prog_offload_remove_insns(struct bpf_verifier_env *env, u32 off, u32 cnt)
197{
198 struct bpf_prog_offload *offload;
199 int ret = -EOPNOTSUPP;
200
201 down_read(&bpf_devs_lock);
202 offload = env->prog->aux->offload;
203 if (offload) {
204 if (!offload->opt_failed && offload->offdev->ops->remove_insns)
205 ret = offload->offdev->ops->remove_insns(env, off, cnt);
206 offload->opt_failed |= ret;
207 }
208 up_read(&bpf_devs_lock);
209}
210
176static void __bpf_prog_offload_destroy(struct bpf_prog *prog) 211static void __bpf_prog_offload_destroy(struct bpf_prog *prog)
177{ 212{
178 struct bpf_prog_offload *offload = prog->aux->offload; 213 struct bpf_prog_offload *offload = prog->aux->offload;
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index f2c49b4235df..8cfe39ef770f 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -6558,6 +6558,9 @@ static int verifier_remove_insns(struct bpf_verifier_env *env, u32 off, u32 cnt)
6558 unsigned int orig_prog_len = env->prog->len; 6558 unsigned int orig_prog_len = env->prog->len;
6559 int err; 6559 int err;
6560 6560
6561 if (bpf_prog_is_dev_bound(env->prog->aux))
6562 bpf_prog_offload_remove_insns(env, off, cnt);
6563
6561 err = bpf_remove_insns(env->prog, off, cnt); 6564 err = bpf_remove_insns(env->prog, off, cnt);
6562 if (err) 6565 if (err)
6563 return err; 6566 return err;
@@ -6632,6 +6635,9 @@ static void opt_hard_wire_dead_code_branches(struct bpf_verifier_env *env)
6632 else 6635 else
6633 continue; 6636 continue;
6634 6637
6638 if (bpf_prog_is_dev_bound(env->prog->aux))
6639 bpf_prog_offload_replace_insn(env, i, &ja);
6640
6635 memcpy(insn, &ja, sizeof(ja)); 6641 memcpy(insn, &ja, sizeof(ja));
6636 } 6642 }
6637} 6643}