.. | .. |
---|
6 | 6 | #include <linux/bug.h> |
---|
7 | 7 | #include <linux/virtio.h> |
---|
8 | 8 | #include <linux/virtio_byteorder.h> |
---|
| 9 | +#include <linux/compiler_types.h> |
---|
9 | 10 | #include <uapi/linux/virtio_config.h> |
---|
10 | 11 | |
---|
11 | 12 | struct irq_affinity; |
---|
12 | 13 | |
---|
| 14 | +struct virtio_shm_region { |
---|
| 15 | + u64 addr; |
---|
| 16 | + u64 len; |
---|
| 17 | +}; |
---|
| 18 | + |
---|
13 | 19 | /** |
---|
14 | 20 | * virtio_config_ops - operations for configuring a virtio device |
---|
| 21 | + * Note: Do not assume that a transport implements all of the operations |
---|
| 22 | + * getting/setting a value as a simple read/write! Generally speaking, |
---|
| 23 | + * any of @get/@set, @get_status/@set_status, or @get_features/ |
---|
| 24 | + * @finalize_features are NOT safe to be called from an atomic |
---|
| 25 | + * context. |
---|
15 | 26 | * @get: read the value of a configuration field |
---|
16 | 27 | * vdev: the virtio_device |
---|
17 | 28 | * offset: the offset of the configuration field |
---|
.. | .. |
---|
22 | 33 | * offset: the offset of the configuration field |
---|
23 | 34 | * buf: the buffer to read the field value from. |
---|
24 | 35 | * len: the length of the buffer |
---|
25 | | - * @generation: config generation counter |
---|
| 36 | + * @generation: config generation counter (optional) |
---|
26 | 37 | * vdev: the virtio_device |
---|
27 | 38 | * Returns the config generation counter |
---|
28 | 39 | * @get_status: read the status byte |
---|
.. | .. |
---|
48 | 59 | * @del_vqs: free virtqueues found by find_vqs(). |
---|
49 | 60 | * @get_features: get the array of feature bits for this device. |
---|
50 | 61 | * vdev: the virtio_device |
---|
51 | | - * Returns the first 32 feature bits (all we currently need). |
---|
| 62 | + * Returns the first 64 feature bits (all we currently need). |
---|
52 | 63 | * @finalize_features: confirm what device features we'll be using. |
---|
53 | 64 | * vdev: the virtio_device |
---|
54 | | - * This gives the final feature bits for the device: it can change |
---|
| 65 | + * This sends the driver feature bits to the device: it can change |
---|
55 | 66 | * the dev->feature bits if it wants. |
---|
| 67 | + * Note: despite the name this can be called any number of times. |
---|
56 | 68 | * Returns 0 on success or error status |
---|
57 | | - * @bus_name: return the bus name associated with the device |
---|
| 69 | + * @bus_name: return the bus name associated with the device (optional) |
---|
58 | 70 | * vdev: the virtio_device |
---|
59 | 71 | * This returns a pointer to the bus name a la pci_name from which |
---|
60 | 72 | * the caller can then copy. |
---|
61 | | - * @set_vq_affinity: set the affinity for a virtqueue. |
---|
| 73 | + * @set_vq_affinity: set the affinity for a virtqueue (optional). |
---|
62 | 74 | * @get_vq_affinity: get the affinity for a virtqueue (optional). |
---|
| 75 | + * @get_shm_region: get a shared memory region based on the index. |
---|
63 | 76 | */ |
---|
64 | 77 | typedef void vq_callback_t(struct virtqueue *); |
---|
65 | 78 | struct virtio_config_ops { |
---|
.. | .. |
---|
83 | 96 | const struct cpumask *cpu_mask); |
---|
84 | 97 | const struct cpumask *(*get_vq_affinity)(struct virtio_device *vdev, |
---|
85 | 98 | int index); |
---|
| 99 | + bool (*get_shm_region)(struct virtio_device *vdev, |
---|
| 100 | + struct virtio_shm_region *region, u8 id); |
---|
86 | 101 | }; |
---|
87 | 102 | |
---|
88 | 103 | /* If driver didn't advertise the feature, it will never appear. */ |
---|
.. | .. |
---|
157 | 172 | } |
---|
158 | 173 | |
---|
159 | 174 | /** |
---|
160 | | - * virtio_has_iommu_quirk - determine whether this device has the iommu quirk |
---|
| 175 | + * virtio_has_dma_quirk - determine whether this device has the DMA quirk |
---|
161 | 176 | * @vdev: the device |
---|
162 | 177 | */ |
---|
163 | | -static inline bool virtio_has_iommu_quirk(const struct virtio_device *vdev) |
---|
| 178 | +static inline bool virtio_has_dma_quirk(const struct virtio_device *vdev) |
---|
164 | 179 | { |
---|
165 | 180 | /* |
---|
166 | 181 | * Note the reverse polarity of the quirk feature (compared to most |
---|
167 | 182 | * other features), this is for compatibility with legacy systems. |
---|
168 | 183 | */ |
---|
169 | | - return !virtio_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM); |
---|
| 184 | + return !virtio_has_feature(vdev, VIRTIO_F_ACCESS_PLATFORM); |
---|
170 | 185 | } |
---|
171 | 186 | |
---|
172 | 187 | static inline |
---|
.. | .. |
---|
245 | 260 | return 0; |
---|
246 | 261 | } |
---|
247 | 262 | |
---|
| 263 | +static inline |
---|
| 264 | +bool virtio_get_shm_region(struct virtio_device *vdev, |
---|
| 265 | + struct virtio_shm_region *region, u8 id) |
---|
| 266 | +{ |
---|
| 267 | + if (!vdev->config->get_shm_region) |
---|
| 268 | + return false; |
---|
| 269 | + return vdev->config->get_shm_region(vdev, region, id); |
---|
| 270 | +} |
---|
| 271 | + |
---|
248 | 272 | static inline bool virtio_is_little_endian(struct virtio_device *vdev) |
---|
249 | 273 | { |
---|
250 | 274 | return virtio_has_feature(vdev, VIRTIO_F_VERSION_1) || |
---|
.. | .. |
---|
282 | 306 | return __cpu_to_virtio64(virtio_is_little_endian(vdev), val); |
---|
283 | 307 | } |
---|
284 | 308 | |
---|
| 309 | +#define virtio_to_cpu(vdev, x) \ |
---|
| 310 | + _Generic((x), \ |
---|
| 311 | + __u8: (x), \ |
---|
| 312 | + __virtio16: virtio16_to_cpu((vdev), (x)), \ |
---|
| 313 | + __virtio32: virtio32_to_cpu((vdev), (x)), \ |
---|
| 314 | + __virtio64: virtio64_to_cpu((vdev), (x)) \ |
---|
| 315 | + ) |
---|
| 316 | + |
---|
| 317 | +#define cpu_to_virtio(vdev, x, m) \ |
---|
| 318 | + _Generic((m), \ |
---|
| 319 | + __u8: (x), \ |
---|
| 320 | + __virtio16: cpu_to_virtio16((vdev), (x)), \ |
---|
| 321 | + __virtio32: cpu_to_virtio32((vdev), (x)), \ |
---|
| 322 | + __virtio64: cpu_to_virtio64((vdev), (x)) \ |
---|
| 323 | + ) |
---|
| 324 | + |
---|
| 325 | +#define __virtio_native_type(structname, member) \ |
---|
| 326 | + typeof(virtio_to_cpu(NULL, ((structname*)0)->member)) |
---|
| 327 | + |
---|
285 | 328 | /* Config space accessors. */ |
---|
286 | 329 | #define virtio_cread(vdev, structname, member, ptr) \ |
---|
287 | 330 | do { \ |
---|
288 | | - /* Must match the member's type, and be integer */ \ |
---|
289 | | - if (!typecheck(typeof((((structname*)0)->member)), *(ptr))) \ |
---|
290 | | - (*ptr) = 1; \ |
---|
| 331 | + typeof(((structname*)0)->member) virtio_cread_v; \ |
---|
291 | 332 | \ |
---|
292 | | - switch (sizeof(*ptr)) { \ |
---|
| 333 | + might_sleep(); \ |
---|
| 334 | + /* Sanity check: must match the member's type */ \ |
---|
| 335 | + typecheck(typeof(virtio_to_cpu((vdev), virtio_cread_v)), *(ptr)); \ |
---|
| 336 | + \ |
---|
| 337 | + switch (sizeof(virtio_cread_v)) { \ |
---|
293 | 338 | case 1: \ |
---|
294 | | - *(ptr) = virtio_cread8(vdev, \ |
---|
295 | | - offsetof(structname, member)); \ |
---|
296 | | - break; \ |
---|
297 | 339 | case 2: \ |
---|
298 | | - *(ptr) = virtio_cread16(vdev, \ |
---|
299 | | - offsetof(structname, member)); \ |
---|
300 | | - break; \ |
---|
301 | 340 | case 4: \ |
---|
302 | | - *(ptr) = virtio_cread32(vdev, \ |
---|
303 | | - offsetof(structname, member)); \ |
---|
304 | | - break; \ |
---|
305 | | - case 8: \ |
---|
306 | | - *(ptr) = virtio_cread64(vdev, \ |
---|
307 | | - offsetof(structname, member)); \ |
---|
| 341 | + vdev->config->get((vdev), \ |
---|
| 342 | + offsetof(structname, member), \ |
---|
| 343 | + &virtio_cread_v, \ |
---|
| 344 | + sizeof(virtio_cread_v)); \ |
---|
308 | 345 | break; \ |
---|
309 | 346 | default: \ |
---|
310 | | - BUG(); \ |
---|
| 347 | + __virtio_cread_many((vdev), \ |
---|
| 348 | + offsetof(structname, member), \ |
---|
| 349 | + &virtio_cread_v, \ |
---|
| 350 | + 1, \ |
---|
| 351 | + sizeof(virtio_cread_v)); \ |
---|
| 352 | + break; \ |
---|
311 | 353 | } \ |
---|
| 354 | + *(ptr) = virtio_to_cpu(vdev, virtio_cread_v); \ |
---|
312 | 355 | } while(0) |
---|
313 | 356 | |
---|
314 | 357 | /* Config space accessors. */ |
---|
315 | 358 | #define virtio_cwrite(vdev, structname, member, ptr) \ |
---|
316 | 359 | do { \ |
---|
317 | | - /* Must match the member's type, and be integer */ \ |
---|
318 | | - if (!typecheck(typeof((((structname*)0)->member)), *(ptr))) \ |
---|
319 | | - BUG_ON((*ptr) == 1); \ |
---|
| 360 | + typeof(((structname*)0)->member) virtio_cwrite_v = \ |
---|
| 361 | + cpu_to_virtio(vdev, *(ptr), ((structname*)0)->member); \ |
---|
320 | 362 | \ |
---|
321 | | - switch (sizeof(*ptr)) { \ |
---|
| 363 | + might_sleep(); \ |
---|
| 364 | + /* Sanity check: must match the member's type */ \ |
---|
| 365 | + typecheck(typeof(virtio_to_cpu((vdev), virtio_cwrite_v)), *(ptr)); \ |
---|
| 366 | + \ |
---|
| 367 | + vdev->config->set((vdev), offsetof(structname, member), \ |
---|
| 368 | + &virtio_cwrite_v, \ |
---|
| 369 | + sizeof(virtio_cwrite_v)); \ |
---|
| 370 | + } while(0) |
---|
| 371 | + |
---|
| 372 | +/* |
---|
| 373 | + * Nothing virtio-specific about these, but let's worry about generalizing |
---|
| 374 | + * these later. |
---|
| 375 | + */ |
---|
| 376 | +#define virtio_le_to_cpu(x) \ |
---|
| 377 | + _Generic((x), \ |
---|
| 378 | + __u8: (u8)(x), \ |
---|
| 379 | + __le16: (u16)le16_to_cpu(x), \ |
---|
| 380 | + __le32: (u32)le32_to_cpu(x), \ |
---|
| 381 | + __le64: (u64)le64_to_cpu(x) \ |
---|
| 382 | + ) |
---|
| 383 | + |
---|
| 384 | +#define virtio_cpu_to_le(x, m) \ |
---|
| 385 | + _Generic((m), \ |
---|
| 386 | + __u8: (x), \ |
---|
| 387 | + __le16: cpu_to_le16(x), \ |
---|
| 388 | + __le32: cpu_to_le32(x), \ |
---|
| 389 | + __le64: cpu_to_le64(x) \ |
---|
| 390 | + ) |
---|
| 391 | + |
---|
| 392 | +/* LE (e.g. modern) Config space accessors. */ |
---|
| 393 | +#define virtio_cread_le(vdev, structname, member, ptr) \ |
---|
| 394 | + do { \ |
---|
| 395 | + typeof(((structname*)0)->member) virtio_cread_v; \ |
---|
| 396 | + \ |
---|
| 397 | + might_sleep(); \ |
---|
| 398 | + /* Sanity check: must match the member's type */ \ |
---|
| 399 | + typecheck(typeof(virtio_le_to_cpu(virtio_cread_v)), *(ptr)); \ |
---|
| 400 | + \ |
---|
| 401 | + switch (sizeof(virtio_cread_v)) { \ |
---|
322 | 402 | case 1: \ |
---|
323 | | - virtio_cwrite8(vdev, \ |
---|
324 | | - offsetof(structname, member), \ |
---|
325 | | - *(ptr)); \ |
---|
326 | | - break; \ |
---|
327 | 403 | case 2: \ |
---|
328 | | - virtio_cwrite16(vdev, \ |
---|
329 | | - offsetof(structname, member), \ |
---|
330 | | - *(ptr)); \ |
---|
331 | | - break; \ |
---|
332 | 404 | case 4: \ |
---|
333 | | - virtio_cwrite32(vdev, \ |
---|
334 | | - offsetof(structname, member), \ |
---|
335 | | - *(ptr)); \ |
---|
336 | | - break; \ |
---|
337 | | - case 8: \ |
---|
338 | | - virtio_cwrite64(vdev, \ |
---|
339 | | - offsetof(structname, member), \ |
---|
340 | | - *(ptr)); \ |
---|
| 405 | + vdev->config->get((vdev), \ |
---|
| 406 | + offsetof(structname, member), \ |
---|
| 407 | + &virtio_cread_v, \ |
---|
| 408 | + sizeof(virtio_cread_v)); \ |
---|
341 | 409 | break; \ |
---|
342 | 410 | default: \ |
---|
343 | | - BUG(); \ |
---|
| 411 | + __virtio_cread_many((vdev), \ |
---|
| 412 | + offsetof(structname, member), \ |
---|
| 413 | + &virtio_cread_v, \ |
---|
| 414 | + 1, \ |
---|
| 415 | + sizeof(virtio_cread_v)); \ |
---|
| 416 | + break; \ |
---|
344 | 417 | } \ |
---|
| 418 | + *(ptr) = virtio_le_to_cpu(virtio_cread_v); \ |
---|
345 | 419 | } while(0) |
---|
| 420 | + |
---|
| 421 | +#define virtio_cwrite_le(vdev, structname, member, ptr) \ |
---|
| 422 | + do { \ |
---|
| 423 | + typeof(((structname*)0)->member) virtio_cwrite_v = \ |
---|
| 424 | + virtio_cpu_to_le(*(ptr), ((structname*)0)->member); \ |
---|
| 425 | + \ |
---|
| 426 | + might_sleep(); \ |
---|
| 427 | + /* Sanity check: must match the member's type */ \ |
---|
| 428 | + typecheck(typeof(virtio_le_to_cpu(virtio_cwrite_v)), *(ptr)); \ |
---|
| 429 | + \ |
---|
| 430 | + vdev->config->set((vdev), offsetof(structname, member), \ |
---|
| 431 | + &virtio_cwrite_v, \ |
---|
| 432 | + sizeof(virtio_cwrite_v)); \ |
---|
| 433 | + } while(0) |
---|
| 434 | + |
---|
346 | 435 | |
---|
347 | 436 | /* Read @count fields, @bytes each. */ |
---|
348 | 437 | static inline void __virtio_cread_many(struct virtio_device *vdev, |
---|
.. | .. |
---|
353 | 442 | vdev->config->generation(vdev) : 0; |
---|
354 | 443 | int i; |
---|
355 | 444 | |
---|
| 445 | + might_sleep(); |
---|
356 | 446 | do { |
---|
357 | 447 | old = gen; |
---|
358 | 448 | |
---|
.. | .. |
---|
375 | 465 | static inline u8 virtio_cread8(struct virtio_device *vdev, unsigned int offset) |
---|
376 | 466 | { |
---|
377 | 467 | u8 ret; |
---|
| 468 | + |
---|
| 469 | + might_sleep(); |
---|
378 | 470 | vdev->config->get(vdev, offset, &ret, sizeof(ret)); |
---|
379 | 471 | return ret; |
---|
380 | 472 | } |
---|
.. | .. |
---|
382 | 474 | static inline void virtio_cwrite8(struct virtio_device *vdev, |
---|
383 | 475 | unsigned int offset, u8 val) |
---|
384 | 476 | { |
---|
| 477 | + might_sleep(); |
---|
385 | 478 | vdev->config->set(vdev, offset, &val, sizeof(val)); |
---|
386 | 479 | } |
---|
387 | 480 | |
---|
388 | 481 | static inline u16 virtio_cread16(struct virtio_device *vdev, |
---|
389 | 482 | unsigned int offset) |
---|
390 | 483 | { |
---|
391 | | - u16 ret; |
---|
| 484 | + __virtio16 ret; |
---|
| 485 | + |
---|
| 486 | + might_sleep(); |
---|
392 | 487 | vdev->config->get(vdev, offset, &ret, sizeof(ret)); |
---|
393 | | - return virtio16_to_cpu(vdev, (__force __virtio16)ret); |
---|
| 488 | + return virtio16_to_cpu(vdev, ret); |
---|
394 | 489 | } |
---|
395 | 490 | |
---|
396 | 491 | static inline void virtio_cwrite16(struct virtio_device *vdev, |
---|
397 | 492 | unsigned int offset, u16 val) |
---|
398 | 493 | { |
---|
399 | | - val = (__force u16)cpu_to_virtio16(vdev, val); |
---|
400 | | - vdev->config->set(vdev, offset, &val, sizeof(val)); |
---|
| 494 | + __virtio16 v; |
---|
| 495 | + |
---|
| 496 | + might_sleep(); |
---|
| 497 | + v = cpu_to_virtio16(vdev, val); |
---|
| 498 | + vdev->config->set(vdev, offset, &v, sizeof(v)); |
---|
401 | 499 | } |
---|
402 | 500 | |
---|
403 | 501 | static inline u32 virtio_cread32(struct virtio_device *vdev, |
---|
404 | 502 | unsigned int offset) |
---|
405 | 503 | { |
---|
406 | | - u32 ret; |
---|
| 504 | + __virtio32 ret; |
---|
| 505 | + |
---|
| 506 | + might_sleep(); |
---|
407 | 507 | vdev->config->get(vdev, offset, &ret, sizeof(ret)); |
---|
408 | | - return virtio32_to_cpu(vdev, (__force __virtio32)ret); |
---|
| 508 | + return virtio32_to_cpu(vdev, ret); |
---|
409 | 509 | } |
---|
410 | 510 | |
---|
411 | 511 | static inline void virtio_cwrite32(struct virtio_device *vdev, |
---|
412 | 512 | unsigned int offset, u32 val) |
---|
413 | 513 | { |
---|
414 | | - val = (__force u32)cpu_to_virtio32(vdev, val); |
---|
415 | | - vdev->config->set(vdev, offset, &val, sizeof(val)); |
---|
| 514 | + __virtio32 v; |
---|
| 515 | + |
---|
| 516 | + might_sleep(); |
---|
| 517 | + v = cpu_to_virtio32(vdev, val); |
---|
| 518 | + vdev->config->set(vdev, offset, &v, sizeof(v)); |
---|
416 | 519 | } |
---|
417 | 520 | |
---|
418 | 521 | static inline u64 virtio_cread64(struct virtio_device *vdev, |
---|
419 | 522 | unsigned int offset) |
---|
420 | 523 | { |
---|
421 | | - u64 ret; |
---|
| 524 | + __virtio64 ret; |
---|
| 525 | + |
---|
422 | 526 | __virtio_cread_many(vdev, offset, &ret, 1, sizeof(ret)); |
---|
423 | | - return virtio64_to_cpu(vdev, (__force __virtio64)ret); |
---|
| 527 | + return virtio64_to_cpu(vdev, ret); |
---|
424 | 528 | } |
---|
425 | 529 | |
---|
426 | 530 | static inline void virtio_cwrite64(struct virtio_device *vdev, |
---|
427 | 531 | unsigned int offset, u64 val) |
---|
428 | 532 | { |
---|
429 | | - val = (__force u64)cpu_to_virtio64(vdev, val); |
---|
430 | | - vdev->config->set(vdev, offset, &val, sizeof(val)); |
---|
| 533 | + __virtio64 v; |
---|
| 534 | + |
---|
| 535 | + might_sleep(); |
---|
| 536 | + v = cpu_to_virtio64(vdev, val); |
---|
| 537 | + vdev->config->set(vdev, offset, &v, sizeof(v)); |
---|
431 | 538 | } |
---|
432 | 539 | |
---|
433 | 540 | /* Conditional config space accessors. */ |
---|
.. | .. |
---|
441 | 548 | _r; \ |
---|
442 | 549 | }) |
---|
443 | 550 | |
---|
| 551 | +/* Conditional config space accessors. */ |
---|
| 552 | +#define virtio_cread_le_feature(vdev, fbit, structname, member, ptr) \ |
---|
| 553 | + ({ \ |
---|
| 554 | + int _r = 0; \ |
---|
| 555 | + if (!virtio_has_feature(vdev, fbit)) \ |
---|
| 556 | + _r = -ENOENT; \ |
---|
| 557 | + else \ |
---|
| 558 | + virtio_cread_le((vdev), structname, member, ptr); \ |
---|
| 559 | + _r; \ |
---|
| 560 | + }) |
---|
| 561 | + |
---|
| 562 | +#ifdef CONFIG_ARCH_HAS_RESTRICTED_VIRTIO_MEMORY_ACCESS |
---|
| 563 | +int arch_has_restricted_virtio_memory_access(void); |
---|
| 564 | +#else |
---|
| 565 | +static inline int arch_has_restricted_virtio_memory_access(void) |
---|
| 566 | +{ |
---|
| 567 | + return 0; |
---|
| 568 | +} |
---|
| 569 | +#endif /* CONFIG_ARCH_HAS_RESTRICTED_VIRTIO_MEMORY_ACCESS */ |
---|
| 570 | + |
---|
444 | 571 | #endif /* _LINUX_VIRTIO_CONFIG_H */ |
---|