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

libeth: add cacheline / struct layout assertion helpers

Add helpers to assert struct field layout, a bit more crazy and
networking-specific than in <linux/cache.h>. They assume you have
3 CL-aligned groups (read-mostly, read-write, cold) in a struct
you want to assert, and nothing besides them.
For 64-bit with 64-byte cachelines, the assertions are as strict
as possible, as the size can then be easily predicted.
For the rest, make sure they don't cross the specified bound.

Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>

authored by

Alexander Lobakin and committed by
Tony Nguyen
62c88425 39daa09d

+66
+66
include/net/libeth/cache.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* Copyright (C) 2024 Intel Corporation */ 3 + 4 + #ifndef __LIBETH_CACHE_H 5 + #define __LIBETH_CACHE_H 6 + 7 + #include <linux/cache.h> 8 + 9 + /** 10 + * libeth_cacheline_group_assert - make sure cacheline group size is expected 11 + * @type: type of the structure containing the group 12 + * @grp: group name inside the struct 13 + * @sz: expected group size 14 + */ 15 + #if defined(CONFIG_64BIT) && SMP_CACHE_BYTES == 64 16 + #define libeth_cacheline_group_assert(type, grp, sz) \ 17 + static_assert(offsetof(type, __cacheline_group_end__##grp) - \ 18 + offsetofend(type, __cacheline_group_begin__##grp) == \ 19 + (sz)) 20 + #define __libeth_cacheline_struct_assert(type, sz) \ 21 + static_assert(sizeof(type) == (sz)) 22 + #else /* !CONFIG_64BIT || SMP_CACHE_BYTES != 64 */ 23 + #define libeth_cacheline_group_assert(type, grp, sz) \ 24 + static_assert(offsetof(type, __cacheline_group_end__##grp) - \ 25 + offsetofend(type, __cacheline_group_begin__##grp) <= \ 26 + (sz)) 27 + #define __libeth_cacheline_struct_assert(type, sz) \ 28 + static_assert(sizeof(type) <= (sz)) 29 + #endif /* !CONFIG_64BIT || SMP_CACHE_BYTES != 64 */ 30 + 31 + #define __libeth_cls1(sz1) SMP_CACHE_ALIGN(sz1) 32 + #define __libeth_cls2(sz1, sz2) (SMP_CACHE_ALIGN(sz1) + SMP_CACHE_ALIGN(sz2)) 33 + #define __libeth_cls3(sz1, sz2, sz3) \ 34 + (SMP_CACHE_ALIGN(sz1) + SMP_CACHE_ALIGN(sz2) + SMP_CACHE_ALIGN(sz3)) 35 + #define __libeth_cls(...) \ 36 + CONCATENATE(__libeth_cls, COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__) 37 + 38 + /** 39 + * libeth_cacheline_struct_assert - make sure CL-based struct size is expected 40 + * @type: type of the struct 41 + * @...: from 1 to 3 CL group sizes (read-mostly, read-write, cold) 42 + * 43 + * When a struct contains several CL groups, it's difficult to predict its size 44 + * on different architectures. The macro instead takes sizes of all of the 45 + * groups the structure contains and generates the final struct size. 46 + */ 47 + #define libeth_cacheline_struct_assert(type, ...) \ 48 + __libeth_cacheline_struct_assert(type, __libeth_cls(__VA_ARGS__)); \ 49 + static_assert(__alignof(type) >= SMP_CACHE_BYTES) 50 + 51 + /** 52 + * libeth_cacheline_set_assert - make sure CL-based struct layout is expected 53 + * @type: type of the struct 54 + * @ro: expected size of the read-mostly group 55 + * @rw: expected size of the read-write group 56 + * @c: expected size of the cold group 57 + * 58 + * Check that each group size is expected and then do final struct size check. 59 + */ 60 + #define libeth_cacheline_set_assert(type, ro, rw, c) \ 61 + libeth_cacheline_group_assert(type, read_mostly, ro); \ 62 + libeth_cacheline_group_assert(type, read_write, rw); \ 63 + libeth_cacheline_group_assert(type, cold, c); \ 64 + libeth_cacheline_struct_assert(type, ro, rw, c) 65 + 66 + #endif /* __LIBETH_CACHE_H */