1 /* SPDX-License-Identifier: BSD-3-Clause */
2 
3 #ifndef _VMBUS_BUF_H_
4 #define _VMBUS_BUF_H_
5 
6 #include <stdbool.h>
7 #include <stdint.h>
8 
9 #define __packed   __attribute__((__packed__))
10 #define unlikely(x)	__builtin_expect(!!(x), 0)
11 
12 #define ICMSGHDRFLAG_TRANSACTION	1
13 #define ICMSGHDRFLAG_REQUEST		2
14 #define ICMSGHDRFLAG_RESPONSE		4
15 
16 #define IC_VERSION_NEGOTIATION_MAX_VER_COUNT 100
17 #define ICMSG_HDR (sizeof(struct vmbuspipe_hdr) + sizeof(struct icmsg_hdr))
18 #define ICMSG_NEGOTIATE_PKT_SIZE(icframe_vercnt, icmsg_vercnt) \
19 	(ICMSG_HDR + sizeof(struct icmsg_negotiate) + \
20 	 (((icframe_vercnt) + (icmsg_vercnt)) * sizeof(struct ic_version)))
21 
22 /*
23  * Channel packets
24  */
25 
26 /* Channel packet flags */
27 #define VMBUS_CHANPKT_TYPE_INBAND	0x0006
28 #define VMBUS_CHANPKT_TYPE_RXBUF	0x0007
29 #define VMBUS_CHANPKT_TYPE_GPA		0x0009
30 #define VMBUS_CHANPKT_TYPE_COMP		0x000b
31 
32 #define VMBUS_CHANPKT_FLAG_NONE		0
33 #define VMBUS_CHANPKT_FLAG_RC		0x0001  /* report completion */
34 
35 #define VMBUS_CHANPKT_SIZE_SHIFT	3
36 #define VMBUS_CHANPKT_SIZE_ALIGN	BIT(VMBUS_CHANPKT_SIZE_SHIFT)
37 #define VMBUS_CHANPKT_HLEN_MIN		\
38 	(sizeof(struct vmbus_chanpkt_hdr) >> VMBUS_CHANPKT_SIZE_SHIFT)
39 
40 /*
41  * Buffer ring
42  */
43 struct vmbus_bufring {
44 	volatile uint32_t windex;
45 	volatile uint32_t rindex;
46 
47 	/*
48 	 * Interrupt mask {0,1}
49 	 *
50 	 * For TX bufring, host set this to 1, when it is processing
51 	 * the TX bufring, so that we can safely skip the TX event
52 	 * notification to host.
53 	 *
54 	 * For RX bufring, once this is set to 1 by us, host will not
55 	 * further dispatch interrupts to us, even if there are data
56 	 * pending on the RX bufring.  This effectively disables the
57 	 * interrupt of the channel to which this RX bufring is attached.
58 	 */
59 	volatile uint32_t imask;
60 
61 	/*
62 	 * Win8 uses some of the reserved bits to implement
63 	 * interrupt driven flow management. On the send side
64 	 * we can request that the receiver interrupt the sender
65 	 * when the ring transitions from being full to being able
66 	 * to handle a message of size "pending_send_sz".
67 	 *
68 	 * Add necessary state for this enhancement.
69 	 */
70 	volatile uint32_t pending_send;
71 	uint32_t reserved1[12];
72 
73 	union {
74 		struct {
75 			uint32_t feat_pending_send_sz:1;
76 		};
77 		uint32_t value;
78 	} feature_bits;
79 
80 	/* Pad it to rte_mem_page_size() so that data starts on page boundary */
81 	uint8_t	reserved2[4028];
82 
83 	/*
84 	 * Ring data starts here + RingDataStartOffset
85 	 * !!! DO NOT place any fields below this !!!
86 	 */
87 	uint8_t data[];
88 } __packed;
89 
90 struct vmbus_br {
91 	struct vmbus_bufring *vbr;
92 	uint32_t	dsize;
93 	uint32_t	windex; /* next available location */
94 };
95 
96 struct vmbus_chanpkt_hdr {
97 	uint16_t	type;	/* VMBUS_CHANPKT_TYPE_ */
98 	uint16_t	hlen;	/* header len, in 8 bytes */
99 	uint16_t	tlen;	/* total len, in 8 bytes */
100 	uint16_t	flags;	/* VMBUS_CHANPKT_FLAG_ */
101 	uint64_t	xactid;
102 } __packed;
103 
104 struct vmbus_chanpkt {
105 	struct vmbus_chanpkt_hdr hdr;
106 } __packed;
107 
108 struct vmbuspipe_hdr {
109 	unsigned int flags;
110 	unsigned int msgsize;
111 } __packed;
112 
113 struct ic_version {
114 	unsigned short major;
115 	unsigned short minor;
116 } __packed;
117 
118 struct icmsg_negotiate {
119 	unsigned short icframe_vercnt;
120 	unsigned short icmsg_vercnt;
121 	unsigned int reserved;
122 	struct ic_version icversion_data[]; /* any size array */
123 } __packed;
124 
125 struct icmsg_hdr {
126 	struct ic_version icverframe;
127 	unsigned short icmsgtype;
128 	struct ic_version icvermsg;
129 	unsigned short icmsgsize;
130 	unsigned int status;
131 	unsigned char ictransaction_id;
132 	unsigned char icflags;
133 	unsigned char reserved[2];
134 } __packed;
135 
136 int rte_vmbus_chan_recv_raw(struct vmbus_br *rxbr, void *data, uint32_t *len);
137 int rte_vmbus_chan_send(struct vmbus_br *txbr, uint16_t type, void *data,
138 			uint32_t dlen, uint32_t flags);
139 void vmbus_br_setup(struct vmbus_br *br, void *buf, unsigned int blen);
140 void *vmbus_uio_map(int *fd, int size);
141 
142 /* Amount of space available for write */
vmbus_br_availwrite(const struct vmbus_br * br,uint32_t windex)143 static inline uint32_t vmbus_br_availwrite(const struct vmbus_br *br, uint32_t windex)
144 {
145 	uint32_t rindex = br->vbr->rindex;
146 
147 	if (windex >= rindex)
148 		return br->dsize - (windex - rindex);
149 	else
150 		return rindex - windex;
151 }
152 
vmbus_br_availread(const struct vmbus_br * br)153 static inline uint32_t vmbus_br_availread(const struct vmbus_br *br)
154 {
155 	return br->dsize - vmbus_br_availwrite(br, br->vbr->windex);
156 }
157 
158 #endif	/* !_VMBUS_BUF_H_ */
159