|
14 | 14 | #include <linux/atomic.h> |
15 | 15 | #include <linux/vhost_iotlb.h> |
16 | 16 | #include <linux/irqbypass.h> |
| 17 | +#include <linux/unroll.h> |
17 | 18 |
|
18 | 19 | struct vhost_work; |
19 | 20 | struct vhost_task; |
@@ -279,14 +280,39 @@ void vhost_iotlb_map_free(struct vhost_iotlb *iotlb, |
279 | 280 | eventfd_signal((vq)->error_ctx);\ |
280 | 281 | } while (0) |
281 | 282 |
|
282 | | -enum { |
283 | | - VHOST_FEATURES = (1ULL << VIRTIO_F_NOTIFY_ON_EMPTY) | |
284 | | - (1ULL << VIRTIO_RING_F_INDIRECT_DESC) | |
285 | | - (1ULL << VIRTIO_RING_F_EVENT_IDX) | |
286 | | - (1ULL << VHOST_F_LOG_ALL) | |
287 | | - (1ULL << VIRTIO_F_ANY_LAYOUT) | |
288 | | - (1ULL << VIRTIO_F_VERSION_1) |
289 | | -}; |
| 283 | +#define VHOST_FEATURES \ |
| 284 | + VIRTIO_F_NOTIFY_ON_EMPTY, \ |
| 285 | + VIRTIO_RING_F_INDIRECT_DESC, \ |
| 286 | + VIRTIO_RING_F_EVENT_IDX, \ |
| 287 | + VHOST_F_LOG_ALL, \ |
| 288 | + VIRTIO_F_ANY_LAYOUT, \ |
| 289 | + VIRTIO_F_VERSION_1 |
| 290 | + |
| 291 | +static inline u64 vhost_features_u64(const int *features, int size, int idx) |
| 292 | +{ |
| 293 | + u64 res = 0; |
| 294 | + |
| 295 | + unrolled_count(VIRTIO_FEATURES_BITS) |
| 296 | + for (int i = 0; i < size; ++i) { |
| 297 | + int bit = features[i]; |
| 298 | + |
| 299 | + if (virtio_features_chk_bit(bit) && VIRTIO_U64(bit) == idx) |
| 300 | + res |= VIRTIO_BIT(bit); |
| 301 | + } |
| 302 | + return res; |
| 303 | +} |
| 304 | + |
| 305 | +#define VHOST_FEATURES_U64(features, idx) \ |
| 306 | + vhost_features_u64(features, ARRAY_SIZE(features), idx) |
| 307 | + |
| 308 | +#define DEFINE_VHOST_FEATURES_ARRAY_ENTRY(idx, features) \ |
| 309 | + [idx] = VHOST_FEATURES_U64(features, idx), |
| 310 | + |
| 311 | +#define DEFINE_VHOST_FEATURES_ARRAY(array, features) \ |
| 312 | + u64 array[VIRTIO_FEATURES_U64S] = { \ |
| 313 | + UNROLL(VIRTIO_FEATURES_U64S, \ |
| 314 | + DEFINE_VHOST_FEATURES_ARRAY_ENTRY, features) \ |
| 315 | + } |
290 | 316 |
|
291 | 317 | /** |
292 | 318 | * vhost_vq_set_backend - Set backend. |
|
0 commit comments