Skip to content

Commit a32014b

Browse files
Jakub KicinskiAlexei Starovoitov
authored andcommitted
nfp: bpf: support optimizing dead branches
Verifier will now optimize out branches to dead code, implement the replace_insn callback to take advantage of that optimization. Signed-off-by: Jakub Kicinski <[email protected]> Reviewed-by: Quentin Monnet <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent e2fc611 commit a32014b

File tree

3 files changed

+49
-0
lines changed

3 files changed

+49
-0
lines changed

drivers/net/ethernet/netronome/nfp/bpf/main.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,17 @@ static inline bool is_mbpf_div(const struct nfp_insn_meta *meta)
412412
return is_mbpf_alu(meta) && mbpf_op(meta) == BPF_DIV;
413413
}
414414

415+
static inline bool is_mbpf_cond_jump(const struct nfp_insn_meta *meta)
416+
{
417+
u8 op;
418+
419+
if (BPF_CLASS(meta->insn.code) != BPF_JMP)
420+
return false;
421+
422+
op = BPF_OP(meta->insn.code);
423+
return op != BPF_JA && op != BPF_EXIT && op != BPF_CALL;
424+
}
425+
415426
static inline bool is_mbpf_helper_call(const struct nfp_insn_meta *meta)
416427
{
417428
struct bpf_insn insn = meta->insn;
@@ -520,6 +531,9 @@ int nfp_verify_insn(struct bpf_verifier_env *env, int insn_idx,
520531
int prev_insn_idx);
521532
int nfp_bpf_finalize(struct bpf_verifier_env *env);
522533

534+
int nfp_bpf_opt_replace_insn(struct bpf_verifier_env *env, u32 off,
535+
struct bpf_insn *insn);
536+
523537
extern const struct bpf_prog_offload_ops nfp_bpf_dev_ops;
524538

525539
struct netdev_bpf;

drivers/net/ethernet/netronome/nfp/bpf/offload.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,7 @@ int nfp_net_bpf_offload(struct nfp_net *nn, struct bpf_prog *prog,
592592
const struct bpf_prog_offload_ops nfp_bpf_dev_ops = {
593593
.insn_hook = nfp_verify_insn,
594594
.finalize = nfp_bpf_finalize,
595+
.replace_insn = nfp_bpf_opt_replace_insn,
595596
.prepare = nfp_bpf_verifier_prep,
596597
.translate = nfp_bpf_translate,
597598
.destroy = nfp_bpf_destroy,

drivers/net/ethernet/netronome/nfp/bpf/verifier.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,3 +786,37 @@ int nfp_bpf_finalize(struct bpf_verifier_env *env)
786786

787787
return 0;
788788
}
789+
790+
int nfp_bpf_opt_replace_insn(struct bpf_verifier_env *env, u32 off,
791+
struct bpf_insn *insn)
792+
{
793+
struct nfp_prog *nfp_prog = env->prog->aux->offload->dev_priv;
794+
struct bpf_insn_aux_data *aux_data = env->insn_aux_data;
795+
struct nfp_insn_meta *meta = nfp_prog->verifier_meta;
796+
797+
meta = nfp_bpf_goto_meta(nfp_prog, meta, aux_data[off].orig_idx);
798+
nfp_prog->verifier_meta = meta;
799+
800+
/* conditional jump to jump conversion */
801+
if (is_mbpf_cond_jump(meta) &&
802+
insn->code == (BPF_JMP | BPF_JA | BPF_K)) {
803+
unsigned int tgt_off;
804+
805+
tgt_off = off + insn->off + 1;
806+
807+
if (!insn->off) {
808+
meta->jmp_dst = list_next_entry(meta, l);
809+
meta->jump_neg_op = false;
810+
} else if (meta->jmp_dst->n != aux_data[tgt_off].orig_idx) {
811+
pr_vlog(env, "branch hard wire at %d changes target %d -> %d\n",
812+
off, meta->jmp_dst->n,
813+
aux_data[tgt_off].orig_idx);
814+
return -EINVAL;
815+
}
816+
return 0;
817+
}
818+
819+
pr_vlog(env, "unsupported instruction replacement %hhx -> %hhx\n",
820+
meta->insn.code, insn->code);
821+
return -EINVAL;
822+
}

0 commit comments

Comments
 (0)