| /* SPDX-License-Identifier: GPL-2.0 */ | |
| #ifndef _LINUX_VIRTIO_FEATURES_H | |
| #define _LINUX_VIRTIO_FEATURES_H | |
| #include <linux/bits.h> | |
| #define VIRTIO_FEATURES_U64S 2 | |
| #define VIRTIO_FEATURES_BITS (VIRTIO_FEATURES_U64S * 64) | |
| #define VIRTIO_BIT(b) BIT_ULL((b) & 0x3f) | |
| #define VIRTIO_U64(b) ((b) >> 6) | |
| #define VIRTIO_DECLARE_FEATURES(name) \ | |
| union { \ | |
| u64 name; \ | |
| u64 name##_array[VIRTIO_FEATURES_U64S];\ | |
| } | |
| static inline bool virtio_features_chk_bit(unsigned int bit) | |
| { | |
| if (__builtin_constant_p(bit)) { | |
| /* | |
| * Don't care returning the correct value: the build | |
| * will fail before any bad features access | |
| */ | |
| BUILD_BUG_ON(bit >= VIRTIO_FEATURES_BITS); | |
| } else { | |
| if (WARN_ON_ONCE(bit >= VIRTIO_FEATURES_BITS)) | |
| return false; | |
| } | |
| return true; | |
| } | |
| static inline bool virtio_features_test_bit(const u64 *features, | |
| unsigned int bit) | |
| { | |
| return virtio_features_chk_bit(bit) && | |
| !!(features[VIRTIO_U64(bit)] & VIRTIO_BIT(bit)); | |
| } | |
| static inline void virtio_features_set_bit(u64 *features, | |
| unsigned int bit) | |
| { | |
| if (virtio_features_chk_bit(bit)) | |
| features[VIRTIO_U64(bit)] |= VIRTIO_BIT(bit); | |
| } | |
| static inline void virtio_features_clear_bit(u64 *features, | |
| unsigned int bit) | |
| { | |
| if (virtio_features_chk_bit(bit)) | |
| features[VIRTIO_U64(bit)] &= ~VIRTIO_BIT(bit); | |
| } | |
| static inline void virtio_features_zero(u64 *features) | |
| { | |
| memset(features, 0, sizeof(features[0]) * VIRTIO_FEATURES_U64S); | |
| } | |
| static inline void virtio_features_from_u64(u64 *features, u64 from) | |
| { | |
| virtio_features_zero(features); | |
| features[0] = from; | |
| } | |
| static inline bool virtio_features_equal(const u64 *f1, const u64 *f2) | |
| { | |
| int i; | |
| for (i = 0; i < VIRTIO_FEATURES_U64S; ++i) | |
| if (f1[i] != f2[i]) | |
| return false; | |
| return true; | |
| } | |
| static inline void virtio_features_copy(u64 *to, const u64 *from) | |
| { | |
| memcpy(to, from, sizeof(to[0]) * VIRTIO_FEATURES_U64S); | |
| } | |
| static inline void virtio_features_andnot(u64 *to, const u64 *f1, const u64 *f2) | |
| { | |
| int i; | |
| for (i = 0; i < VIRTIO_FEATURES_U64S; i++) | |
| to[i] = f1[i] & ~f2[i]; | |
| } | |
| #endif |