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

bpf: Add BTF_KIND_FLOAT support

On the kernel side, introduce a new btf_kind_operations. It is
similar to that of BTF_KIND_INT, however, it does not need to
handle encodings and bit offsets. Do not implement printing, since
the kernel does not know how to format floating-point values.

Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Yonghong Song <yhs@fb.com>
Link: https://lore.kernel.org/bpf/20210226202256.116518-7-iii@linux.ibm.com

authored by

Ilya Leoshkevich and committed by
Alexei Starovoitov
b1828f0b eea154a8

+81 -2
+81 -2
kernel/bpf/btf.c
··· 173 173 #define BITS_ROUNDUP_BYTES(bits) \ 174 174 (BITS_ROUNDDOWN_BYTES(bits) + !!BITS_PER_BYTE_MASKED(bits)) 175 175 176 - #define BTF_INFO_MASK 0x8f00ffff 176 + #define BTF_INFO_MASK 0x9f00ffff 177 177 #define BTF_INT_MASK 0x0fffffff 178 178 #define BTF_TYPE_ID_VALID(type_id) ((type_id) <= BTF_MAX_TYPE) 179 179 #define BTF_STR_OFFSET_VALID(name_off) ((name_off) <= BTF_MAX_NAME_OFFSET) ··· 280 280 [BTF_KIND_FUNC_PROTO] = "FUNC_PROTO", 281 281 [BTF_KIND_VAR] = "VAR", 282 282 [BTF_KIND_DATASEC] = "DATASEC", 283 + [BTF_KIND_FLOAT] = "FLOAT", 283 284 }; 284 285 285 286 static const char *btf_type_str(const struct btf_type *t) ··· 575 574 case BTF_KIND_UNION: 576 575 case BTF_KIND_ENUM: 577 576 case BTF_KIND_DATASEC: 577 + case BTF_KIND_FLOAT: 578 578 return true; 579 579 } 580 580 ··· 1706 1704 case BTF_KIND_STRUCT: 1707 1705 case BTF_KIND_UNION: 1708 1706 case BTF_KIND_ENUM: 1707 + case BTF_KIND_FLOAT: 1709 1708 size = type->size; 1710 1709 goto resolved; 1711 1710 ··· 1852 1849 return -EINVAL; 1853 1850 } 1854 1851 1855 - /* Used for ptr, array and struct/union type members. 1852 + /* Used for ptr, array struct/union and float type members. 1856 1853 * int, enum and modifier types have their specific callback functions. 1857 1854 */ 1858 1855 static int btf_generic_check_kflag_member(struct btf_verifier_env *env, ··· 3678 3675 .show = btf_datasec_show, 3679 3676 }; 3680 3677 3678 + static s32 btf_float_check_meta(struct btf_verifier_env *env, 3679 + const struct btf_type *t, 3680 + u32 meta_left) 3681 + { 3682 + if (btf_type_vlen(t)) { 3683 + btf_verifier_log_type(env, t, "vlen != 0"); 3684 + return -EINVAL; 3685 + } 3686 + 3687 + if (btf_type_kflag(t)) { 3688 + btf_verifier_log_type(env, t, "Invalid btf_info kind_flag"); 3689 + return -EINVAL; 3690 + } 3691 + 3692 + if (t->size != 2 && t->size != 4 && t->size != 8 && t->size != 12 && 3693 + t->size != 16) { 3694 + btf_verifier_log_type(env, t, "Invalid type_size"); 3695 + return -EINVAL; 3696 + } 3697 + 3698 + btf_verifier_log_type(env, t, NULL); 3699 + 3700 + return 0; 3701 + } 3702 + 3703 + static int btf_float_check_member(struct btf_verifier_env *env, 3704 + const struct btf_type *struct_type, 3705 + const struct btf_member *member, 3706 + const struct btf_type *member_type) 3707 + { 3708 + u64 start_offset_bytes; 3709 + u64 end_offset_bytes; 3710 + u64 misalign_bits; 3711 + u64 align_bytes; 3712 + u64 align_bits; 3713 + 3714 + /* Different architectures have different alignment requirements, so 3715 + * here we check only for the reasonable minimum. This way we ensure 3716 + * that types after CO-RE can pass the kernel BTF verifier. 3717 + */ 3718 + align_bytes = min_t(u64, sizeof(void *), member_type->size); 3719 + align_bits = align_bytes * BITS_PER_BYTE; 3720 + div64_u64_rem(member->offset, align_bits, &misalign_bits); 3721 + if (misalign_bits) { 3722 + btf_verifier_log_member(env, struct_type, member, 3723 + "Member is not properly aligned"); 3724 + return -EINVAL; 3725 + } 3726 + 3727 + start_offset_bytes = member->offset / BITS_PER_BYTE; 3728 + end_offset_bytes = start_offset_bytes + member_type->size; 3729 + if (end_offset_bytes > struct_type->size) { 3730 + btf_verifier_log_member(env, struct_type, member, 3731 + "Member exceeds struct_size"); 3732 + return -EINVAL; 3733 + } 3734 + 3735 + return 0; 3736 + } 3737 + 3738 + static void btf_float_log(struct btf_verifier_env *env, 3739 + const struct btf_type *t) 3740 + { 3741 + btf_verifier_log(env, "size=%u", t->size); 3742 + } 3743 + 3744 + static const struct btf_kind_operations float_ops = { 3745 + .check_meta = btf_float_check_meta, 3746 + .resolve = btf_df_resolve, 3747 + .check_member = btf_float_check_member, 3748 + .check_kflag_member = btf_generic_check_kflag_member, 3749 + .log_details = btf_float_log, 3750 + .show = btf_df_show, 3751 + }; 3752 + 3681 3753 static int btf_func_proto_check(struct btf_verifier_env *env, 3682 3754 const struct btf_type *t) 3683 3755 { ··· 3886 3808 [BTF_KIND_FUNC_PROTO] = &func_proto_ops, 3887 3809 [BTF_KIND_VAR] = &var_ops, 3888 3810 [BTF_KIND_DATASEC] = &datasec_ops, 3811 + [BTF_KIND_FLOAT] = &float_ops, 3889 3812 }; 3890 3813 3891 3814 static s32 btf_check_meta(struct btf_verifier_env *env,