120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * VMware VMCI Driver
320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang *
420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Copyright (C) 2012 VMware, Inc. All rights reserved.
520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang *
620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * This program is free software; you can redistribute it and/or modify it
720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * under the terms of the GNU General Public License as published by the
820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Free Software Foundation version 2 and no later version.
920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang *
1020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * This program is distributed in the hope that it will be useful, but
1120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * for more details.
1420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
1520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
1620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#ifndef _VMW_VMCI_DEF_H_
1720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define _VMW_VMCI_DEF_H_
1820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
1920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#include <linux/atomic.h>
2020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
2120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/* Register offsets. */
2220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_STATUS_ADDR      0x00
2320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_CONTROL_ADDR     0x04
2420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_ICR_ADDR	      0x08
2520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_IMR_ADDR         0x0c
2620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_DATA_OUT_ADDR    0x10
2720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_DATA_IN_ADDR     0x14
2820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_CAPS_ADDR        0x18
2920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_RESULT_LOW_ADDR  0x1c
3020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_RESULT_HIGH_ADDR 0x20
3120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
3220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/* Max number of devices. */
3320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_MAX_DEVICES 1
3420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
3520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/* Status register bits. */
3620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_STATUS_INT_ON     0x1
3720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
3820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/* Control register bits. */
3920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_CONTROL_RESET        0x1
4020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_CONTROL_INT_ENABLE   0x2
4120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_CONTROL_INT_DISABLE  0x4
4220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
4320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/* Capabilities register bits. */
4420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_CAPS_HYPERCALL     0x1
4520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_CAPS_GUESTCALL     0x2
4620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_CAPS_DATAGRAM      0x4
4720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_CAPS_NOTIFICATIONS 0x8
4820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
4920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/* Interrupt Cause register bits. */
5020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_ICR_DATAGRAM      0x1
5120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_ICR_NOTIFICATION  0x2
5220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
5320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/* Interrupt Mask register bits. */
5420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_IMR_DATAGRAM      0x1
5520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_IMR_NOTIFICATION  0x2
5620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
5720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/* Interrupt type. */
5820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangenum {
5920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_INTR_TYPE_INTX = 0,
6020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_INTR_TYPE_MSI = 1,
6120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_INTR_TYPE_MSIX = 2,
6220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
6320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
6420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/* Maximum MSI/MSI-X interrupt vectors in the device. */
6520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_MAX_INTRS 2
6620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
6720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
6820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Supported interrupt vectors.  There is one for each ICR value above,
6920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * but here they indicate the position in the vector array/message ID.
7020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
7120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangenum {
7220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_INTR_DATAGRAM = 0,
7320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_INTR_NOTIFICATION = 1,
7420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
7520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
7620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
7720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * A single VMCI device has an upper limit of 128MB on the amount of
7820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * memory that can be used for queue pairs.
7920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
8020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_MAX_GUEST_QP_MEMORY (128 * 1024 * 1024)
8120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
8220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
8320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Queues with pre-mapped data pages must be small, so that we don't pin
8420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * too much kernel memory (especially on vmkernel).  We limit a queuepair to
8520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * 32 KB, or 16 KB per queue for symmetrical pairs.
8620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
8720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_MAX_PINNED_QP_MEMORY (32 * 1024)
8820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
8920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
9020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * We have a fixed set of resource IDs available in the VMX.
9120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * This allows us to have a very simple implementation since we statically
9220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * know how many will create datagram handles. If a new caller arrives and
9320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * we have run out of slots we can manually increment the maximum size of
9420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * available resource IDs.
9520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang *
9620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * VMCI reserved hypervisor datagram resource IDs.
9720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
9820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangenum {
9920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_RESOURCES_QUERY = 0,
10020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_GET_CONTEXT_ID = 1,
10120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_SET_NOTIFY_BITMAP = 2,
10220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_DOORBELL_LINK = 3,
10320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_DOORBELL_UNLINK = 4,
10420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_DOORBELL_NOTIFY = 5,
10520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	/*
10620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	 * VMCI_DATAGRAM_REQUEST_MAP and VMCI_DATAGRAM_REMOVE_MAP are
10720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	 * obsoleted by the removal of VM to VM communication.
10820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	 */
10920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_DATAGRAM_REQUEST_MAP = 6,
11020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_DATAGRAM_REMOVE_MAP = 7,
11120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_EVENT_SUBSCRIBE = 8,
11220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_EVENT_UNSUBSCRIBE = 9,
11320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_QUEUEPAIR_ALLOC = 10,
11420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_QUEUEPAIR_DETACH = 11,
11520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
11620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	/*
11720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	 * VMCI_VSOCK_VMX_LOOKUP was assigned to 12 for Fusion 3.0/3.1,
11820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	 * WS 7.0/7.1 and ESX 4.1
11920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	 */
12020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_HGFS_TRANSPORT = 13,
12120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_UNITY_PBRPC_REGISTER = 14,
12220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_RPC_PRIVILEGED = 15,
12320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_RPC_UNPRIVILEGED = 16,
12420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_RESOURCE_MAX = 17,
12520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
12620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
12720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
12820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * struct vmci_handle - Ownership information structure
12920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * @context:    The VMX context ID.
13020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * @resource:   The resource ID (used for locating in resource hash).
13120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang *
13220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * The vmci_handle structure is used to track resources used within
13320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * vmw_vmci.
13420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
13520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstruct vmci_handle {
13620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u32 context;
13720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u32 resource;
13820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
13920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
14020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define vmci_make_handle(_cid, _rid) \
14120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	(struct vmci_handle){ .context = _cid, .resource = _rid }
14220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
14320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstatic inline bool vmci_handle_is_equal(struct vmci_handle h1,
14420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang					struct vmci_handle h2)
14520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang{
14620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	return h1.context == h2.context && h1.resource == h2.resource;
14720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang}
14820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
14920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_INVALID_ID ~0
15020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstatic const struct vmci_handle VMCI_INVALID_HANDLE = {
15120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	.context = VMCI_INVALID_ID,
15220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	.resource = VMCI_INVALID_ID
15320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
15420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
15520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstatic inline bool vmci_handle_is_invalid(struct vmci_handle h)
15620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang{
15720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	return vmci_handle_is_equal(h, VMCI_INVALID_HANDLE);
15820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang}
15920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
16020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
16120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * The below defines can be used to send anonymous requests.
16220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * This also indicates that no response is expected.
16320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
16420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_ANON_SRC_CONTEXT_ID   VMCI_INVALID_ID
16520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_ANON_SRC_RESOURCE_ID  VMCI_INVALID_ID
16620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstatic const struct vmci_handle VMCI_ANON_SRC_HANDLE = {
16720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	.context = VMCI_ANON_SRC_CONTEXT_ID,
16820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	.resource = VMCI_ANON_SRC_RESOURCE_ID
16920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
17020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
17120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/* The lowest 16 context ids are reserved for internal use. */
17220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_RESERVED_CID_LIMIT ((u32) 16)
17320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
17420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
17520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Hypervisor context id, used for calling into hypervisor
17620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * supplied services from the VM.
17720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
17820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_HYPERVISOR_CONTEXT_ID 0
17920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
18020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
18120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Well-known context id, a logical context that contains a set of
18220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * well-known services. This context ID is now obsolete.
18320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
18420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_WELL_KNOWN_CONTEXT_ID 1
18520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
18620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
18720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Context ID used by host endpoints.
18820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
18920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_HOST_CONTEXT_ID  2
19020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
19120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_CONTEXT_IS_VM(_cid) (VMCI_INVALID_ID != (_cid) &&		\
19220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang				  (_cid) > VMCI_HOST_CONTEXT_ID)
19320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
19420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
19520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * The VMCI_CONTEXT_RESOURCE_ID is used together with vmci_make_handle to make
19620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * handles that refer to a specific context.
19720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
19820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_CONTEXT_RESOURCE_ID 0
19920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
20020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
20120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * VMCI error codes.
20220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
20320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangenum {
20420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_SUCCESS_QUEUEPAIR_ATTACH	= 5,
20520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_SUCCESS_QUEUEPAIR_CREATE	= 4,
20620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_SUCCESS_LAST_DETACH	= 3,
20720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_SUCCESS_ACCESS_GRANTED	= 2,
20820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_SUCCESS_ENTRY_DEAD		= 1,
20920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_SUCCESS			 = 0,
21020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_INVALID_RESOURCE	 = (-1),
21120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_INVALID_ARGS		 = (-2),
21220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_NO_MEM		 = (-3),
21320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_DATAGRAM_FAILED	 = (-4),
21420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_MORE_DATA		 = (-5),
21520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_NO_MORE_DATAGRAMS	 = (-6),
21620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_NO_ACCESS		 = (-7),
21720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_NO_HANDLE		 = (-8),
21820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_DUPLICATE_ENTRY	 = (-9),
21920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_DST_UNREACHABLE	 = (-10),
22020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_PAYLOAD_TOO_LARGE	 = (-11),
22120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_INVALID_PRIV		 = (-12),
22220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_GENERIC		 = (-13),
22320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_PAGE_ALREADY_SHARED	 = (-14),
22420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_CANNOT_SHARE_PAGE	 = (-15),
22520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_CANNOT_UNSHARE_PAGE	 = (-16),
22620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_NO_PROCESS		 = (-17),
22720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_NO_DATAGRAM		 = (-18),
22820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_NO_RESOURCES		 = (-19),
22920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_UNAVAILABLE		 = (-20),
23020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_NOT_FOUND		 = (-21),
23120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_ALREADY_EXISTS	 = (-22),
23220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_NOT_PAGE_ALIGNED	 = (-23),
23320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_INVALID_SIZE		 = (-24),
23420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_REGION_ALREADY_SHARED = (-25),
23520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_TIMEOUT		 = (-26),
23620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_DATAGRAM_INCOMPLETE	 = (-27),
23720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_INCORRECT_IRQL	 = (-28),
23820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_EVENT_UNKNOWN	 = (-29),
23920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_OBSOLETE		 = (-30),
24020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_QUEUEPAIR_MISMATCH	 = (-31),
24120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_QUEUEPAIR_NOTSET	 = (-32),
24220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_QUEUEPAIR_NOTOWNER	 = (-33),
24320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_QUEUEPAIR_NOTATTACHED = (-34),
24420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_QUEUEPAIR_NOSPACE	 = (-35),
24520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_QUEUEPAIR_NODATA	 = (-36),
24620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_BUSMEM_INVALIDATION	 = (-37),
24720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_MODULE_NOT_LOADED	 = (-38),
24820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_DEVICE_NOT_FOUND	 = (-39),
24920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_QUEUEPAIR_NOT_READY	 = (-40),
25020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_WOULD_BLOCK		 = (-41),
25120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
25220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	/* VMCI clients should return error code within this range */
25320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_CLIENT_MIN		 = (-500),
25420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_ERROR_CLIENT_MAX		 = (-550),
25520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
25620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	/* Internal error codes. */
25720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_SHAREDMEM_ERROR_BAD_CONTEXT = (-1000),
25820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
25920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
26020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/* VMCI reserved events. */
26120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangenum {
26220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	/* Only applicable to guest endpoints */
26320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_EVENT_CTX_ID_UPDATE  = 0,
26420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
26520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	/* Applicable to guest and host */
26620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_EVENT_CTX_REMOVED	  = 1,
26720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
26820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	/* Only applicable to guest endpoints */
26920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_EVENT_QP_RESUMED	  = 2,
27020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
27120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	/* Applicable to guest and host */
27220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_EVENT_QP_PEER_ATTACH = 3,
27320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
27420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	/* Applicable to guest and host */
27520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_EVENT_QP_PEER_DETACH = 4,
27620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
27720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	/*
27820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	 * Applicable to VMX and vmk.  On vmk,
27920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	 * this event has the Context payload type.
28020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	 */
28120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_EVENT_MEM_ACCESS_ON  = 5,
28220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
28320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	/*
28420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	 * Applicable to VMX and vmk.  Same as
28520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	 * above for the payload type.
28620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	 */
28720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_EVENT_MEM_ACCESS_OFF = 6,
28820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_EVENT_MAX		  = 7,
28920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
29020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
29120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
29220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Of the above events, a few are reserved for use in the VMX, and
29320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * other endpoints (guest and host kernel) should not use them. For
29420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * the rest of the events, we allow both host and guest endpoints to
29520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * subscribe to them, to maintain the same API for host and guest
29620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * endpoints.
29720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
29820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_EVENT_VALID_VMX(_event) ((_event) == VMCI_EVENT_MEM_ACCESS_ON || \
29920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang				      (_event) == VMCI_EVENT_MEM_ACCESS_OFF)
30020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
30120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_EVENT_VALID(_event) ((_event) < VMCI_EVENT_MAX &&		\
30220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang				  !VMCI_EVENT_VALID_VMX(_event))
30320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
30420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/* Reserved guest datagram resource ids. */
30520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_EVENT_HANDLER 0
30620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
30720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
30820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * VMCI coarse-grained privileges (per context or host
30920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * process/endpoint. An entity with the restricted flag is only
31020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * allowed to interact with the hypervisor and trusted entities.
31120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
31220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangenum {
31320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_NO_PRIVILEGE_FLAGS = 0,
31420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_PRIVILEGE_FLAG_RESTRICTED = 1,
31520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_PRIVILEGE_FLAG_TRUSTED = 2,
31620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_PRIVILEGE_ALL_FLAGS = (VMCI_PRIVILEGE_FLAG_RESTRICTED |
31720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang				    VMCI_PRIVILEGE_FLAG_TRUSTED),
31820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_DEFAULT_PROC_PRIVILEGE_FLAGS = VMCI_NO_PRIVILEGE_FLAGS,
31920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_LEAST_PRIVILEGE_FLAGS = VMCI_PRIVILEGE_FLAG_RESTRICTED,
32020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_MAX_PRIVILEGE_FLAGS = VMCI_PRIVILEGE_FLAG_TRUSTED,
32120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
32220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
32320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/* 0 through VMCI_RESERVED_RESOURCE_ID_MAX are reserved. */
32420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_RESERVED_RESOURCE_ID_MAX 1023
32520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
32620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
32720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Driver version.
32820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang *
32920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Increment major version when you make an incompatible change.
33020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Compatibility goes both ways (old driver with new executable
33120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * as well as new driver with old executable).
33220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
33320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
33420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/* Never change VMCI_VERSION_SHIFT_WIDTH */
33520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_VERSION_SHIFT_WIDTH 16
33620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_MAKE_VERSION(_major, _minor)			\
33720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	((_major) << VMCI_VERSION_SHIFT_WIDTH | (u16) (_minor))
33820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
33920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_VERSION_MAJOR(v)  ((u32) (v) >> VMCI_VERSION_SHIFT_WIDTH)
34020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_VERSION_MINOR(v)  ((u16) (v))
34120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
34220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
34320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * VMCI_VERSION is always the current version.  Subsequently listed
34420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * versions are ways of detecting previous versions of the connecting
34520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * application (i.e., VMX).
34620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang *
34720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * VMCI_VERSION_NOVMVM: This version removed support for VM to VM
34820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * communication.
34920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang *
35020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * VMCI_VERSION_NOTIFY: This version introduced doorbell notification
35120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * support.
35220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang *
35320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * VMCI_VERSION_HOSTQP: This version introduced host end point support
35420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * for hosted products.
35520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang *
35620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * VMCI_VERSION_PREHOSTQP: This is the version prior to the adoption of
35720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * support for host end-points.
35820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang *
35920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * VMCI_VERSION_PREVERS2: This fictional version number is intended to
36020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * represent the version of a VMX which doesn't call into the driver
36120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * with ioctl VERSION2 and thus doesn't establish its version with the
36220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * driver.
36320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
36420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
36520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_VERSION                VMCI_VERSION_NOVMVM
36620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_VERSION_NOVMVM         VMCI_MAKE_VERSION(11, 0)
36720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_VERSION_NOTIFY         VMCI_MAKE_VERSION(10, 0)
36820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_VERSION_HOSTQP         VMCI_MAKE_VERSION(9, 0)
36920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_VERSION_PREHOSTQP      VMCI_MAKE_VERSION(8, 0)
37020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_VERSION_PREVERS2       VMCI_MAKE_VERSION(1, 0)
37120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
37220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_SOCKETS_MAKE_VERSION(_p)					\
37320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	((((_p)[0] & 0xFF) << 24) | (((_p)[1] & 0xFF) << 16) | ((_p)[2]))
37420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
37520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
37620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * The VMCI IOCTLs.  We use identity code 7, as noted in ioctl-number.h, and
37720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * we start at sequence 9f.  This gives us the same values that our shipping
37820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * products use, starting at 1951, provided we leave out the direction and
37920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * structure size.  Note that VMMon occupies the block following us, starting
38020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * at 2001.
38120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
38220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define IOCTL_VMCI_VERSION			_IO(7, 0x9f)	/* 1951 */
38320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define IOCTL_VMCI_INIT_CONTEXT			_IO(7, 0xa0)
38420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define IOCTL_VMCI_QUEUEPAIR_SETVA		_IO(7, 0xa4)
38520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define IOCTL_VMCI_NOTIFY_RESOURCE		_IO(7, 0xa5)
38620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define IOCTL_VMCI_NOTIFICATIONS_RECEIVE	_IO(7, 0xa6)
38720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define IOCTL_VMCI_VERSION2			_IO(7, 0xa7)
38820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define IOCTL_VMCI_QUEUEPAIR_ALLOC		_IO(7, 0xa8)
38920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define IOCTL_VMCI_QUEUEPAIR_SETPAGEFILE	_IO(7, 0xa9)
39020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define IOCTL_VMCI_QUEUEPAIR_DETACH		_IO(7, 0xaa)
39120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define IOCTL_VMCI_DATAGRAM_SEND		_IO(7, 0xab)
39220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define IOCTL_VMCI_DATAGRAM_RECEIVE		_IO(7, 0xac)
39320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define IOCTL_VMCI_CTX_ADD_NOTIFICATION		_IO(7, 0xaf)
39420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define IOCTL_VMCI_CTX_REMOVE_NOTIFICATION	_IO(7, 0xb0)
39520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define IOCTL_VMCI_CTX_GET_CPT_STATE		_IO(7, 0xb1)
39620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define IOCTL_VMCI_CTX_SET_CPT_STATE		_IO(7, 0xb2)
39720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define IOCTL_VMCI_GET_CONTEXT_ID		_IO(7, 0xb3)
39820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define IOCTL_VMCI_SOCKETS_VERSION		_IO(7, 0xb4)
39920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define IOCTL_VMCI_SOCKETS_GET_AF_VALUE		_IO(7, 0xb8)
40020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define IOCTL_VMCI_SOCKETS_GET_LOCAL_CID	_IO(7, 0xb9)
40120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define IOCTL_VMCI_SET_NOTIFY			_IO(7, 0xcb)	/* 1995 */
40220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*IOCTL_VMMON_START				_IO(7, 0xd1)*/	/* 2001 */
40320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
40420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
40520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * struct vmci_queue_header - VMCI Queue Header information.
40620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang *
40720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * A Queue cannot stand by itself as designed.  Each Queue's header
40820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * contains a pointer into itself (the producer_tail) and into its peer
40920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * (consumer_head).  The reason for the separation is one of
41020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * accessibility: Each end-point can modify two things: where the next
41120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * location to enqueue is within its produce_q (producer_tail); and
41220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * where the next dequeue location is in its consume_q (consumer_head).
41320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang *
41420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * An end-point cannot modify the pointers of its peer (guest to
41520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * guest; NOTE that in the host both queue headers are mapped r/w).
41620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * But, each end-point needs read access to both Queue header
41720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * structures in order to determine how much space is used (or left)
41820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * in the Queue.  This is because for an end-point to know how full
41920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * its produce_q is, it needs to use the consumer_head that points into
42020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * the produce_q but -that- consumer_head is in the Queue header for
42120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * that end-points consume_q.
42220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang *
42320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Thoroughly confused?  Sorry.
42420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang *
42520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * producer_tail: the point to enqueue new entrants.  When you approach
42620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * a line in a store, for example, you walk up to the tail.
42720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang *
42820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * consumer_head: the point in the queue from which the next element is
42920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * dequeued.  In other words, who is next in line is he who is at the
43020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * head of the line.
43120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang *
43220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Also, producer_tail points to an empty byte in the Queue, whereas
43320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * consumer_head points to a valid byte of data (unless producer_tail ==
43420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * consumer_head in which case consumer_head does not point to a valid
43520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * byte of data).
43620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang *
43720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * For a queue of buffer 'size' bytes, the tail and head pointers will be in
43820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * the range [0, size-1].
43920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang *
44020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * If produce_q_header->producer_tail == consume_q_header->consumer_head
44120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * then the produce_q is empty.
44220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
44320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstruct vmci_queue_header {
44420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	/* All fields are 64bit and aligned. */
44520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_handle handle;	/* Identifier. */
44620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	atomic64_t producer_tail;	/* Offset in this queue. */
44720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	atomic64_t consumer_head;	/* Offset in peer queue. */
44820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
44920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
45020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
45120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * struct vmci_datagram - Base struct for vmci datagrams.
45220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * @dst:        A vmci_handle that tracks the destination of the datagram.
45320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * @src:        A vmci_handle that tracks the source of the datagram.
45420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * @payload_size:       The size of the payload.
45520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang *
45620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * vmci_datagram structs are used when sending vmci datagrams.  They include
45720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * the necessary source and destination information to properly route
45820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * the information along with the size of the package.
45920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
46020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstruct vmci_datagram {
46120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_handle dst;
46220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_handle src;
46320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u64 payload_size;
46420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
46520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
46620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
46720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Second flag is for creating a well-known handle instead of a per context
46820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * handle.  Next flag is for deferring datagram delivery, so that the
46920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * datagram callback is invoked in a delayed context (not interrupt context).
47020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
47120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_FLAG_DG_NONE          0
47220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_FLAG_WELLKNOWN_DG_HND 0x1
47320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_FLAG_ANYCID_DG_HND    0x2
47420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_FLAG_DG_DELAYED_CB    0x4
47520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
47620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
47720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Maximum supported size of a VMCI datagram for routable datagrams.
47820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Datagrams going to the hypervisor are allowed to be larger.
47920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
48020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_MAX_DG_SIZE (17 * 4096)
48120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_MAX_DG_PAYLOAD_SIZE (VMCI_MAX_DG_SIZE - \
48220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang				  sizeof(struct vmci_datagram))
48320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_DG_PAYLOAD(_dg) (void *)((char *)(_dg) +			\
48420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang				      sizeof(struct vmci_datagram))
48520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_DG_HEADERSIZE sizeof(struct vmci_datagram)
48620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_DG_SIZE(_dg) (VMCI_DG_HEADERSIZE + (size_t)(_dg)->payload_size)
48720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_DG_SIZE_ALIGNED(_dg) ((VMCI_DG_SIZE(_dg) + 7) & (~((size_t) 0x7)))
48820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_MAX_DATAGRAM_QUEUE_SIZE (VMCI_MAX_DG_SIZE * 2)
48920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
49020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstruct vmci_event_payload_qp {
49120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_handle handle;  /* queue_pair handle. */
49220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u32 peer_id;		    /* Context id of attaching/detaching VM. */
49320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u32 _pad;
49420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
49520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
49620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/* Flags for VMCI queue_pair API. */
49720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangenum {
49820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	/* Fail alloc if QP not created by peer. */
49920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_QPFLAG_ATTACH_ONLY = 1 << 0,
50020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
50120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	/* Only allow attaches from local context. */
50220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_QPFLAG_LOCAL = 1 << 1,
50320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
50420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	/* Host won't block when guest is quiesced. */
50520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_QPFLAG_NONBLOCK = 1 << 2,
50620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
50720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	/* Pin data pages in ESX.  Used with NONBLOCK */
50820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_QPFLAG_PINNED = 1 << 3,
50920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
51020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	/* Update the following flag when adding new flags. */
51120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_QP_ALL_FLAGS = (VMCI_QPFLAG_ATTACH_ONLY | VMCI_QPFLAG_LOCAL |
51220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang			     VMCI_QPFLAG_NONBLOCK | VMCI_QPFLAG_PINNED),
51320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
51420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	/* Convenience flags */
51520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_QP_ASYMM = (VMCI_QPFLAG_NONBLOCK | VMCI_QPFLAG_PINNED),
51620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	VMCI_QP_ASYMM_PEER = (VMCI_QPFLAG_ATTACH_ONLY | VMCI_QP_ASYMM),
51720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
51820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
51920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
52020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * We allow at least 1024 more event datagrams from the hypervisor past the
52120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * normally allowed datagrams pending for a given context.  We define this
52220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * limit on event datagrams from the hypervisor to guard against DoS attack
52320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * from a malicious VM which could repeatedly attach to and detach from a queue
52420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * pair, causing events to be queued at the destination VM.  However, the rate
52520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * at which such events can be generated is small since it requires a VM exit
52620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * and handling of queue pair attach/detach call at the hypervisor.  Event
52720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * datagrams may be queued up at the destination VM if it has interrupts
52820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * disabled or if it is not draining events for some other reason.  1024
52920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * datagrams is a grossly conservative estimate of the time for which
53020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * interrupts may be disabled in the destination VM, but at the same time does
53120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * not exacerbate the memory pressure problem on the host by much (size of each
53220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * event datagram is small).
53320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
53420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_MAX_DATAGRAM_AND_EVENT_QUEUE_SIZE				\
53520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	(VMCI_MAX_DATAGRAM_QUEUE_SIZE +					\
53620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	 1024 * (sizeof(struct vmci_datagram) +				\
53720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang		 sizeof(struct vmci_event_data_max)))
53820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
53920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
54020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Struct used for querying, via VMCI_RESOURCES_QUERY, the availability of
54120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * hypervisor resources.  Struct size is 16 bytes. All fields in struct are
54220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * aligned to their natural alignment.
54320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
54420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstruct vmci_resource_query_hdr {
54520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_datagram hdr;
54620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u32 num_resources;
54720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u32 _padding;
54820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
54920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
55020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
55120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Convenience struct for negotiating vectors. Must match layout of
55220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * VMCIResourceQueryHdr minus the struct vmci_datagram header.
55320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
55420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstruct vmci_resource_query_msg {
55520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u32 num_resources;
55620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u32 _padding;
55720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u32 resources[1];
55820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
55920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
56020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
56120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * The maximum number of resources that can be queried using
56220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * VMCI_RESOURCE_QUERY is 31, as the result is encoded in the lower 31
56320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * bits of a positive return value. Negative values are reserved for
56420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * errors.
56520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
56620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_RESOURCE_QUERY_MAX_NUM 31
56720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
56820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/* Maximum size for the VMCI_RESOURCE_QUERY request. */
56920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_RESOURCE_QUERY_MAX_SIZE				\
57020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	(sizeof(struct vmci_resource_query_hdr) +		\
57120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	 sizeof(u32) * VMCI_RESOURCE_QUERY_MAX_NUM)
57220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
57320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
57420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Struct used for setting the notification bitmap.  All fields in
57520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * struct are aligned to their natural alignment.
57620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
57720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstruct vmci_notify_bm_set_msg {
57820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_datagram hdr;
57920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u32 bitmap_ppn;
58020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u32 _pad;
58120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
58220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
58320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
58420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Struct used for linking a doorbell handle with an index in the
58520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * notify bitmap. All fields in struct are aligned to their natural
58620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * alignment.
58720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
58820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstruct vmci_doorbell_link_msg {
58920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_datagram hdr;
59020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_handle handle;
59120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u64 notify_idx;
59220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
59320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
59420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
59520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Struct used for unlinking a doorbell handle from an index in the
59620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * notify bitmap. All fields in struct are aligned to their natural
59720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * alignment.
59820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
59920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstruct vmci_doorbell_unlink_msg {
60020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_datagram hdr;
60120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_handle handle;
60220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
60320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
60420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
60520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Struct used for generating a notification on a doorbell handle. All
60620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * fields in struct are aligned to their natural alignment.
60720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
60820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstruct vmci_doorbell_notify_msg {
60920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_datagram hdr;
61020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_handle handle;
61120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
61220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
61320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
61420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * This struct is used to contain data for events.  Size of this struct is a
61520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * multiple of 8 bytes, and all fields are aligned to their natural alignment.
61620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
61720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstruct vmci_event_data {
61820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u32 event;		/* 4 bytes. */
61920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u32 _pad;
62020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	/* Event payload is put here. */
62120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
62220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
62320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
62420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Define the different VMCI_EVENT payload data types here.  All structs must
62520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * be a multiple of 8 bytes, and fields must be aligned to their natural
62620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * alignment.
62720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
62820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstruct vmci_event_payld_ctx {
62920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u32 context_id;	/* 4 bytes. */
63020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u32 _pad;
63120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
63220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
63320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstruct vmci_event_payld_qp {
63420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_handle handle;  /* queue_pair handle. */
63520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u32 peer_id;	    /* Context id of attaching/detaching VM. */
63620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u32 _pad;
63720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
63820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
63920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
64020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * We define the following struct to get the size of the maximum event
64120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * data the hypervisor may send to the guest.  If adding a new event
64220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * payload type above, add it to the following struct too (inside the
64320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * union).
64420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
64520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstruct vmci_event_data_max {
64620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_event_data event_data;
64720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	union {
64820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang		struct vmci_event_payld_ctx context_payload;
64920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang		struct vmci_event_payld_qp qp_payload;
65020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	} ev_data_payload;
65120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
65220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
65320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
65420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Struct used for VMCI_EVENT_SUBSCRIBE/UNSUBSCRIBE and
65520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * VMCI_EVENT_HANDLER messages.  Struct size is 32 bytes.  All fields
65620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * in struct are aligned to their natural alignment.
65720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
65820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstruct vmci_event_msg {
65920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_datagram hdr;
66020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
66120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	/* Has event type and payload. */
66220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_event_data event_data;
66320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
66420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	/* Payload gets put here. */
66520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
66620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
66720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/* Event with context payload. */
66820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstruct vmci_event_ctx {
66920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_event_msg msg;
67020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_event_payld_ctx payload;
67120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
67220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
67320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/* Event with QP payload. */
67420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstruct vmci_event_qp {
67520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_event_msg msg;
67620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_event_payld_qp payload;
67720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
67820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
67920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
68020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Structs used for queue_pair alloc and detach messages.  We align fields of
68120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * these structs to 64bit boundaries.
68220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
68320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstruct vmci_qp_alloc_msg {
68420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_datagram hdr;
68520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_handle handle;
68620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u32 peer;
68720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u32 flags;
68820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u64 produce_size;
68920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u64 consume_size;
69020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u64 num_ppns;
69120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
69220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	/* List of PPNs placed here. */
69320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
69420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
69520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstruct vmci_qp_detach_msg {
69620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_datagram hdr;
69720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_handle handle;
69820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang};
69920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
70020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/* VMCI Doorbell API. */
70120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#define VMCI_FLAG_DELAYED_CB 0x01
70220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
70320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangtypedef void (*vmci_callback) (void *client_data);
70420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
70520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
70620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * struct vmci_qp - A vmw_vmci queue pair handle.
70720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang *
70820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * This structure is used as a handle to a queue pair created by
70920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * VMCI.  It is intentionally left opaque to clients.
71020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
71120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstruct vmci_qp;
71220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
71320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/* Callback needed for correctly waiting on events. */
71420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangtypedef int (*vmci_datagram_recv_cb) (void *client_data,
71520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang				      struct vmci_datagram *msg);
71620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
71720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/* VMCI Event API. */
71820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangtypedef void (*vmci_event_cb) (u32 sub_id, const struct vmci_event_data *ed,
71920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang			       void *client_data);
72020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
72120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
72220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * We use the following inline function to access the payload data
72320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * associated with an event data.
72420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
72520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstatic inline const void *
72620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangvmci_event_data_const_payload(const struct vmci_event_data *ev_data)
72720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang{
72820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	return (const char *)ev_data + sizeof(*ev_data);
72920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang}
73020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
73120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstatic inline void *vmci_event_data_payload(struct vmci_event_data *ev_data)
73220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang{
73320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	return (void *)vmci_event_data_const_payload(ev_data);
73420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang}
73520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
73620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
73720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Helper to add a given offset to a head or tail pointer. Wraps the
73820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * value of the pointer around the max size of the queue.
73920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
74020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstatic inline void vmci_qp_add_pointer(atomic64_t *var,
74120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang				       size_t add,
74220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang				       u64 size)
74320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang{
74420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u64 new_val = atomic64_read(var);
74520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
74620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	if (new_val >= size - add)
74720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang		new_val -= size;
74820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
74920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	new_val += add;
75020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
75120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	atomic64_set(var, new_val);
75220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang}
75320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
75420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
75520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Helper routine to get the Producer Tail from the supplied queue.
75620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
75720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstatic inline u64
75820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangvmci_q_header_producer_tail(const struct vmci_queue_header *q_header)
75920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang{
76020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_queue_header *qh = (struct vmci_queue_header *)q_header;
76120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	return atomic64_read(&qh->producer_tail);
76220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang}
76320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
76420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
76520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Helper routine to get the Consumer Head from the supplied queue.
76620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
76720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstatic inline u64
76820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangvmci_q_header_consumer_head(const struct vmci_queue_header *q_header)
76920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang{
77020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	struct vmci_queue_header *qh = (struct vmci_queue_header *)q_header;
77120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	return atomic64_read(&qh->consumer_head);
77220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang}
77320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
77420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
77520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Helper routine to increment the Producer Tail.  Fundamentally,
77620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * vmci_qp_add_pointer() is used to manipulate the tail itself.
77720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
77820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstatic inline void
77920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangvmci_q_header_add_producer_tail(struct vmci_queue_header *q_header,
78020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang				size_t add,
78120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang				u64 queue_size)
78220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang{
78320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	vmci_qp_add_pointer(&q_header->producer_tail, add, queue_size);
78420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang}
78520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
78620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
78720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Helper routine to increment the Consumer Head.  Fundamentally,
78820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * vmci_qp_add_pointer() is used to manipulate the head itself.
78920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
79020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstatic inline void
79120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangvmci_q_header_add_consumer_head(struct vmci_queue_header *q_header,
79220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang				size_t add,
79320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang				u64 queue_size)
79420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang{
79520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	vmci_qp_add_pointer(&q_header->consumer_head, add, queue_size);
79620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang}
79720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
79820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
79920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Helper routine for getting the head and the tail pointer for a queue.
80020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Both the VMCIQueues are needed to get both the pointers for one queue.
80120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
80220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstatic inline void
80320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangvmci_q_header_get_pointers(const struct vmci_queue_header *produce_q_header,
80420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang			   const struct vmci_queue_header *consume_q_header,
80520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang			   u64 *producer_tail,
80620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang			   u64 *consumer_head)
80720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang{
80820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	if (producer_tail)
80920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang		*producer_tail = vmci_q_header_producer_tail(produce_q_header);
81020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
81120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	if (consumer_head)
81220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang		*consumer_head = vmci_q_header_consumer_head(consume_q_header);
81320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang}
81420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
81520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstatic inline void vmci_q_header_init(struct vmci_queue_header *q_header,
81620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang				      const struct vmci_handle handle)
81720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang{
81820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	q_header->handle = handle;
81920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	atomic64_set(&q_header->producer_tail, 0);
82020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	atomic64_set(&q_header->consumer_head, 0);
82120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang}
82220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
82320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
82420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Finds available free space in a produce queue to enqueue more
82520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * data or reports an error if queue pair corruption is detected.
82620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
82720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstatic s64
82820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangvmci_q_header_free_space(const struct vmci_queue_header *produce_q_header,
82920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang			 const struct vmci_queue_header *consume_q_header,
83020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang			 const u64 produce_q_size)
83120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang{
83220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u64 tail;
83320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u64 head;
83420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	u64 free_space;
83520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
83620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	tail = vmci_q_header_producer_tail(produce_q_header);
83720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	head = vmci_q_header_consumer_head(consume_q_header);
83820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
83920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	if (tail >= produce_q_size || head >= produce_q_size)
84020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang		return VMCI_ERROR_INVALID_SIZE;
84120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
84220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	/*
84320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	 * Deduct 1 to avoid tail becoming equal to head which causes
84420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	 * ambiguity. If head and tail are equal it means that the
84520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	 * queue is empty.
84620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	 */
84720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	if (tail >= head)
84820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang		free_space = produce_q_size - (tail - head) - 1;
84920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	else
85020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang		free_space = head - tail - 1;
85120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
85220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	return free_space;
85320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang}
85420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
85520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang/*
85620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * vmci_q_header_free_space() does all the heavy lifting of
85720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * determing the number of free bytes in a Queue.  This routine,
85820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * then subtracts that size from the full size of the Queue so
85920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * the caller knows how many bytes are ready to be dequeued.
86020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * Results:
86120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * On success, available data size in bytes (up to MAX_INT64).
86220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang * On failure, appropriate error code.
86320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang */
86420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangstatic inline s64
86520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhangvmci_q_header_buf_ready(const struct vmci_queue_header *consume_q_header,
86620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang			const struct vmci_queue_header *produce_q_header,
86720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang			const u64 consume_q_size)
86820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang{
86920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	s64 free_space;
87020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
87120259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	free_space = vmci_q_header_free_space(consume_q_header,
87220259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang					      produce_q_header, consume_q_size);
87320259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	if (free_space < VMCI_SUCCESS)
87420259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang		return free_space;
87520259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
87620259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang	return consume_q_size - free_space - 1;
87720259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang}
87820259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
87920259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang
88020259849bb1ac1ffb0156eb359810e8b99cb644dGeorge Zhang#endif /* _VMW_VMCI_DEF_H_ */
881