1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _LINUX_VIRTIO_FEATURES_H
3 #define _LINUX_VIRTIO_FEATURES_H
4
5 #include <linux/bits.h>
6
7 #define VIRTIO_FEATURES_DWORDS 2
8 #define VIRTIO_FEATURES_MAX (VIRTIO_FEATURES_DWORDS * 64)
9 #define VIRTIO_FEATURES_WORDS (VIRTIO_FEATURES_DWORDS * 2)
10 #define VIRTIO_BIT(b) BIT_ULL((b) & 0x3f)
11 #define VIRTIO_DWORD(b) ((b) >> 6)
12 #define VIRTIO_DECLARE_FEATURES(name) \
13 union { \
14 u64 name; \
15 u64 name##_array[VIRTIO_FEATURES_DWORDS];\
16 }
17
virtio_features_chk_bit(unsigned int bit)18 static inline bool virtio_features_chk_bit(unsigned int bit)
19 {
20 if (__builtin_constant_p(bit)) {
21 /*
22 * Don't care returning the correct value: the build
23 * will fail before any bad features access
24 */
25 BUILD_BUG_ON(bit >= VIRTIO_FEATURES_MAX);
26 } else {
27 if (WARN_ON_ONCE(bit >= VIRTIO_FEATURES_MAX))
28 return false;
29 }
30 return true;
31 }
32
virtio_features_test_bit(const u64 * features,unsigned int bit)33 static inline bool virtio_features_test_bit(const u64 *features,
34 unsigned int bit)
35 {
36 return virtio_features_chk_bit(bit) &&
37 !!(features[VIRTIO_DWORD(bit)] & VIRTIO_BIT(bit));
38 }
39
virtio_features_set_bit(u64 * features,unsigned int bit)40 static inline void virtio_features_set_bit(u64 *features,
41 unsigned int bit)
42 {
43 if (virtio_features_chk_bit(bit))
44 features[VIRTIO_DWORD(bit)] |= VIRTIO_BIT(bit);
45 }
46
virtio_features_clear_bit(u64 * features,unsigned int bit)47 static inline void virtio_features_clear_bit(u64 *features,
48 unsigned int bit)
49 {
50 if (virtio_features_chk_bit(bit))
51 features[VIRTIO_DWORD(bit)] &= ~VIRTIO_BIT(bit);
52 }
53
virtio_features_zero(u64 * features)54 static inline void virtio_features_zero(u64 *features)
55 {
56 memset(features, 0, sizeof(features[0]) * VIRTIO_FEATURES_DWORDS);
57 }
58
virtio_features_from_u64(u64 * features,u64 from)59 static inline void virtio_features_from_u64(u64 *features, u64 from)
60 {
61 virtio_features_zero(features);
62 features[0] = from;
63 }
64
virtio_features_equal(const u64 * f1,const u64 * f2)65 static inline bool virtio_features_equal(const u64 *f1, const u64 *f2)
66 {
67 int i;
68
69 for (i = 0; i < VIRTIO_FEATURES_DWORDS; ++i)
70 if (f1[i] != f2[i])
71 return false;
72 return true;
73 }
74
virtio_features_copy(u64 * to,const u64 * from)75 static inline void virtio_features_copy(u64 *to, const u64 *from)
76 {
77 memcpy(to, from, sizeof(to[0]) * VIRTIO_FEATURES_DWORDS);
78 }
79
virtio_features_andnot(u64 * to,const u64 * f1,const u64 * f2)80 static inline void virtio_features_andnot(u64 *to, const u64 *f1, const u64 *f2)
81 {
82 int i;
83
84 for (i = 0; i < VIRTIO_FEATURES_DWORDS; i++)
85 to[i] = f1[i] & ~f2[i];
86 }
87
88 #endif
89