Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: btf: Add BTF_FMODEL_SIGNED_ARG flag

s390x eBPF JIT needs to know whether a function return value is signed
and which function arguments are signed, in order to generate code
compliant with the s390x ABI.

Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Link: https://lore.kernel.org/r/20230128000650.1516334-26-iii@linux.ibm.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Ilya Leoshkevich and committed by
Alexei Starovoitov
49f67f39 0f0e5f5b

+29 -6
+4
include/linux/bpf.h
··· 899 899 /* The argument is a structure. */ 900 900 #define BTF_FMODEL_STRUCT_ARG BIT(0) 901 901 902 + /* The argument is signed. */ 903 + #define BTF_FMODEL_SIGNED_ARG BIT(1) 904 + 902 905 struct btf_func_model { 903 906 u8 ret_size; 907 + u8 ret_flags; 904 908 u8 nr_args; 905 909 u8 arg_size[MAX_BPF_FUNC_ARGS]; 906 910 u8 arg_flags[MAX_BPF_FUNC_ARGS];
+10 -5
include/linux/btf.h
··· 236 236 return btf_type_is_int(t) && t->size <= sizeof(u64); 237 237 } 238 238 239 + static inline u8 btf_int_encoding(const struct btf_type *t) 240 + { 241 + return BTF_INT_ENCODING(*(u32 *)(t + 1)); 242 + } 243 + 244 + static inline bool btf_type_is_signed_int(const struct btf_type *t) 245 + { 246 + return btf_type_is_int(t) && (btf_int_encoding(t) & BTF_INT_SIGNED); 247 + } 248 + 239 249 static inline bool btf_type_is_enum(const struct btf_type *t) 240 250 { 241 251 return BTF_INFO_KIND(t->info) == BTF_KIND_ENUM; ··· 314 304 static inline u8 btf_int_offset(const struct btf_type *t) 315 305 { 316 306 return BTF_INT_OFFSET(*(u32 *)(t + 1)); 317 - } 318 - 319 - static inline u8 btf_int_encoding(const struct btf_type *t) 320 - { 321 - return BTF_INT_ENCODING(*(u32 *)(t + 1)); 322 307 } 323 308 324 309 static inline bool btf_type_is_scalar(const struct btf_type *t)
+15 -1
kernel/bpf/btf.c
··· 6453 6453 return -EINVAL; 6454 6454 } 6455 6455 6456 + static u8 __get_type_fmodel_flags(const struct btf_type *t) 6457 + { 6458 + u8 flags = 0; 6459 + 6460 + if (__btf_type_is_struct(t)) 6461 + flags |= BTF_FMODEL_STRUCT_ARG; 6462 + if (btf_type_is_signed_int(t)) 6463 + flags |= BTF_FMODEL_SIGNED_ARG; 6464 + 6465 + return flags; 6466 + } 6467 + 6456 6468 int btf_distill_func_proto(struct bpf_verifier_log *log, 6457 6469 struct btf *btf, 6458 6470 const struct btf_type *func, ··· 6485 6473 m->arg_flags[i] = 0; 6486 6474 } 6487 6475 m->ret_size = 8; 6476 + m->ret_flags = 0; 6488 6477 m->nr_args = MAX_BPF_FUNC_REG_ARGS; 6489 6478 return 0; 6490 6479 } ··· 6505 6492 return -EINVAL; 6506 6493 } 6507 6494 m->ret_size = ret; 6495 + m->ret_flags = __get_type_fmodel_flags(t); 6508 6496 6509 6497 for (i = 0; i < nargs; i++) { 6510 6498 if (i == nargs - 1 && args[i].type == 0) { ··· 6530 6516 return -EINVAL; 6531 6517 } 6532 6518 m->arg_size[i] = ret; 6533 - m->arg_flags[i] = __btf_type_is_struct(t) ? BTF_FMODEL_STRUCT_ARG : 0; 6519 + m->arg_flags[i] = __get_type_fmodel_flags(t); 6534 6520 } 6535 6521 m->nr_args = nargs; 6536 6522 return 0;