0001
0002
0003
0004
0005
0006
0007
0008 #ifndef _VMW_VMCI_DEF_H_
0009 #define _VMW_VMCI_DEF_H_
0010
0011 #include <linux/atomic.h>
0012 #include <linux/bits.h>
0013
0014
0015 #define VMCI_STATUS_ADDR 0x00
0016 #define VMCI_CONTROL_ADDR 0x04
0017 #define VMCI_ICR_ADDR 0x08
0018 #define VMCI_IMR_ADDR 0x0c
0019 #define VMCI_DATA_OUT_ADDR 0x10
0020 #define VMCI_DATA_IN_ADDR 0x14
0021 #define VMCI_CAPS_ADDR 0x18
0022 #define VMCI_RESULT_LOW_ADDR 0x1c
0023 #define VMCI_RESULT_HIGH_ADDR 0x20
0024 #define VMCI_DATA_OUT_LOW_ADDR 0x24
0025 #define VMCI_DATA_OUT_HIGH_ADDR 0x28
0026 #define VMCI_DATA_IN_LOW_ADDR 0x2c
0027 #define VMCI_DATA_IN_HIGH_ADDR 0x30
0028 #define VMCI_GUEST_PAGE_SHIFT 0x34
0029
0030
0031 #define VMCI_MAX_DEVICES 1
0032
0033
0034 #define VMCI_STATUS_INT_ON BIT(0)
0035
0036
0037 #define VMCI_CONTROL_RESET BIT(0)
0038 #define VMCI_CONTROL_INT_ENABLE BIT(1)
0039 #define VMCI_CONTROL_INT_DISABLE BIT(2)
0040
0041
0042 #define VMCI_CAPS_HYPERCALL BIT(0)
0043 #define VMCI_CAPS_GUESTCALL BIT(1)
0044 #define VMCI_CAPS_DATAGRAM BIT(2)
0045 #define VMCI_CAPS_NOTIFICATIONS BIT(3)
0046 #define VMCI_CAPS_PPN64 BIT(4)
0047 #define VMCI_CAPS_DMA_DATAGRAM BIT(5)
0048
0049
0050 #define VMCI_ICR_DATAGRAM BIT(0)
0051 #define VMCI_ICR_NOTIFICATION BIT(1)
0052 #define VMCI_ICR_DMA_DATAGRAM BIT(2)
0053
0054
0055 #define VMCI_IMR_DATAGRAM BIT(0)
0056 #define VMCI_IMR_NOTIFICATION BIT(1)
0057 #define VMCI_IMR_DMA_DATAGRAM BIT(2)
0058
0059
0060
0061
0062
0063
0064
0065 #define VMCI_MAX_INTRS_NOTIFICATION 2
0066 #define VMCI_MAX_INTRS_DMA_DATAGRAM 3
0067 #define VMCI_MAX_INTRS VMCI_MAX_INTRS_DMA_DATAGRAM
0068
0069
0070
0071
0072
0073 enum {
0074 VMCI_INTR_DATAGRAM = 0,
0075 VMCI_INTR_NOTIFICATION = 1,
0076 VMCI_INTR_DMA_DATAGRAM = 2,
0077 };
0078
0079
0080
0081
0082
0083
0084
0085 #define VMCI_MAX_GUEST_QP_MEMORY ((size_t)(128 * 1024 * 1024))
0086 #define VMCI_MAX_GUEST_QP_COUNT (VMCI_MAX_GUEST_QP_MEMORY / PAGE_SIZE / 2)
0087
0088
0089
0090
0091
0092 #define VMCI_MAX_GUEST_DOORBELL_COUNT PAGE_SIZE
0093
0094
0095
0096
0097
0098
0099 #define VMCI_MAX_PINNED_QP_MEMORY ((size_t)(32 * 1024))
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109 #define VMCI_WITH_MMIO_ACCESS_BAR_SIZE ((size_t)(256 * 1024))
0110 #define VMCI_MMIO_ACCESS_OFFSET ((size_t)(128 * 1024))
0111 #define VMCI_MMIO_ACCESS_SIZE ((size_t)(64 * 1024))
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134 struct vmci_data_in_out_header {
0135 uint32_t busy;
0136 uint32_t opcode;
0137 uint32_t size;
0138 uint32_t rsvd;
0139 uint64_t result;
0140 };
0141
0142 struct vmci_sg_elem {
0143 uint64_t addr;
0144 uint64_t size;
0145 };
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156 enum {
0157 VMCI_RESOURCES_QUERY = 0,
0158 VMCI_GET_CONTEXT_ID = 1,
0159 VMCI_SET_NOTIFY_BITMAP = 2,
0160 VMCI_DOORBELL_LINK = 3,
0161 VMCI_DOORBELL_UNLINK = 4,
0162 VMCI_DOORBELL_NOTIFY = 5,
0163
0164
0165
0166
0167 VMCI_DATAGRAM_REQUEST_MAP = 6,
0168 VMCI_DATAGRAM_REMOVE_MAP = 7,
0169 VMCI_EVENT_SUBSCRIBE = 8,
0170 VMCI_EVENT_UNSUBSCRIBE = 9,
0171 VMCI_QUEUEPAIR_ALLOC = 10,
0172 VMCI_QUEUEPAIR_DETACH = 11,
0173
0174
0175
0176
0177
0178 VMCI_HGFS_TRANSPORT = 13,
0179 VMCI_UNITY_PBRPC_REGISTER = 14,
0180 VMCI_RPC_PRIVILEGED = 15,
0181 VMCI_RPC_UNPRIVILEGED = 16,
0182 VMCI_RESOURCE_MAX = 17,
0183 };
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193 struct vmci_handle {
0194 u32 context;
0195 u32 resource;
0196 };
0197
0198 #define vmci_make_handle(_cid, _rid) \
0199 (struct vmci_handle){ .context = _cid, .resource = _rid }
0200
0201 static inline bool vmci_handle_is_equal(struct vmci_handle h1,
0202 struct vmci_handle h2)
0203 {
0204 return h1.context == h2.context && h1.resource == h2.resource;
0205 }
0206
0207 #define VMCI_INVALID_ID ~0
0208 static const struct vmci_handle VMCI_INVALID_HANDLE = {
0209 .context = VMCI_INVALID_ID,
0210 .resource = VMCI_INVALID_ID
0211 };
0212
0213 static inline bool vmci_handle_is_invalid(struct vmci_handle h)
0214 {
0215 return vmci_handle_is_equal(h, VMCI_INVALID_HANDLE);
0216 }
0217
0218
0219
0220
0221
0222 #define VMCI_ANON_SRC_CONTEXT_ID VMCI_INVALID_ID
0223 #define VMCI_ANON_SRC_RESOURCE_ID VMCI_INVALID_ID
0224 static const struct vmci_handle __maybe_unused VMCI_ANON_SRC_HANDLE = {
0225 .context = VMCI_ANON_SRC_CONTEXT_ID,
0226 .resource = VMCI_ANON_SRC_RESOURCE_ID
0227 };
0228
0229
0230 #define VMCI_RESERVED_CID_LIMIT ((u32) 16)
0231
0232
0233
0234
0235
0236 #define VMCI_HYPERVISOR_CONTEXT_ID 0
0237
0238
0239
0240
0241
0242 #define VMCI_WELL_KNOWN_CONTEXT_ID 1
0243
0244
0245
0246
0247 #define VMCI_HOST_CONTEXT_ID 2
0248
0249 #define VMCI_CONTEXT_IS_VM(_cid) (VMCI_INVALID_ID != (_cid) && \
0250 (_cid) > VMCI_HOST_CONTEXT_ID)
0251
0252
0253
0254
0255
0256 #define VMCI_CONTEXT_RESOURCE_ID 0
0257
0258
0259
0260
0261 enum {
0262 VMCI_SUCCESS_QUEUEPAIR_ATTACH = 5,
0263 VMCI_SUCCESS_QUEUEPAIR_CREATE = 4,
0264 VMCI_SUCCESS_LAST_DETACH = 3,
0265 VMCI_SUCCESS_ACCESS_GRANTED = 2,
0266 VMCI_SUCCESS_ENTRY_DEAD = 1,
0267 VMCI_SUCCESS = 0,
0268 VMCI_ERROR_INVALID_RESOURCE = (-1),
0269 VMCI_ERROR_INVALID_ARGS = (-2),
0270 VMCI_ERROR_NO_MEM = (-3),
0271 VMCI_ERROR_DATAGRAM_FAILED = (-4),
0272 VMCI_ERROR_MORE_DATA = (-5),
0273 VMCI_ERROR_NO_MORE_DATAGRAMS = (-6),
0274 VMCI_ERROR_NO_ACCESS = (-7),
0275 VMCI_ERROR_NO_HANDLE = (-8),
0276 VMCI_ERROR_DUPLICATE_ENTRY = (-9),
0277 VMCI_ERROR_DST_UNREACHABLE = (-10),
0278 VMCI_ERROR_PAYLOAD_TOO_LARGE = (-11),
0279 VMCI_ERROR_INVALID_PRIV = (-12),
0280 VMCI_ERROR_GENERIC = (-13),
0281 VMCI_ERROR_PAGE_ALREADY_SHARED = (-14),
0282 VMCI_ERROR_CANNOT_SHARE_PAGE = (-15),
0283 VMCI_ERROR_CANNOT_UNSHARE_PAGE = (-16),
0284 VMCI_ERROR_NO_PROCESS = (-17),
0285 VMCI_ERROR_NO_DATAGRAM = (-18),
0286 VMCI_ERROR_NO_RESOURCES = (-19),
0287 VMCI_ERROR_UNAVAILABLE = (-20),
0288 VMCI_ERROR_NOT_FOUND = (-21),
0289 VMCI_ERROR_ALREADY_EXISTS = (-22),
0290 VMCI_ERROR_NOT_PAGE_ALIGNED = (-23),
0291 VMCI_ERROR_INVALID_SIZE = (-24),
0292 VMCI_ERROR_REGION_ALREADY_SHARED = (-25),
0293 VMCI_ERROR_TIMEOUT = (-26),
0294 VMCI_ERROR_DATAGRAM_INCOMPLETE = (-27),
0295 VMCI_ERROR_INCORRECT_IRQL = (-28),
0296 VMCI_ERROR_EVENT_UNKNOWN = (-29),
0297 VMCI_ERROR_OBSOLETE = (-30),
0298 VMCI_ERROR_QUEUEPAIR_MISMATCH = (-31),
0299 VMCI_ERROR_QUEUEPAIR_NOTSET = (-32),
0300 VMCI_ERROR_QUEUEPAIR_NOTOWNER = (-33),
0301 VMCI_ERROR_QUEUEPAIR_NOTATTACHED = (-34),
0302 VMCI_ERROR_QUEUEPAIR_NOSPACE = (-35),
0303 VMCI_ERROR_QUEUEPAIR_NODATA = (-36),
0304 VMCI_ERROR_BUSMEM_INVALIDATION = (-37),
0305 VMCI_ERROR_MODULE_NOT_LOADED = (-38),
0306 VMCI_ERROR_DEVICE_NOT_FOUND = (-39),
0307 VMCI_ERROR_QUEUEPAIR_NOT_READY = (-40),
0308 VMCI_ERROR_WOULD_BLOCK = (-41),
0309
0310
0311 VMCI_ERROR_CLIENT_MIN = (-500),
0312 VMCI_ERROR_CLIENT_MAX = (-550),
0313
0314
0315 VMCI_SHAREDMEM_ERROR_BAD_CONTEXT = (-1000),
0316 };
0317
0318
0319 enum {
0320
0321 VMCI_EVENT_CTX_ID_UPDATE = 0,
0322
0323
0324 VMCI_EVENT_CTX_REMOVED = 1,
0325
0326
0327 VMCI_EVENT_QP_RESUMED = 2,
0328
0329
0330 VMCI_EVENT_QP_PEER_ATTACH = 3,
0331
0332
0333 VMCI_EVENT_QP_PEER_DETACH = 4,
0334
0335
0336
0337
0338
0339 VMCI_EVENT_MEM_ACCESS_ON = 5,
0340
0341
0342
0343
0344
0345 VMCI_EVENT_MEM_ACCESS_OFF = 6,
0346 VMCI_EVENT_MAX = 7,
0347 };
0348
0349
0350
0351
0352
0353
0354
0355
0356 #define VMCI_EVENT_VALID_VMX(_event) ((_event) == VMCI_EVENT_MEM_ACCESS_ON || \
0357 (_event) == VMCI_EVENT_MEM_ACCESS_OFF)
0358
0359 #define VMCI_EVENT_VALID(_event) ((_event) < VMCI_EVENT_MAX && \
0360 !VMCI_EVENT_VALID_VMX(_event))
0361
0362
0363 #define VMCI_EVENT_HANDLER 0
0364
0365
0366
0367
0368
0369
0370 enum {
0371 VMCI_NO_PRIVILEGE_FLAGS = 0,
0372 VMCI_PRIVILEGE_FLAG_RESTRICTED = 1,
0373 VMCI_PRIVILEGE_FLAG_TRUSTED = 2,
0374 VMCI_PRIVILEGE_ALL_FLAGS = (VMCI_PRIVILEGE_FLAG_RESTRICTED |
0375 VMCI_PRIVILEGE_FLAG_TRUSTED),
0376 VMCI_DEFAULT_PROC_PRIVILEGE_FLAGS = VMCI_NO_PRIVILEGE_FLAGS,
0377 VMCI_LEAST_PRIVILEGE_FLAGS = VMCI_PRIVILEGE_FLAG_RESTRICTED,
0378 VMCI_MAX_PRIVILEGE_FLAGS = VMCI_PRIVILEGE_FLAG_TRUSTED,
0379 };
0380
0381
0382 #define VMCI_RESERVED_RESOURCE_ID_MAX 1023
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393 #define VMCI_VERSION_SHIFT_WIDTH 16
0394 #define VMCI_MAKE_VERSION(_major, _minor) \
0395 ((_major) << VMCI_VERSION_SHIFT_WIDTH | (u16) (_minor))
0396
0397 #define VMCI_VERSION_MAJOR(v) ((u32) (v) >> VMCI_VERSION_SHIFT_WIDTH)
0398 #define VMCI_VERSION_MINOR(v) ((u16) (v))
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423 #define VMCI_VERSION VMCI_VERSION_NOVMVM
0424 #define VMCI_VERSION_NOVMVM VMCI_MAKE_VERSION(11, 0)
0425 #define VMCI_VERSION_NOTIFY VMCI_MAKE_VERSION(10, 0)
0426 #define VMCI_VERSION_HOSTQP VMCI_MAKE_VERSION(9, 0)
0427 #define VMCI_VERSION_PREHOSTQP VMCI_MAKE_VERSION(8, 0)
0428 #define VMCI_VERSION_PREVERS2 VMCI_MAKE_VERSION(1, 0)
0429
0430 #define VMCI_SOCKETS_MAKE_VERSION(_p) \
0431 ((((_p)[0] & 0xFF) << 24) | (((_p)[1] & 0xFF) << 16) | ((_p)[2]))
0432
0433
0434
0435
0436
0437
0438
0439
0440 #define IOCTL_VMCI_VERSION _IO(7, 0x9f)
0441 #define IOCTL_VMCI_INIT_CONTEXT _IO(7, 0xa0)
0442 #define IOCTL_VMCI_QUEUEPAIR_SETVA _IO(7, 0xa4)
0443 #define IOCTL_VMCI_NOTIFY_RESOURCE _IO(7, 0xa5)
0444 #define IOCTL_VMCI_NOTIFICATIONS_RECEIVE _IO(7, 0xa6)
0445 #define IOCTL_VMCI_VERSION2 _IO(7, 0xa7)
0446 #define IOCTL_VMCI_QUEUEPAIR_ALLOC _IO(7, 0xa8)
0447 #define IOCTL_VMCI_QUEUEPAIR_SETPAGEFILE _IO(7, 0xa9)
0448 #define IOCTL_VMCI_QUEUEPAIR_DETACH _IO(7, 0xaa)
0449 #define IOCTL_VMCI_DATAGRAM_SEND _IO(7, 0xab)
0450 #define IOCTL_VMCI_DATAGRAM_RECEIVE _IO(7, 0xac)
0451 #define IOCTL_VMCI_CTX_ADD_NOTIFICATION _IO(7, 0xaf)
0452 #define IOCTL_VMCI_CTX_REMOVE_NOTIFICATION _IO(7, 0xb0)
0453 #define IOCTL_VMCI_CTX_GET_CPT_STATE _IO(7, 0xb1)
0454 #define IOCTL_VMCI_CTX_SET_CPT_STATE _IO(7, 0xb2)
0455 #define IOCTL_VMCI_GET_CONTEXT_ID _IO(7, 0xb3)
0456 #define IOCTL_VMCI_SOCKETS_VERSION _IO(7, 0xb4)
0457 #define IOCTL_VMCI_SOCKETS_GET_AF_VALUE _IO(7, 0xb8)
0458 #define IOCTL_VMCI_SOCKETS_GET_LOCAL_CID _IO(7, 0xb9)
0459 #define IOCTL_VMCI_SET_NOTIFY _IO(7, 0xcb)
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501 struct vmci_queue_header {
0502
0503 struct vmci_handle handle;
0504 u64 producer_tail;
0505 u64 consumer_head;
0506 };
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518 struct vmci_datagram {
0519 struct vmci_handle dst;
0520 struct vmci_handle src;
0521 u64 payload_size;
0522 };
0523
0524
0525
0526
0527
0528
0529 #define VMCI_FLAG_DG_NONE 0
0530 #define VMCI_FLAG_WELLKNOWN_DG_HND BIT(0)
0531 #define VMCI_FLAG_ANYCID_DG_HND BIT(1)
0532 #define VMCI_FLAG_DG_DELAYED_CB BIT(2)
0533
0534
0535
0536
0537
0538 #define VMCI_MAX_DG_SIZE (17 * 4096)
0539 #define VMCI_MAX_DG_PAYLOAD_SIZE (VMCI_MAX_DG_SIZE - \
0540 sizeof(struct vmci_datagram))
0541 #define VMCI_DG_PAYLOAD(_dg) (void *)((char *)(_dg) + \
0542 sizeof(struct vmci_datagram))
0543 #define VMCI_DG_HEADERSIZE sizeof(struct vmci_datagram)
0544 #define VMCI_DG_SIZE(_dg) (VMCI_DG_HEADERSIZE + (size_t)(_dg)->payload_size)
0545 #define VMCI_DG_SIZE_ALIGNED(_dg) ((VMCI_DG_SIZE(_dg) + 7) & (~((size_t) 0x7)))
0546 #define VMCI_MAX_DATAGRAM_QUEUE_SIZE (VMCI_MAX_DG_SIZE * 2)
0547
0548 struct vmci_event_payload_qp {
0549 struct vmci_handle handle;
0550 u32 peer_id;
0551 u32 _pad;
0552 };
0553
0554
0555 enum {
0556
0557 VMCI_QPFLAG_ATTACH_ONLY = 1 << 0,
0558
0559
0560 VMCI_QPFLAG_LOCAL = 1 << 1,
0561
0562
0563 VMCI_QPFLAG_NONBLOCK = 1 << 2,
0564
0565
0566 VMCI_QPFLAG_PINNED = 1 << 3,
0567
0568
0569 VMCI_QP_ALL_FLAGS = (VMCI_QPFLAG_ATTACH_ONLY | VMCI_QPFLAG_LOCAL |
0570 VMCI_QPFLAG_NONBLOCK | VMCI_QPFLAG_PINNED),
0571
0572
0573 VMCI_QP_ASYMM = (VMCI_QPFLAG_NONBLOCK | VMCI_QPFLAG_PINNED),
0574 VMCI_QP_ASYMM_PEER = (VMCI_QPFLAG_ATTACH_ONLY | VMCI_QP_ASYMM),
0575 };
0576
0577
0578
0579
0580
0581
0582
0583
0584
0585
0586
0587
0588
0589
0590
0591
0592 #define VMCI_MAX_DATAGRAM_AND_EVENT_QUEUE_SIZE \
0593 (VMCI_MAX_DATAGRAM_QUEUE_SIZE + \
0594 1024 * (sizeof(struct vmci_datagram) + \
0595 sizeof(struct vmci_event_data_max)))
0596
0597
0598
0599
0600
0601
0602 struct vmci_resource_query_hdr {
0603 struct vmci_datagram hdr;
0604 u32 num_resources;
0605 u32 _padding;
0606 };
0607
0608
0609
0610
0611
0612 struct vmci_resource_query_msg {
0613 u32 num_resources;
0614 u32 _padding;
0615 u32 resources[1];
0616 };
0617
0618
0619
0620
0621
0622
0623
0624 #define VMCI_RESOURCE_QUERY_MAX_NUM 31
0625
0626
0627 #define VMCI_RESOURCE_QUERY_MAX_SIZE \
0628 (sizeof(struct vmci_resource_query_hdr) + \
0629 sizeof(u32) * VMCI_RESOURCE_QUERY_MAX_NUM)
0630
0631
0632
0633
0634
0635 struct vmci_notify_bm_set_msg {
0636 struct vmci_datagram hdr;
0637 union {
0638 u32 bitmap_ppn32;
0639 u64 bitmap_ppn64;
0640 };
0641 };
0642
0643
0644
0645
0646
0647
0648 struct vmci_doorbell_link_msg {
0649 struct vmci_datagram hdr;
0650 struct vmci_handle handle;
0651 u64 notify_idx;
0652 };
0653
0654
0655
0656
0657
0658
0659 struct vmci_doorbell_unlink_msg {
0660 struct vmci_datagram hdr;
0661 struct vmci_handle handle;
0662 };
0663
0664
0665
0666
0667
0668 struct vmci_doorbell_notify_msg {
0669 struct vmci_datagram hdr;
0670 struct vmci_handle handle;
0671 };
0672
0673
0674
0675
0676
0677 struct vmci_event_data {
0678 u32 event;
0679 u32 _pad;
0680
0681 };
0682
0683
0684
0685
0686
0687
0688 struct vmci_event_payld_ctx {
0689 u32 context_id;
0690 u32 _pad;
0691 };
0692
0693 struct vmci_event_payld_qp {
0694 struct vmci_handle handle;
0695 u32 peer_id;
0696 u32 _pad;
0697 };
0698
0699
0700
0701
0702
0703
0704
0705 struct vmci_event_data_max {
0706 struct vmci_event_data event_data;
0707 union {
0708 struct vmci_event_payld_ctx context_payload;
0709 struct vmci_event_payld_qp qp_payload;
0710 } ev_data_payload;
0711 };
0712
0713
0714
0715
0716
0717
0718 struct vmci_event_msg {
0719 struct vmci_datagram hdr;
0720
0721
0722 struct vmci_event_data event_data;
0723
0724
0725 };
0726
0727
0728 struct vmci_event_ctx {
0729 struct vmci_event_msg msg;
0730 struct vmci_event_payld_ctx payload;
0731 };
0732
0733
0734 struct vmci_event_qp {
0735 struct vmci_event_msg msg;
0736 struct vmci_event_payld_qp payload;
0737 };
0738
0739
0740
0741
0742
0743 struct vmci_qp_alloc_msg {
0744 struct vmci_datagram hdr;
0745 struct vmci_handle handle;
0746 u32 peer;
0747 u32 flags;
0748 u64 produce_size;
0749 u64 consume_size;
0750 u64 num_ppns;
0751
0752
0753 };
0754
0755 struct vmci_qp_detach_msg {
0756 struct vmci_datagram hdr;
0757 struct vmci_handle handle;
0758 };
0759
0760
0761 #define VMCI_FLAG_DELAYED_CB BIT(0)
0762
0763 typedef void (*vmci_callback) (void *client_data);
0764
0765
0766
0767
0768
0769
0770
0771 struct vmci_qp;
0772
0773
0774 typedef int (*vmci_datagram_recv_cb) (void *client_data,
0775 struct vmci_datagram *msg);
0776
0777
0778 typedef void (*vmci_event_cb) (u32 sub_id, const struct vmci_event_data *ed,
0779 void *client_data);
0780
0781
0782
0783
0784
0785 static inline const void *
0786 vmci_event_data_const_payload(const struct vmci_event_data *ev_data)
0787 {
0788 return (const char *)ev_data + sizeof(*ev_data);
0789 }
0790
0791 static inline void *vmci_event_data_payload(struct vmci_event_data *ev_data)
0792 {
0793 return (void *)vmci_event_data_const_payload(ev_data);
0794 }
0795
0796
0797
0798
0799
0800
0801
0802
0803
0804
0805
0806 static inline u64 vmci_q_read_pointer(u64 *var)
0807 {
0808 return READ_ONCE(*(unsigned long *)var);
0809 }
0810
0811
0812
0813
0814
0815
0816
0817 static inline void vmci_q_set_pointer(u64 *var, u64 new_val)
0818 {
0819
0820 WRITE_ONCE(*(unsigned long *)var, (unsigned long)new_val);
0821 }
0822
0823
0824
0825
0826
0827 static inline void vmci_qp_add_pointer(u64 *var, size_t add, u64 size)
0828 {
0829 u64 new_val = vmci_q_read_pointer(var);
0830
0831 if (new_val >= size - add)
0832 new_val -= size;
0833
0834 new_val += add;
0835
0836 vmci_q_set_pointer(var, new_val);
0837 }
0838
0839
0840
0841
0842 static inline u64
0843 vmci_q_header_producer_tail(const struct vmci_queue_header *q_header)
0844 {
0845 struct vmci_queue_header *qh = (struct vmci_queue_header *)q_header;
0846 return vmci_q_read_pointer(&qh->producer_tail);
0847 }
0848
0849
0850
0851
0852 static inline u64
0853 vmci_q_header_consumer_head(const struct vmci_queue_header *q_header)
0854 {
0855 struct vmci_queue_header *qh = (struct vmci_queue_header *)q_header;
0856 return vmci_q_read_pointer(&qh->consumer_head);
0857 }
0858
0859
0860
0861
0862
0863 static inline void
0864 vmci_q_header_add_producer_tail(struct vmci_queue_header *q_header,
0865 size_t add,
0866 u64 queue_size)
0867 {
0868 vmci_qp_add_pointer(&q_header->producer_tail, add, queue_size);
0869 }
0870
0871
0872
0873
0874
0875 static inline void
0876 vmci_q_header_add_consumer_head(struct vmci_queue_header *q_header,
0877 size_t add,
0878 u64 queue_size)
0879 {
0880 vmci_qp_add_pointer(&q_header->consumer_head, add, queue_size);
0881 }
0882
0883
0884
0885
0886
0887 static inline void
0888 vmci_q_header_get_pointers(const struct vmci_queue_header *produce_q_header,
0889 const struct vmci_queue_header *consume_q_header,
0890 u64 *producer_tail,
0891 u64 *consumer_head)
0892 {
0893 if (producer_tail)
0894 *producer_tail = vmci_q_header_producer_tail(produce_q_header);
0895
0896 if (consumer_head)
0897 *consumer_head = vmci_q_header_consumer_head(consume_q_header);
0898 }
0899
0900 static inline void vmci_q_header_init(struct vmci_queue_header *q_header,
0901 const struct vmci_handle handle)
0902 {
0903 q_header->handle = handle;
0904 q_header->producer_tail = 0;
0905 q_header->consumer_head = 0;
0906 }
0907
0908
0909
0910
0911
0912 static s64
0913 vmci_q_header_free_space(const struct vmci_queue_header *produce_q_header,
0914 const struct vmci_queue_header *consume_q_header,
0915 const u64 produce_q_size)
0916 {
0917 u64 tail;
0918 u64 head;
0919 u64 free_space;
0920
0921 tail = vmci_q_header_producer_tail(produce_q_header);
0922 head = vmci_q_header_consumer_head(consume_q_header);
0923
0924 if (tail >= produce_q_size || head >= produce_q_size)
0925 return VMCI_ERROR_INVALID_SIZE;
0926
0927
0928
0929
0930
0931
0932 if (tail >= head)
0933 free_space = produce_q_size - (tail - head) - 1;
0934 else
0935 free_space = head - tail - 1;
0936
0937 return free_space;
0938 }
0939
0940
0941
0942
0943
0944
0945
0946
0947
0948
0949 static inline s64
0950 vmci_q_header_buf_ready(const struct vmci_queue_header *consume_q_header,
0951 const struct vmci_queue_header *produce_q_header,
0952 const u64 consume_q_size)
0953 {
0954 s64 free_space;
0955
0956 free_space = vmci_q_header_free_space(consume_q_header,
0957 produce_q_header, consume_q_size);
0958 if (free_space < VMCI_SUCCESS)
0959 return free_space;
0960
0961 return consume_q_size - free_space - 1;
0962 }
0963
0964
0965 #endif