Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 | /* SPDX-License-Identifier: GPL-2.0-only */ /* * VMware VMCI Driver * * Copyright (C) 2012 VMware, Inc. All rights reserved. */ #ifndef _VMW_VMCI_DEF_H_ #define _VMW_VMCI_DEF_H_ #include <linux/atomic.h> #include <linux/bits.h> /* Register offsets. */ #define VMCI_STATUS_ADDR 0x00 #define VMCI_CONTROL_ADDR 0x04 #define VMCI_ICR_ADDR 0x08 #define VMCI_IMR_ADDR 0x0c #define VMCI_DATA_OUT_ADDR 0x10 #define VMCI_DATA_IN_ADDR 0x14 #define VMCI_CAPS_ADDR 0x18 #define VMCI_RESULT_LOW_ADDR 0x1c #define VMCI_RESULT_HIGH_ADDR 0x20 #define VMCI_DATA_OUT_LOW_ADDR 0x24 #define VMCI_DATA_OUT_HIGH_ADDR 0x28 #define VMCI_DATA_IN_LOW_ADDR 0x2c #define VMCI_DATA_IN_HIGH_ADDR 0x30 #define VMCI_GUEST_PAGE_SHIFT 0x34 /* Max number of devices. */ #define VMCI_MAX_DEVICES 1 /* Status register bits. */ #define VMCI_STATUS_INT_ON BIT(0) /* Control register bits. */ #define VMCI_CONTROL_RESET BIT(0) #define VMCI_CONTROL_INT_ENABLE BIT(1) #define VMCI_CONTROL_INT_DISABLE BIT(2) /* Capabilities register bits. */ #define VMCI_CAPS_HYPERCALL BIT(0) #define VMCI_CAPS_GUESTCALL BIT(1) #define VMCI_CAPS_DATAGRAM BIT(2) #define VMCI_CAPS_NOTIFICATIONS BIT(3) #define VMCI_CAPS_PPN64 BIT(4) #define VMCI_CAPS_DMA_DATAGRAM BIT(5) /* Interrupt Cause register bits. */ #define VMCI_ICR_DATAGRAM BIT(0) #define VMCI_ICR_NOTIFICATION BIT(1) #define VMCI_ICR_DMA_DATAGRAM BIT(2) /* Interrupt Mask register bits. */ #define VMCI_IMR_DATAGRAM BIT(0) #define VMCI_IMR_NOTIFICATION BIT(1) #define VMCI_IMR_DMA_DATAGRAM BIT(2) /* * Maximum MSI/MSI-X interrupt vectors in the device. * If VMCI_CAPS_DMA_DATAGRAM is supported by the device, * VMCI_MAX_INTRS_DMA_DATAGRAM vectors are available, * otherwise only VMCI_MAX_INTRS_NOTIFICATION. */ #define VMCI_MAX_INTRS_NOTIFICATION 2 #define VMCI_MAX_INTRS_DMA_DATAGRAM 3 #define VMCI_MAX_INTRS VMCI_MAX_INTRS_DMA_DATAGRAM /* * Supported interrupt vectors. There is one for each ICR value above, * but here they indicate the position in the vector array/message ID. */ enum { VMCI_INTR_DATAGRAM = 0, VMCI_INTR_NOTIFICATION = 1, VMCI_INTR_DMA_DATAGRAM = 2, }; /* * A single VMCI device has an upper limit of 128MB on the amount of * memory that can be used for queue pairs. Since each queue pair * consists of at least two pages, the memory limit also dictates the * number of queue pairs a guest can create. */ #define VMCI_MAX_GUEST_QP_MEMORY ((size_t)(128 * 1024 * 1024)) #define VMCI_MAX_GUEST_QP_COUNT (VMCI_MAX_GUEST_QP_MEMORY / PAGE_SIZE / 2) /* * There can be at most PAGE_SIZE doorbells since there is one doorbell * per byte in the doorbell bitmap page. */ #define VMCI_MAX_GUEST_DOORBELL_COUNT PAGE_SIZE /* * Queues with pre-mapped data pages must be small, so that we don't pin * too much kernel memory (especially on vmkernel). We limit a queuepair to * 32 KB, or 16 KB per queue for symmetrical pairs. */ #define VMCI_MAX_PINNED_QP_MEMORY ((size_t)(32 * 1024)) /* * The version of the VMCI device that supports MMIO access to registers * requests 256KB for BAR1 whereas the version of VMCI that supports * MSI/MSI-X only requests 8KB. The layout of the larger 256KB region is: * - the first 128KB are used for MSI/MSI-X. * - the following 64KB are used for MMIO register access. * - the remaining 64KB are unused. */ #define VMCI_WITH_MMIO_ACCESS_BAR_SIZE ((size_t)(256 * 1024)) #define VMCI_MMIO_ACCESS_OFFSET ((size_t)(128 * 1024)) #define VMCI_MMIO_ACCESS_SIZE ((size_t)(64 * 1024)) /* * For VMCI devices supporting the VMCI_CAPS_DMA_DATAGRAM capability, the * sending and receiving of datagrams can be performed using DMA to/from * a driver allocated buffer. * Sending and receiving will be handled as follows: * - when sending datagrams, the driver initializes the buffer where the * data part will refer to the outgoing VMCI datagram, sets the busy flag * to 1 and writes the address of the buffer to VMCI_DATA_OUT_HIGH_ADDR * and VMCI_DATA_OUT_LOW_ADDR. Writing to VMCI_DATA_OUT_LOW_ADDR triggers * the device processing of the buffer. When the device has processed the * buffer, it will write the result value to the buffer and then clear the * busy flag. * - when receiving datagrams, the driver initializes the buffer where the * data part will describe the receive buffer, clears the busy flag and * writes the address of the buffer to VMCI_DATA_IN_HIGH_ADDR and * VMCI_DATA_IN_LOW_ADDR. Writing to VMCI_DATA_IN_LOW_ADDR triggers the * device processing of the buffer. The device will copy as many available * datagrams into the buffer as possible, and then sets the busy flag. * When the busy flag is set, the driver will process the datagrams in the * buffer. */ struct vmci_data_in_out_header { uint32_t busy; uint32_t opcode; uint32_t size; uint32_t rsvd; uint64_t result; }; struct vmci_sg_elem { uint64_t addr; uint64_t size; }; /* * We have a fixed set of resource IDs available in the VMX. * This allows us to have a very simple implementation since we statically * know how many will create datagram handles. If a new caller arrives and * we have run out of slots we can manually increment the maximum size of * available resource IDs. * * VMCI reserved hypervisor datagram resource IDs. */ enum { VMCI_RESOURCES_QUERY = 0, VMCI_GET_CONTEXT_ID = 1, VMCI_SET_NOTIFY_BITMAP = 2, VMCI_DOORBELL_LINK = 3, VMCI_DOORBELL_UNLINK = 4, VMCI_DOORBELL_NOTIFY = 5, /* * VMCI_DATAGRAM_REQUEST_MAP and VMCI_DATAGRAM_REMOVE_MAP are * obsoleted by the removal of VM to VM communication. */ VMCI_DATAGRAM_REQUEST_MAP = 6, VMCI_DATAGRAM_REMOVE_MAP = 7, VMCI_EVENT_SUBSCRIBE = 8, VMCI_EVENT_UNSUBSCRIBE = 9, VMCI_QUEUEPAIR_ALLOC = 10, VMCI_QUEUEPAIR_DETACH = 11, /* * VMCI_VSOCK_VMX_LOOKUP was assigned to 12 for Fusion 3.0/3.1, * WS 7.0/7.1 and ESX 4.1 */ VMCI_HGFS_TRANSPORT = 13, VMCI_UNITY_PBRPC_REGISTER = 14, VMCI_RPC_PRIVILEGED = 15, VMCI_RPC_UNPRIVILEGED = 16, VMCI_RESOURCE_MAX = 17, }; /* * struct vmci_handle - Ownership information structure * @context: The VMX context ID. * @resource: The resource ID (used for locating in resource hash). * * The vmci_handle structure is used to track resources used within * vmw_vmci. */ struct vmci_handle { u32 context; u32 resource; }; #define vmci_make_handle(_cid, _rid) \ (struct vmci_handle){ .context = _cid, .resource = _rid } static inline bool vmci_handle_is_equal(struct vmci_handle h1, struct vmci_handle h2) { return h1.context == h2.context && h1.resource == h2.resource; } #define VMCI_INVALID_ID ~0 static const struct vmci_handle VMCI_INVALID_HANDLE = { .context = VMCI_INVALID_ID, .resource = VMCI_INVALID_ID }; static inline bool vmci_handle_is_invalid(struct vmci_handle h) { return vmci_handle_is_equal(h, VMCI_INVALID_HANDLE); } /* * The below defines can be used to send anonymous requests. * This also indicates that no response is expected. */ #define VMCI_ANON_SRC_CONTEXT_ID VMCI_INVALID_ID #define VMCI_ANON_SRC_RESOURCE_ID VMCI_INVALID_ID static const struct vmci_handle __maybe_unused VMCI_ANON_SRC_HANDLE = { .context = VMCI_ANON_SRC_CONTEXT_ID, .resource = VMCI_ANON_SRC_RESOURCE_ID }; /* The lowest 16 context ids are reserved for internal use. */ #define VMCI_RESERVED_CID_LIMIT ((u32) 16) /* * Hypervisor context id, used for calling into hypervisor * supplied services from the VM. */ #define VMCI_HYPERVISOR_CONTEXT_ID 0 /* * Well-known context id, a logical context that contains a set of * well-known services. This context ID is now obsolete. */ #define VMCI_WELL_KNOWN_CONTEXT_ID 1 /* * Context ID used by host endpoints. */ #define VMCI_HOST_CONTEXT_ID 2 #define VMCI_CONTEXT_IS_VM(_cid) (VMCI_INVALID_ID != (_cid) && \ (_cid) > VMCI_HOST_CONTEXT_ID) /* * The VMCI_CONTEXT_RESOURCE_ID is used together with vmci_make_handle to make * handles that refer to a specific context. */ #define VMCI_CONTEXT_RESOURCE_ID 0 /* * VMCI error codes. */ enum { VMCI_SUCCESS_QUEUEPAIR_ATTACH = 5, VMCI_SUCCESS_QUEUEPAIR_CREATE = 4, VMCI_SUCCESS_LAST_DETACH = 3, VMCI_SUCCESS_ACCESS_GRANTED = 2, VMCI_SUCCESS_ENTRY_DEAD = 1, VMCI_SUCCESS = 0, VMCI_ERROR_INVALID_RESOURCE = (-1), VMCI_ERROR_INVALID_ARGS = (-2), VMCI_ERROR_NO_MEM = (-3), VMCI_ERROR_DATAGRAM_FAILED = (-4), VMCI_ERROR_MORE_DATA = (-5), VMCI_ERROR_NO_MORE_DATAGRAMS = (-6), VMCI_ERROR_NO_ACCESS = (-7), VMCI_ERROR_NO_HANDLE = (-8), VMCI_ERROR_DUPLICATE_ENTRY = (-9), VMCI_ERROR_DST_UNREACHABLE = (-10), VMCI_ERROR_PAYLOAD_TOO_LARGE = (-11), VMCI_ERROR_INVALID_PRIV = (-12), VMCI_ERROR_GENERIC = (-13), VMCI_ERROR_PAGE_ALREADY_SHARED = (-14), VMCI_ERROR_CANNOT_SHARE_PAGE = (-15), VMCI_ERROR_CANNOT_UNSHARE_PAGE = (-16), VMCI_ERROR_NO_PROCESS = (-17), VMCI_ERROR_NO_DATAGRAM = (-18), VMCI_ERROR_NO_RESOURCES = (-19), VMCI_ERROR_UNAVAILABLE = (-20), VMCI_ERROR_NOT_FOUND = (-21), VMCI_ERROR_ALREADY_EXISTS = (-22), VMCI_ERROR_NOT_PAGE_ALIGNED = (-23), VMCI_ERROR_INVALID_SIZE = (-24), VMCI_ERROR_REGION_ALREADY_SHARED = (-25), VMCI_ERROR_TIMEOUT = (-26), VMCI_ERROR_DATAGRAM_INCOMPLETE = (-27), VMCI_ERROR_INCORRECT_IRQL = (-28), VMCI_ERROR_EVENT_UNKNOWN = (-29), VMCI_ERROR_OBSOLETE = (-30), VMCI_ERROR_QUEUEPAIR_MISMATCH = (-31), VMCI_ERROR_QUEUEPAIR_NOTSET = (-32), VMCI_ERROR_QUEUEPAIR_NOTOWNER = (-33), VMCI_ERROR_QUEUEPAIR_NOTATTACHED = (-34), VMCI_ERROR_QUEUEPAIR_NOSPACE = (-35), VMCI_ERROR_QUEUEPAIR_NODATA = (-36), VMCI_ERROR_BUSMEM_INVALIDATION = (-37), VMCI_ERROR_MODULE_NOT_LOADED = (-38), VMCI_ERROR_DEVICE_NOT_FOUND = (-39), VMCI_ERROR_QUEUEPAIR_NOT_READY = (-40), VMCI_ERROR_WOULD_BLOCK = (-41), /* VMCI clients should return error code within this range */ VMCI_ERROR_CLIENT_MIN = (-500), VMCI_ERROR_CLIENT_MAX = (-550), /* Internal error codes. */ VMCI_SHAREDMEM_ERROR_BAD_CONTEXT = (-1000), }; /* VMCI reserved events. */ enum { /* Only applicable to guest endpoints */ VMCI_EVENT_CTX_ID_UPDATE = 0, /* Applicable to guest and host */ VMCI_EVENT_CTX_REMOVED = 1, /* Only applicable to guest endpoints */ VMCI_EVENT_QP_RESUMED = 2, /* Applicable to guest and host */ VMCI_EVENT_QP_PEER_ATTACH = 3, /* Applicable to guest and host */ VMCI_EVENT_QP_PEER_DETACH = 4, /* * Applicable to VMX and vmk. On vmk, * this event has the Context payload type. */ VMCI_EVENT_MEM_ACCESS_ON = 5, /* * Applicable to VMX and vmk. Same as * above for the payload type. */ VMCI_EVENT_MEM_ACCESS_OFF = 6, VMCI_EVENT_MAX = 7, }; /* * Of the above events, a few are reserved for use in the VMX, and * other endpoints (guest and host kernel) should not use them. For * the rest of the events, we allow both host and guest endpoints to * subscribe to them, to maintain the same API for host and guest * endpoints. */ #define VMCI_EVENT_VALID_VMX(_event) ((_event) == VMCI_EVENT_MEM_ACCESS_ON || \ (_event) == VMCI_EVENT_MEM_ACCESS_OFF) #define VMCI_EVENT_VALID(_event) ((_event) < VMCI_EVENT_MAX && \ !VMCI_EVENT_VALID_VMX(_event)) /* Reserved guest datagram resource ids. */ #define VMCI_EVENT_HANDLER 0 /* * VMCI coarse-grained privileges (per context or host * process/endpoint. An entity with the restricted flag is only * allowed to interact with the hypervisor and trusted entities. */ enum { VMCI_NO_PRIVILEGE_FLAGS = 0, VMCI_PRIVILEGE_FLAG_RESTRICTED = 1, VMCI_PRIVILEGE_FLAG_TRUSTED = 2, VMCI_PRIVILEGE_ALL_FLAGS = (VMCI_PRIVILEGE_FLAG_RESTRICTED | VMCI_PRIVILEGE_FLAG_TRUSTED), VMCI_DEFAULT_PROC_PRIVILEGE_FLAGS = VMCI_NO_PRIVILEGE_FLAGS, VMCI_LEAST_PRIVILEGE_FLAGS = VMCI_PRIVILEGE_FLAG_RESTRICTED, VMCI_MAX_PRIVILEGE_FLAGS = VMCI_PRIVILEGE_FLAG_TRUSTED, }; /* 0 through VMCI_RESERVED_RESOURCE_ID_MAX are reserved. */ #define VMCI_RESERVED_RESOURCE_ID_MAX 1023 /* * Driver version. * * Increment major version when you make an incompatible change. * Compatibility goes both ways (old driver with new executable * as well as new driver with old executable). */ /* Never change VMCI_VERSION_SHIFT_WIDTH */ #define VMCI_VERSION_SHIFT_WIDTH 16 #define VMCI_MAKE_VERSION(_major, _minor) \ ((_major) << VMCI_VERSION_SHIFT_WIDTH | (u16) (_minor)) #define VMCI_VERSION_MAJOR(v) ((u32) (v) >> VMCI_VERSION_SHIFT_WIDTH) #define VMCI_VERSION_MINOR(v) ((u16) (v)) /* * VMCI_VERSION is always the current version. Subsequently listed * versions are ways of detecting previous versions of the connecting * application (i.e., VMX). * * VMCI_VERSION_NOVMVM: This version removed support for VM to VM * communication. * * VMCI_VERSION_NOTIFY: This version introduced doorbell notification * support. * * VMCI_VERSION_HOSTQP: This version introduced host end point support * for hosted products. * * VMCI_VERSION_PREHOSTQP: This is the version prior to the adoption of * support for host end-points. * * VMCI_VERSION_PREVERS2: This fictional version number is intended to * represent the version of a VMX which doesn't call into the driver * with ioctl VERSION2 and thus doesn't establish its version with the * driver. */ #define VMCI_VERSION VMCI_VERSION_NOVMVM #define VMCI_VERSION_NOVMVM VMCI_MAKE_VERSION(11, 0) #define VMCI_VERSION_NOTIFY VMCI_MAKE_VERSION(10, 0) #define VMCI_VERSION_HOSTQP VMCI_MAKE_VERSION(9, 0) #define VMCI_VERSION_PREHOSTQP VMCI_MAKE_VERSION(8, 0) #define VMCI_VERSION_PREVERS2 VMCI_MAKE_VERSION(1, 0) #define VMCI_SOCKETS_MAKE_VERSION(_p) \ ((((_p)[0] & 0xFF) << 24) | (((_p)[1] & 0xFF) << 16) | ((_p)[2])) /* * The VMCI IOCTLs. We use identity code 7, as noted in ioctl-number.h, and * we start at sequence 9f. This gives us the same values that our shipping * products use, starting at 1951, provided we leave out the direction and * structure size. Note that VMMon occupies the block following us, starting * at 2001. */ #define IOCTL_VMCI_VERSION _IO(7, 0x9f) /* 1951 */ #define IOCTL_VMCI_INIT_CONTEXT _IO(7, 0xa0) #define IOCTL_VMCI_QUEUEPAIR_SETVA _IO(7, 0xa4) #define IOCTL_VMCI_NOTIFY_RESOURCE _IO(7, 0xa5) #define IOCTL_VMCI_NOTIFICATIONS_RECEIVE _IO(7, 0xa6) #define IOCTL_VMCI_VERSION2 _IO(7, 0xa7) #define IOCTL_VMCI_QUEUEPAIR_ALLOC _IO(7, 0xa8) #define IOCTL_VMCI_QUEUEPAIR_SETPAGEFILE _IO(7, 0xa9) #define IOCTL_VMCI_QUEUEPAIR_DETACH _IO(7, 0xaa) #define IOCTL_VMCI_DATAGRAM_SEND _IO(7, 0xab) #define IOCTL_VMCI_DATAGRAM_RECEIVE _IO(7, 0xac) #define IOCTL_VMCI_CTX_ADD_NOTIFICATION _IO(7, 0xaf) #define IOCTL_VMCI_CTX_REMOVE_NOTIFICATION _IO(7, 0xb0) #define IOCTL_VMCI_CTX_GET_CPT_STATE _IO(7, 0xb1) #define IOCTL_VMCI_CTX_SET_CPT_STATE _IO(7, 0xb2) #define IOCTL_VMCI_GET_CONTEXT_ID _IO(7, 0xb3) #define IOCTL_VMCI_SOCKETS_VERSION _IO(7, 0xb4) #define IOCTL_VMCI_SOCKETS_GET_AF_VALUE _IO(7, 0xb8) #define IOCTL_VMCI_SOCKETS_GET_LOCAL_CID _IO(7, 0xb9) #define IOCTL_VMCI_SET_NOTIFY _IO(7, 0xcb) /* 1995 */ /*IOCTL_VMMON_START _IO(7, 0xd1)*/ /* 2001 */ /* * struct vmci_queue_header - VMCI Queue Header information. * * A Queue cannot stand by itself as designed. Each Queue's header * contains a pointer into itself (the producer_tail) and into its peer * (consumer_head). The reason for the separation is one of * accessibility: Each end-point can modify two things: where the next * location to enqueue is within its produce_q (producer_tail); and * where the next dequeue location is in its consume_q (consumer_head). * * An end-point cannot modify the pointers of its peer (guest to * guest; NOTE that in the host both queue headers are mapped r/w). * But, each end-point needs read access to both Queue header * structures in order to determine how much space is used (or left) * in the Queue. This is because for an end-point to know how full * its produce_q is, it needs to use the consumer_head that points into * the produce_q but -that- consumer_head is in the Queue header for * that end-points consume_q. * * Thoroughly confused? Sorry. * * producer_tail: the point to enqueue new entrants. When you approach * a line in a store, for example, you walk up to the tail. * * consumer_head: the point in the queue from which the next element is * dequeued. In other words, who is next in line is he who is at the * head of the line. * * Also, producer_tail points to an empty byte in the Queue, whereas * consumer_head points to a valid byte of data (unless producer_tail == * consumer_head in which case consumer_head does not point to a valid * byte of data). * * For a queue of buffer 'size' bytes, the tail and head pointers will be in * the range [0, size-1]. * * If produce_q_header->producer_tail == consume_q_header->consumer_head * then the produce_q is empty. */ struct vmci_queue_header { /* All fields are 64bit and aligned. */ struct vmci_handle handle; /* Identifier. */ u64 producer_tail; /* Offset in this queue. */ u64 consumer_head; /* Offset in peer queue. */ }; /* * struct vmci_datagram - Base struct for vmci datagrams. * @dst: A vmci_handle that tracks the destination of the datagram. * @src: A vmci_handle that tracks the source of the datagram. * @payload_size: The size of the payload. * * vmci_datagram structs are used when sending vmci datagrams. They include * the necessary source and destination information to properly route * the information along with the size of the package. */ struct vmci_datagram { struct vmci_handle dst; struct vmci_handle src; u64 payload_size; }; /* * Second flag is for creating a well-known handle instead of a per context * handle. Next flag is for deferring datagram delivery, so that the * datagram callback is invoked in a delayed context (not interrupt context). */ #define VMCI_FLAG_DG_NONE 0 #define VMCI_FLAG_WELLKNOWN_DG_HND BIT(0) #define VMCI_FLAG_ANYCID_DG_HND BIT(1) #define VMCI_FLAG_DG_DELAYED_CB BIT(2) /* * Maximum supported size of a VMCI datagram for routable datagrams. * Datagrams going to the hypervisor are allowed to be larger. */ #define VMCI_MAX_DG_SIZE (17 * 4096) #define VMCI_MAX_DG_PAYLOAD_SIZE (VMCI_MAX_DG_SIZE - \ sizeof(struct vmci_datagram)) #define VMCI_DG_PAYLOAD(_dg) (void *)((char *)(_dg) + \ sizeof(struct vmci_datagram)) #define VMCI_DG_HEADERSIZE sizeof(struct vmci_datagram) #define VMCI_DG_SIZE(_dg) (VMCI_DG_HEADERSIZE + (size_t)(_dg)->payload_size) #define VMCI_DG_SIZE_ALIGNED(_dg) ((VMCI_DG_SIZE(_dg) + 7) & (~((size_t) 0x7))) #define VMCI_MAX_DATAGRAM_QUEUE_SIZE (VMCI_MAX_DG_SIZE * 2) struct vmci_event_payload_qp { struct vmci_handle handle; /* queue_pair handle. */ u32 peer_id; /* Context id of attaching/detaching VM. */ u32 _pad; }; /* Flags for VMCI queue_pair API. */ enum { /* Fail alloc if QP not created by peer. */ VMCI_QPFLAG_ATTACH_ONLY = 1 << 0, /* Only allow attaches from local context. */ VMCI_QPFLAG_LOCAL = 1 << 1, /* Host won't block when guest is quiesced. */ VMCI_QPFLAG_NONBLOCK = 1 << 2, /* Pin data pages in ESX. Used with NONBLOCK */ VMCI_QPFLAG_PINNED = 1 << 3, /* Update the following flag when adding new flags. */ VMCI_QP_ALL_FLAGS = (VMCI_QPFLAG_ATTACH_ONLY | VMCI_QPFLAG_LOCAL | VMCI_QPFLAG_NONBLOCK | VMCI_QPFLAG_PINNED), /* Convenience flags */ VMCI_QP_ASYMM = (VMCI_QPFLAG_NONBLOCK | VMCI_QPFLAG_PINNED), VMCI_QP_ASYMM_PEER = (VMCI_QPFLAG_ATTACH_ONLY | VMCI_QP_ASYMM), }; /* * We allow at least 1024 more event datagrams from the hypervisor past the * normally allowed datagrams pending for a given context. We define this * limit on event datagrams from the hypervisor to guard against DoS attack * from a malicious VM which could repeatedly attach to and detach from a queue * pair, causing events to be queued at the destination VM. However, the rate * at which such events can be generated is small since it requires a VM exit * and handling of queue pair attach/detach call at the hypervisor. Event * datagrams may be queued up at the destination VM if it has interrupts * disabled or if it is not draining events for some other reason. 1024 * datagrams is a grossly conservative estimate of the time for which * interrupts may be disabled in the destination VM, but at the same time does * not exacerbate the memory pressure problem on the host by much (size of each * event datagram is small). */ #define VMCI_MAX_DATAGRAM_AND_EVENT_QUEUE_SIZE \ (VMCI_MAX_DATAGRAM_QUEUE_SIZE + \ 1024 * (sizeof(struct vmci_datagram) + \ sizeof(struct vmci_event_data_max))) /* * Struct used for querying, via VMCI_RESOURCES_QUERY, the availability of * hypervisor resources. Struct size is 16 bytes. All fields in struct are * aligned to their natural alignment. */ struct vmci_resource_query_hdr { struct vmci_datagram hdr; u32 num_resources; u32 _padding; }; /* * Convenience struct for negotiating vectors. Must match layout of * VMCIResourceQueryHdr minus the struct vmci_datagram header. */ struct vmci_resource_query_msg { u32 num_resources; u32 _padding; u32 resources[1]; }; /* * The maximum number of resources that can be queried using * VMCI_RESOURCE_QUERY is 31, as the result is encoded in the lower 31 * bits of a positive return value. Negative values are reserved for * errors. */ #define VMCI_RESOURCE_QUERY_MAX_NUM 31 /* Maximum size for the VMCI_RESOURCE_QUERY request. */ #define VMCI_RESOURCE_QUERY_MAX_SIZE \ (sizeof(struct vmci_resource_query_hdr) + \ sizeof(u32) * VMCI_RESOURCE_QUERY_MAX_NUM) /* * Struct used for setting the notification bitmap. All fields in * struct are aligned to their natural alignment. */ struct vmci_notify_bm_set_msg { struct vmci_datagram hdr; union { u32 bitmap_ppn32; u64 bitmap_ppn64; }; }; /* * Struct used for linking a doorbell handle with an index in the * notify bitmap. All fields in struct are aligned to their natural * alignment. */ struct vmci_doorbell_link_msg { struct vmci_datagram hdr; struct vmci_handle handle; u64 notify_idx; }; /* * Struct used for unlinking a doorbell handle from an index in the * notify bitmap. All fields in struct are aligned to their natural * alignment. */ struct vmci_doorbell_unlink_msg { struct vmci_datagram hdr; struct vmci_handle handle; }; /* * Struct used for generating a notification on a doorbell handle. All * fields in struct are aligned to their natural alignment. */ struct vmci_doorbell_notify_msg { struct vmci_datagram hdr; struct vmci_handle handle; }; /* * This struct is used to contain data for events. Size of this struct is a * multiple of 8 bytes, and all fields are aligned to their natural alignment. */ struct vmci_event_data { u32 event; /* 4 bytes. */ u32 _pad; /* Event payload is put here. */ }; /* * Define the different VMCI_EVENT payload data types here. All structs must * be a multiple of 8 bytes, and fields must be aligned to their natural * alignment. */ struct vmci_event_payld_ctx { u32 context_id; /* 4 bytes. */ u32 _pad; }; struct vmci_event_payld_qp { struct vmci_handle handle; /* queue_pair handle. */ u32 peer_id; /* Context id of attaching/detaching VM. */ u32 _pad; }; /* * We define the following struct to get the size of the maximum event * data the hypervisor may send to the guest. If adding a new event * payload type above, add it to the following struct too (inside the * union). */ struct vmci_event_data_max { struct vmci_event_data event_data; union { struct vmci_event_payld_ctx context_payload; struct vmci_event_payld_qp qp_payload; } ev_data_payload; }; /* * Struct used for VMCI_EVENT_SUBSCRIBE/UNSUBSCRIBE and * VMCI_EVENT_HANDLER messages. Struct size is 32 bytes. All fields * in struct are aligned to their natural alignment. */ struct vmci_event_msg { struct vmci_datagram hdr; /* Has event type and payload. */ struct vmci_event_data event_data; /* Payload gets put here. */ }; /* Event with context payload. */ struct vmci_event_ctx { struct vmci_event_msg msg; struct vmci_event_payld_ctx payload; }; /* Event with QP payload. */ struct vmci_event_qp { struct vmci_event_msg msg; struct vmci_event_payld_qp payload; }; /* * Structs used for queue_pair alloc and detach messages. We align fields of * these structs to 64bit boundaries. */ struct vmci_qp_alloc_msg { struct vmci_datagram hdr; struct vmci_handle handle; u32 peer; u32 flags; u64 produce_size; u64 consume_size; u64 num_ppns; /* List of PPNs placed here. */ }; struct vmci_qp_detach_msg { struct vmci_datagram hdr; struct vmci_handle handle; }; /* VMCI Doorbell API. */ #define VMCI_FLAG_DELAYED_CB BIT(0) typedef void (*vmci_callback) (void *client_data); /* * struct vmci_qp - A vmw_vmci queue pair handle. * * This structure is used as a handle to a queue pair created by * VMCI. It is intentionally left opaque to clients. */ struct vmci_qp; /* Callback needed for correctly waiting on events. */ typedef int (*vmci_datagram_recv_cb) (void *client_data, struct vmci_datagram *msg); /* VMCI Event API. */ typedef void (*vmci_event_cb) (u32 sub_id, const struct vmci_event_data *ed, void *client_data); /* * We use the following inline function to access the payload data * associated with an event data. */ static inline const void * vmci_event_data_const_payload(const struct vmci_event_data *ev_data) { return (const char *)ev_data + sizeof(*ev_data); } static inline void *vmci_event_data_payload(struct vmci_event_data *ev_data) { return (void *)vmci_event_data_const_payload(ev_data); } /* * Helper to read a value from a head or tail pointer. For X86_32, the * pointer is treated as a 32bit value, since the pointer value * never exceeds a 32bit value in this case. Also, doing an * atomic64_read on X86_32 uniprocessor systems may be implemented * as a non locked cmpxchg8b, that may end up overwriting updates done * by the VMCI device to the memory location. On 32bit SMP, the lock * prefix will be used, so correctness isn't an issue, but using a * 64bit operation still adds unnecessary overhead. */ static inline u64 vmci_q_read_pointer(u64 *var) { return READ_ONCE(*(unsigned long *)var); } /* * Helper to set the value of a head or tail pointer. For X86_32, the * pointer is treated as a 32bit value, since the pointer value * never exceeds a 32bit value in this case. On 32bit SMP, using a * locked cmpxchg8b adds unnecessary overhead. */ static inline void vmci_q_set_pointer(u64 *var, u64 new_val) { /* XXX buggered on big-endian */ WRITE_ONCE(*(unsigned long *)var, (unsigned long)new_val); } /* * Helper to add a given offset to a head or tail pointer. Wraps the * value of the pointer around the max size of the queue. */ static inline void vmci_qp_add_pointer(u64 *var, size_t add, u64 size) { u64 new_val = vmci_q_read_pointer(var); if (new_val >= size - add) new_val -= size; new_val += add; vmci_q_set_pointer(var, new_val); } /* * Helper routine to get the Producer Tail from the supplied queue. */ static inline u64 vmci_q_header_producer_tail(const struct vmci_queue_header *q_header) { struct vmci_queue_header *qh = (struct vmci_queue_header *)q_header; return vmci_q_read_pointer(&qh->producer_tail); } /* * Helper routine to get the Consumer Head from the supplied queue. */ static inline u64 vmci_q_header_consumer_head(const struct vmci_queue_header *q_header) { struct vmci_queue_header *qh = (struct vmci_queue_header *)q_header; return vmci_q_read_pointer(&qh->consumer_head); } /* * Helper routine to increment the Producer Tail. Fundamentally, * vmci_qp_add_pointer() is used to manipulate the tail itself. */ static inline void vmci_q_header_add_producer_tail(struct vmci_queue_header *q_header, size_t add, u64 queue_size) { vmci_qp_add_pointer(&q_header->producer_tail, add, queue_size); } /* * Helper routine to increment the Consumer Head. Fundamentally, * vmci_qp_add_pointer() is used to manipulate the head itself. */ static inline void vmci_q_header_add_consumer_head(struct vmci_queue_header *q_header, size_t add, u64 queue_size) { vmci_qp_add_pointer(&q_header->consumer_head, add, queue_size); } /* * Helper routine for getting the head and the tail pointer for a queue. * Both the VMCIQueues are needed to get both the pointers for one queue. */ static inline void vmci_q_header_get_pointers(const struct vmci_queue_header *produce_q_header, const struct vmci_queue_header *consume_q_header, u64 *producer_tail, u64 *consumer_head) { if (producer_tail) *producer_tail = vmci_q_header_producer_tail(produce_q_header); if (consumer_head) *consumer_head = vmci_q_header_consumer_head(consume_q_header); } static inline void vmci_q_header_init(struct vmci_queue_header *q_header, const struct vmci_handle handle) { q_header->handle = handle; q_header->producer_tail = 0; q_header->consumer_head = 0; } /* * Finds available free space in a produce queue to enqueue more * data or reports an error if queue pair corruption is detected. */ static s64 vmci_q_header_free_space(const struct vmci_queue_header *produce_q_header, const struct vmci_queue_header *consume_q_header, const u64 produce_q_size) { u64 tail; u64 head; u64 free_space; tail = vmci_q_header_producer_tail(produce_q_header); head = vmci_q_header_consumer_head(consume_q_header); if (tail >= produce_q_size || head >= produce_q_size) return VMCI_ERROR_INVALID_SIZE; /* * Deduct 1 to avoid tail becoming equal to head which causes * ambiguity. If head and tail are equal it means that the * queue is empty. */ if (tail >= head) free_space = produce_q_size - (tail - head) - 1; else free_space = head - tail - 1; return free_space; } /* * vmci_q_header_free_space() does all the heavy lifting of * determing the number of free bytes in a Queue. This routine, * then subtracts that size from the full size of the Queue so * the caller knows how many bytes are ready to be dequeued. * Results: * On success, available data size in bytes (up to MAX_INT64). * On failure, appropriate error code. */ static inline s64 vmci_q_header_buf_ready(const struct vmci_queue_header *consume_q_header, const struct vmci_queue_header *produce_q_header, const u64 consume_q_size) { s64 free_space; free_space = vmci_q_header_free_space(consume_q_header, produce_q_header, consume_q_size); if (free_space < VMCI_SUCCESS) return free_space; return consume_q_size - free_space - 1; } #endif /* _VMW_VMCI_DEF_H_ */ |