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;
else
break;
- }
- 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;
}
- }
+}
[...]