On 5/22/2025 6:14 PM, Alexis Lothoré wrote:
[...]
-static void save_args(struct jit_ctx *ctx, int args_off, int nregs) +struct arg_aux {
- /* how many args are passed through registers, the rest of the args are
* passed through stack*/- int args_in_regs;
- /* how many registers are used to pass arguments */
- int regs_for_args;
- /* how much stack is used for additional args passed to bpf program
* that did not fit in original function registers**/
nit: "**/" should be "*/"
- int bstack_for_args;
- /* home much stack is used for additional args passed to the
* original function when called from trampoline (this one needs* arguments to be properly aligned)*/- int ostack_for_args;
+};
+static int calc_arg_aux(const struct btf_func_model *m,
{struct arg_aux *a)
- int i;
- int stack_slots, nregs, slots, i;
- /* verifier ensures m->nr_args <= MAX_BPF_FUNC_ARGS */
- for (i = 0, nregs = 0; i < m->nr_args; i++) {
slots = (m->arg_size[i] + 7) / 8;if (nregs + slots <= 8) /* passed through register ? */nregs += slots;elsebreak;- }
- a->args_in_regs = i;
- a->regs_for_args = nregs;
- a->ostack_for_args = 0;
- /* the rest arguments are passed through stack */
- for (a->ostack_for_args = 0, a->bstack_for_args = 0;
i < m->nr_args; i++) {
a->ostack_for_args is initialized twice.
move all initializations before the loop?
/* We can not know for sure about exact alignment needs for* struct passed on stack, so deny those*/if (m->arg_flags[i] & BTF_FMODEL_STRUCT_ARG)return -EOPNOTSUPP;
leave the error code as is, namely, return -ENOTSUPP?
stack_slots = (m->arg_size[i] + 7) / 8;/* AAPCS 64 C.14: arguments passed on stack must be aligned to* max(8, arg_natural_alignment)*/a->bstack_for_args += stack_slots * 8;a->ostack_for_args = round_up(a->ostack_for_args + stack_slots * 8, 8);
since a->ostack_for_args starts from 0 and is always incremented by multiples of 8, round_up() to 8 is not needed.
- }
- for (i = 0; i < nregs; i++) {
emit(A64_STR64I(i, A64_SP, args_off), ctx);args_off += 8;
- return 0;
+}
+static void clear_garbage(struct jit_ctx *ctx, int reg, int effective_bytes) +{
- if (effective_bytes) {
int garbage_bits = 64 - 8 * effective_bytes;+#ifdef CONFIG_CPU_BIG_ENDIAN
/* garbage bits are at the right end */emit(A64_LSR(1, reg, reg, garbage_bits), ctx);emit(A64_LSL(1, reg, reg, garbage_bits), ctx);+#else
/* garbage bits are at the left end */emit(A64_LSL(1, reg, reg, garbage_bits), ctx);emit(A64_LSR(1, reg, reg, garbage_bits), ctx);+#endif } } -static void restore_args(struct jit_ctx *ctx, int args_off, int nregs) +static void save_args(struct jit_ctx *ctx, int bargs_off, int oargs_off,
const struct btf_func_model *m,const struct arg_aux *a, { int i;bool for_call_origin)- int reg;
- int doff;
- int soff;
- int slots;
- u8 tmp = bpf2a64[TMP_REG_1];
- /* store arguments to the stack for the bpf program, or restore
* arguments from stack for the original function*/- for (reg = 0; reg < a->regs_for_args; reg++) {
emit(for_call_origin ?A64_LDR64I(reg, A64_SP, bargs_off) :A64_STR64I(reg, A64_SP, bargs_off),ctx);bargs_off += 8;- }
- soff = 32; /* on stack arguments start from FP + 32 */
- doff = (for_call_origin ? oargs_off : bargs_off);
- /* save on stack arguments */
- for (i = a->args_in_regs; i < m->nr_args; i++) {
slots = (m->arg_size[i] + 7) / 8;/* AAPCS C.14: additional arguments on stack must be* aligned on max(8, arg_natural_alignment)*/soff = round_up(soff, 8);if (for_call_origin)doff = round_up(doff, 8);
since both soff and doff start from multiples of 8 and are incremented by 8 each time, the two round_up()s are also not needed.
/* verifier ensures arg_size <= 16, so slots equals 1 or 2 */while (slots-- > 0) {emit(A64_LDR64I(tmp, A64_FP, soff), ctx);/* if there is unused space in the last slot, clear* the garbage contained in the space.*/if (slots == 0 && !for_call_origin)clear_garbage(ctx, tmp, m->arg_size[i] % 8);emit(A64_STR64I(tmp, A64_SP, doff), ctx);soff += 8;doff += 8;}- }
+}
[...]