Skip to content

Commit

Permalink
bpf: use register liveness information for func_states_equal
Browse files Browse the repository at this point in the history
Liveness analysis DFA computes a conservative set of registers live
before each instruction. Leverage this information to skip comparison
of dead registers in func_states_equal(). This helps with convergance
of iterator processing loops, as bpf_reg_state->live marks can't be
used when loops are processed.

This has certain performance impact for selftests, here is a veristat
listing for bigger ones:

File                                Program                              Insns     (DIFF)  States  (DIFF)
----------------------------------  -----------------------------------  ----------------  --------------
iters.bpf.o                         checkpoint_states_deletion           -16636 (-91.81%)  -745 (-91.19%)
iters.bpf.o                         iter_nested_deeply_iters               -267 (-47.09%)   -26 (-41.27%)
iters.bpf.o                         iter_nested_iters                      -181 (-22.26%)   -17 (-21.52%)
iters.bpf.o                         iter_subprog_iters                     -339 (-33.80%)   -24 (-28.92%)
iters.bpf.o                         loop_state_deps2                       -349 (-48.14%)   -27 (-42.86%)
pyperf600_iter.bpf.o                on_event                                -795 (-6.59%)  +239 (+65.30%)

The pyperf600_iter is curious, as it shows an increase in number of
processed states. The reason for this is:

  <TBD>

Signed-off-by: Eduard Zingerman <[email protected]>
  • Loading branch information
eddyz87 committed Jan 8, 2025
1 parent c16ad68 commit e8d601f
Showing 1 changed file with 10 additions and 4 deletions.
14 changes: 10 additions & 4 deletions kernel/bpf/verifier.c
Original file line number Diff line number Diff line change
Expand Up @@ -18129,15 +18129,17 @@ static bool refsafe(struct bpf_verifier_state *old, struct bpf_verifier_state *c
* the current state will reach 'bpf_exit' instruction safely
*/
static bool func_states_equal(struct bpf_verifier_env *env, struct bpf_func_state *old,
struct bpf_func_state *cur, enum exact_level exact)
struct bpf_func_state *cur, u32 insn_idx, enum exact_level exact)
{
int i;
u16 live_regs = env->insn_aux_data[insn_idx].live_regs_before;
u16 i;

if (old->callback_depth > cur->callback_depth)
return false;

for (i = 0; i < MAX_BPF_REG; i++)
if (!regsafe(env, &old->regs[i], &cur->regs[i],
if (((1 << i) & live_regs) &&
!regsafe(env, &old->regs[i], &cur->regs[i],
&env->idmap_scratch, exact))
return false;

Expand All @@ -18158,6 +18160,7 @@ static bool states_equal(struct bpf_verifier_env *env,
struct bpf_verifier_state *cur,
enum exact_level exact)
{
u32 insn_idx;
int i;

if (old->curframe != cur->curframe)
Expand All @@ -18181,9 +18184,12 @@ static bool states_equal(struct bpf_verifier_env *env,
* and all frame states need to be equivalent
*/
for (i = 0; i <= old->curframe; i++) {
insn_idx = i == old->curframe
? env->insn_idx
: old->frame[i + 1]->callsite;
if (old->frame[i]->callsite != cur->frame[i]->callsite)
return false;
if (!func_states_equal(env, old->frame[i], cur->frame[i], exact))
if (!func_states_equal(env, old->frame[i], cur->frame[i], insn_idx, exact))
return false;
}
return true;
Expand Down

0 comments on commit e8d601f

Please sign in to comment.