insn->src_reg == BPF_PSEUDO_KFUNC_CALL;
 }
 
-static bool bpf_pseudo_func(const struct bpf_insn *insn)
-{
-       return insn->code == (BPF_LD | BPF_IMM | BPF_DW) &&
-              insn->src_reg == BPF_PSEUDO_FUNC;
-}
-
 struct bpf_call_arg_meta {
        struct bpf_map *map_ptr;
        bool raw_mode;
                        return -EPERM;
                }
 
-               if (bpf_pseudo_func(insn)) {
+               if (bpf_pseudo_func(insn) || bpf_pseudo_call(insn))
                        ret = add_subprog(env, i + insn->imm + 1);
-                       if (ret >= 0)
-                               /* remember subprog */
-                               insn[1].imm = ret;
-               } else if (bpf_pseudo_call(insn)) {
-                       ret = add_subprog(env, i + insn->imm + 1);
-               } else {
+               else
                        ret = add_kfunc_call(env, insn->imm);
-               }
 
                if (ret < 0)
                        return ret;
 
        if (insn->src_reg == BPF_PSEUDO_FUNC) {
                struct bpf_prog_aux *aux = env->prog->aux;
-               u32 subprogno = insn[1].imm;
+               u32 subprogno = find_subprog(env,
+                                            env->insn_idx + insn->imm + 1);
 
                if (!aux->func_info) {
                        verbose(env, "missing btf func_info\n");
                return 0;
 
        for (i = 0, insn = prog->insnsi; i < prog->len; i++, insn++) {
-               if (bpf_pseudo_func(insn)) {
-                       env->insn_aux_data[i].call_imm = insn->imm;
-                       /* subprog is encoded in insn[1].imm */
+               if (!bpf_pseudo_func(insn) && !bpf_pseudo_call(insn))
                        continue;
-               }
 
-               if (!bpf_pseudo_call(insn))
-                       continue;
                /* Upon error here we cannot fall back to interpreter but
                 * need a hard reject of the program. Thus -EFAULT is
                 * propagated in any case.
                env->insn_aux_data[i].call_imm = insn->imm;
                /* point imm to __bpf_call_base+1 from JITs point of view */
                insn->imm = 1;
+               if (bpf_pseudo_func(insn))
+                       /* jit (e.g. x86_64) may emit fewer instructions
+                        * if it learns a u32 imm is the same as a u64 imm.
+                        * Force a non zero here.
+                        */
+                       insn[1].imm = 1;
        }
 
        err = bpf_prog_alloc_jited_linfo(prog);
                insn = func[i]->insnsi;
                for (j = 0; j < func[i]->len; j++, insn++) {
                        if (bpf_pseudo_func(insn)) {
-                               subprog = insn[1].imm;
+                               subprog = insn->off;
                                insn[0].imm = (u32)(long)func[subprog]->bpf_func;
                                insn[1].imm = ((u64)(long)func[subprog]->bpf_func) >> 32;
                                continue;
        for (i = 0, insn = prog->insnsi; i < prog->len; i++, insn++) {
                if (bpf_pseudo_func(insn)) {
                        insn[0].imm = env->insn_aux_data[i].call_imm;
-                       insn[1].imm = find_subprog(env, i + insn[0].imm + 1);
+                       insn[1].imm = insn->off;
+                       insn->off = 0;
                        continue;
                }
                if (!bpf_pseudo_call(insn))