On Thu, Apr 17, 2025 at 12:14 AM Alexis Lothoré <alexis.loth...@bootlin.com> wrote: > > Hi Andrii, > > On Wed Apr 16, 2025 at 11:24 PM CEST, Andrii Nakryiko wrote: > > On Fri, Apr 11, 2025 at 1:32 PM Alexis Lothoré (eBPF Foundation) > > <alexis.loth...@bootlin.com> wrote: > >> > >> In order to properly JIT the trampolines needed to attach BPF programs > >> to functions, some architectures like ARM64 need to know about the > >> alignment needed for the function arguments. Such alignment can > >> generally be deduced from the argument size, but that's not completely > >> true for composite types. In the specific case of ARM64, the AAPCS64 ABI > >> defines that a composite type which needs to be passed through stack > >> must be aligned on the maximum between 8 and the largest alignment > >> constraint of its first-level members. So the JIT compiler needs more > >> information about the arguments to make sure to generate code that > >> respects those alignment constraints. > >> > >> For struct arguments, add information about the size of the largest > >> first-level member in the struct btf_func_model to allow the JIT > >> compiler to guess the needed alignment. The information is quite > > > > I might be missing something, but how can the *size* of the field be > > used to calculate that argument's *alignment*? i.e., I don't > > understand why arg_largest_member_size needs to be calculated instead > > of arg_largest_member_alignment... > > Indeed I initially checked whether I could return directly some alignment > info from btf, but it then involves the alignment computation in the btf > module. Since there could be minor differences between architectures about > alignment requirements, I though it would be better to in fact keep alignment > computation out of the btf module. For example, I see that 128 bits values > are aligned on 16 bytes on ARM64, while being aligned on 8 bytes on S390. > > And since for ARM64, all needed alignments are somehow derived from size > (it is either directly size for fundamental types, or alignment of the > largest member for structs, which is then size of largest member), > returning the size seems to be enough to allow the JIT side to compute > alignments.
If you mean the size of "primitive" field and/or array element (applied recursively for all embedded structs/unions) then yes, that's close enough. But saying just "largest struct member" is wrong, because for struct blah { struct { int whatever[128]; } heya; }; blah.heya has a large size, but alignment is still just 4 bytes. I'd suggest looking at btf__align_of() in libbpf (tools/lib/bpf/btf.c) to see how we calculate alignment there. It seems to work decently enough. It won't cover any arch-specific extra rules like double needing 16-byte alignment (I vaguely remember something like that for some architectures, but I might be misremembering), or anything similar. It also won't detect (I don't think it's possible without DWARF) artificially increased alignment with attribute((aligned(N))). > > >> specific, but it allows to keep arch-specific concerns (ie: guessing the > >> final needed alignment for an argument) isolated in each JIT compiler. > > > > couldn't all this information be calculated in the JIT compiler (if > > JIT needs that) from BTF? > > From what I understand, the JIT compiler does not have access to BTF info, > only a substract from it, arranged in a struct btf_func_model ? This > struct btf_func_model already has size info for standard types, but for > structs we need some additional info about the members, hence this > arg_largest_member_alignment addition in btf_func_model. > > Thanks, > > Alexis > > -- > Alexis Lothoré, Bootlin > Embedded Linux and Kernel engineering > https://bootlin.com >