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
18static 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
33static 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
40static 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
47static 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
54static inline void virtio_features_zero(u64 *features)
55{
56 memset(s: features, c: 0, n: sizeof(features[0]) * VIRTIO_FEATURES_DWORDS);
57}
58
59static inline void virtio_features_from_u64(u64 *features, u64 from)
60{
61 virtio_features_zero(features);
62 features[0] = from;
63}
64
65static 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
75static inline void virtio_features_copy(u64 *to, const u64 *from)
76{
77 memcpy(to, from, len: sizeof(to[0]) * VIRTIO_FEATURES_DWORDS);
78}
79
80static 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