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 */ 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 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