master
h 126 lines 3.44 KB
Raw
1 /*
2 * Virtio features helpers
3 *
4 * Copyright 2025 Red Hat, Inc.
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9 #ifndef QEMU_VIRTIO_FEATURES_H
10 #define QEMU_VIRTIO_FEATURES_H
11
12 #include "qemu/bitops.h"
13
14 #define VIRTIO_FEATURES_FMT "%016"PRIx64"%016"PRIx64
15 #define VIRTIO_FEATURES_PR(f) (f)[1], (f)[0]
16
17 #define VIRTIO_FEATURES_MAX 128
18 #define VIRTIO_FEATURES_BIT(b) BIT_ULL((b) % 64)
19 #define VIRTIO_FEATURES_U64(b) ((b) / 64)
20 #define VIRTIO_FEATURES_NU32S (VIRTIO_FEATURES_MAX / 32)
21 #define VIRTIO_FEATURES_NU64S (VIRTIO_FEATURES_MAX / 64)
22
23 #define VIRTIO_DECLARE_FEATURES(name) \
24 union { \
25 uint64_t name; \
26 uint64_t name##_ex[VIRTIO_FEATURES_NU64S]; \
27 }
28
29 #define VIRTIO_DEFINE_PROP_FEATURE(_name, _state, _field, _bit, _defval) \
30 DEFINE_PROP_BIT64(_name, _state, _field[VIRTIO_FEATURES_U64(_bit)], \
31 (_bit) % 64, _defval)
32
33 static inline void virtio_features_clear(uint64_t *features)
34 {
35 memset(features, 0, sizeof(features[0]) * VIRTIO_FEATURES_NU64S);
36 }
37
38 static inline void virtio_features_from_u64(uint64_t *features, uint64_t from)
39 {
40 virtio_features_clear(features);
41 features[0] = from;
42 }
43
44 static inline bool virtio_has_feature_ex(const uint64_t *features,
45 unsigned int fbit)
46 {
47 assert(fbit < VIRTIO_FEATURES_MAX);
48 return features[VIRTIO_FEATURES_U64(fbit)] & VIRTIO_FEATURES_BIT(fbit);
49 }
50
51 static inline void virtio_add_feature_ex(uint64_t *features,
52 unsigned int fbit)
53 {
54 assert(fbit < VIRTIO_FEATURES_MAX);
55 features[VIRTIO_FEATURES_U64(fbit)] |= VIRTIO_FEATURES_BIT(fbit);
56 }
57
58 static inline void virtio_clear_feature_ex(uint64_t *features,
59 unsigned int fbit)
60 {
61 assert(fbit < VIRTIO_FEATURES_MAX);
62 features[VIRTIO_FEATURES_U64(fbit)] &= ~VIRTIO_FEATURES_BIT(fbit);
63 }
64
65 static inline bool virtio_features_equal(const uint64_t *f1,
66 const uint64_t *f2)
67 {
68 return !memcmp(f1, f2, sizeof(uint64_t) * VIRTIO_FEATURES_NU64S);
69 }
70
71 static inline bool virtio_features_use_ex(const uint64_t *features)
72 {
73 int i;
74
75 for (i = 1; i < VIRTIO_FEATURES_NU64S; ++i) {
76 if (features[i]) {
77 return true;
78 }
79 }
80 return false;
81 }
82
83 static inline bool virtio_features_empty(const uint64_t *features)
84 {
85 return !virtio_features_use_ex(features) && !features[0];
86 }
87
88 static inline void virtio_features_copy(uint64_t *to, const uint64_t *from)
89 {
90 memcpy(to, from, sizeof(to[0]) * VIRTIO_FEATURES_NU64S);
91 }
92
93 static inline bool virtio_features_andnot(uint64_t *to, const uint64_t *f1,
94 const uint64_t *f2)
95 {
96 uint64_t diff = 0;
97 int i;
98
99 for (i = 0; i < VIRTIO_FEATURES_NU64S; i++) {
100 to[i] = f1[i] & ~f2[i];
101 diff |= to[i];
102 }
103 return diff;
104 }
105
106 static inline void virtio_features_and(uint64_t *to, const uint64_t *f1,
107 const uint64_t *f2)
108 {
109 int i;
110
111 for (i = 0; i < VIRTIO_FEATURES_NU64S; i++) {
112 to[i] = f1[i] & f2[i];
113 }
114 }
115
116 static inline void virtio_features_or(uint64_t *to, const uint64_t *f1,
117 const uint64_t *f2)
118 {
119 int i;
120
121 for (i = 0; i < VIRTIO_FEATURES_NU64S; i++) {
122 to[i] = f1[i] | f2[i];
123 }
124 }
125
126 #endif