xref: /linux/include/linux/virtio_features.h (revision 8be4d31cb8aaeea27bde4b7ddb26e28a89062ebf)
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