xref: /linux/include/net/libeth/cache.h (revision c771600c6af14749609b49565ffb4cac2959710d)
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 */
67