xref: /dpdk/drivers/net/virtio/virtio.h (revision e77506397fc8005c5129e22e9e2d15d5876790fd)
1f8b60756SMaxime Coquelin /* SPDX-License-Identifier: BSD-3-Clause
2f8b60756SMaxime Coquelin  * Copyright(c) 2010-2014 Intel Corporation
3f8b60756SMaxime Coquelin  * Copyright(c) 2021 Red Hat, Inc.
4f8b60756SMaxime Coquelin  */
5f8b60756SMaxime Coquelin 
6f8b60756SMaxime Coquelin #ifndef _VIRTIO_H_
7f8b60756SMaxime Coquelin #define _VIRTIO_H_
8f8b60756SMaxime Coquelin 
9f8b60756SMaxime Coquelin #include <rte_ether.h>
10f8b60756SMaxime Coquelin 
11b4f9a45aSMaxime Coquelin /* The feature bitmap for virtio net */
12b4f9a45aSMaxime Coquelin #define VIRTIO_NET_F_CSUM	0	/* Host handles pkts w/ partial csum */
13b4f9a45aSMaxime Coquelin #define VIRTIO_NET_F_GUEST_CSUM	1	/* Guest handles pkts w/ partial csum */
14b4f9a45aSMaxime Coquelin #define VIRTIO_NET_F_MTU	3	/* Initial MTU advice. */
15b4f9a45aSMaxime Coquelin #define VIRTIO_NET_F_MAC	5	/* Host has given MAC address. */
16b4f9a45aSMaxime Coquelin #define VIRTIO_NET_F_GUEST_TSO4	7	/* Guest can handle TSOv4 in. */
17b4f9a45aSMaxime Coquelin #define VIRTIO_NET_F_GUEST_TSO6	8	/* Guest can handle TSOv6 in. */
18b4f9a45aSMaxime Coquelin #define VIRTIO_NET_F_GUEST_ECN	9	/* Guest can handle TSO[6] w/ ECN in. */
19b4f9a45aSMaxime Coquelin #define VIRTIO_NET_F_GUEST_UFO	10	/* Guest can handle UFO in. */
20b4f9a45aSMaxime Coquelin #define VIRTIO_NET_F_HOST_TSO4	11	/* Host can handle TSOv4 in. */
21b4f9a45aSMaxime Coquelin #define VIRTIO_NET_F_HOST_TSO6	12	/* Host can handle TSOv6 in. */
22b4f9a45aSMaxime Coquelin #define VIRTIO_NET_F_HOST_ECN	13	/* Host can handle TSO[6] w/ ECN in. */
23b4f9a45aSMaxime Coquelin #define VIRTIO_NET_F_HOST_UFO	14	/* Host can handle UFO in. */
24b4f9a45aSMaxime Coquelin #define VIRTIO_NET_F_MRG_RXBUF	15	/* Host can merge receive buffers. */
25b4f9a45aSMaxime Coquelin #define VIRTIO_NET_F_STATUS	16	/* virtio_net_config.status available */
26b4f9a45aSMaxime Coquelin #define VIRTIO_NET_F_CTRL_VQ	17	/* Control channel available */
27b4f9a45aSMaxime Coquelin #define VIRTIO_NET_F_CTRL_RX	18	/* Control channel RX mode support */
28b4f9a45aSMaxime Coquelin #define VIRTIO_NET_F_CTRL_VLAN	19	/* Control channel VLAN filtering */
29b4f9a45aSMaxime Coquelin #define VIRTIO_NET_F_CTRL_RX_EXTRA 20	/* Extra RX mode control support */
30b4f9a45aSMaxime Coquelin #define VIRTIO_NET_F_GUEST_ANNOUNCE 21	/* Guest can announce device on the network */
31b4f9a45aSMaxime Coquelin #define VIRTIO_NET_F_MQ		22	/* Device supports Receive Flow Steering */
32b4f9a45aSMaxime Coquelin #define VIRTIO_NET_F_CTRL_MAC_ADDR 23	/* Set MAC address */
330c9d6620SMaxime Coquelin #define VIRTIO_NET_F_RSS	60	/* RSS supported */
34b4f9a45aSMaxime Coquelin 
35b4f9a45aSMaxime Coquelin /*
36b4f9a45aSMaxime Coquelin  * Do we get callbacks when the ring is completely used,
37b4f9a45aSMaxime Coquelin  * even if we've suppressed them?
38b4f9a45aSMaxime Coquelin  */
39b4f9a45aSMaxime Coquelin #define VIRTIO_F_NOTIFY_ON_EMPTY	24
40b4f9a45aSMaxime Coquelin 
41b4f9a45aSMaxime Coquelin /* Can the device handle any descriptor layout? */
42b4f9a45aSMaxime Coquelin #define VIRTIO_F_ANY_LAYOUT		27
43b4f9a45aSMaxime Coquelin 
44b4f9a45aSMaxime Coquelin /* We support indirect buffer descriptors */
45b4f9a45aSMaxime Coquelin #define VIRTIO_RING_F_INDIRECT_DESC	28
46b4f9a45aSMaxime Coquelin 
47b4f9a45aSMaxime Coquelin #define VIRTIO_F_VERSION_1		32
48b4f9a45aSMaxime Coquelin #define VIRTIO_F_IOMMU_PLATFORM	33
49b4f9a45aSMaxime Coquelin #define VIRTIO_F_RING_PACKED		34
50b4f9a45aSMaxime Coquelin 
51b4f9a45aSMaxime Coquelin /*
52b4f9a45aSMaxime Coquelin  * Some VirtIO feature bits (currently bits 28 through 31) are
53b4f9a45aSMaxime Coquelin  * reserved for the transport being used (eg. virtio_ring), the
54b4f9a45aSMaxime Coquelin  * rest are per-device feature bits.
55b4f9a45aSMaxime Coquelin  */
56b4f9a45aSMaxime Coquelin #define VIRTIO_TRANSPORT_F_START 28
57b4f9a45aSMaxime Coquelin #define VIRTIO_TRANSPORT_F_END   34
58b4f9a45aSMaxime Coquelin 
59b4f9a45aSMaxime Coquelin /*
60b4f9a45aSMaxime Coquelin  * Inorder feature indicates that all buffers are used by the device
61b4f9a45aSMaxime Coquelin  * in the same order in which they have been made available.
62b4f9a45aSMaxime Coquelin  */
63b4f9a45aSMaxime Coquelin #define VIRTIO_F_IN_ORDER 35
64b4f9a45aSMaxime Coquelin 
65b4f9a45aSMaxime Coquelin /*
66b4f9a45aSMaxime Coquelin  * This feature indicates that memory accesses by the driver and the device
67b4f9a45aSMaxime Coquelin  * are ordered in a way described by the platform.
68b4f9a45aSMaxime Coquelin  */
69b4f9a45aSMaxime Coquelin #define VIRTIO_F_ORDER_PLATFORM 36
70b4f9a45aSMaxime Coquelin 
71b4f9a45aSMaxime Coquelin /*
72b4f9a45aSMaxime Coquelin  * This feature indicates that the driver passes extra data (besides
73b4f9a45aSMaxime Coquelin  * identifying the virtqueue) in its device notifications.
74b4f9a45aSMaxime Coquelin  */
75b4f9a45aSMaxime Coquelin #define VIRTIO_F_NOTIFICATION_DATA 38
76b4f9a45aSMaxime Coquelin 
77b4f9a45aSMaxime Coquelin /* Device set linkspeed and duplex */
78b4f9a45aSMaxime Coquelin #define VIRTIO_NET_F_SPEED_DUPLEX 63
79b4f9a45aSMaxime Coquelin 
80b4f9a45aSMaxime Coquelin /*
81b4f9a45aSMaxime Coquelin  * The Guest publishes the used index for which it expects an interrupt
82b4f9a45aSMaxime Coquelin  * at the end of the avail ring. Host should ignore the avail->flags field
83b4f9a45aSMaxime Coquelin  *
84b4f9a45aSMaxime Coquelin  * The Host publishes the avail index for which it expects a kick
85b4f9a45aSMaxime Coquelin  * at the end of the used ring. Guest should ignore the used->flags field.
86b4f9a45aSMaxime Coquelin  */
87b4f9a45aSMaxime Coquelin #define VIRTIO_RING_F_EVENT_IDX		29
88b4f9a45aSMaxime Coquelin 
89b4f9a45aSMaxime Coquelin #define VIRTIO_NET_S_LINK_UP	1	/* Link is up */
90b4f9a45aSMaxime Coquelin #define VIRTIO_NET_S_ANNOUNCE	2	/* Announcement is needed */
91b4f9a45aSMaxime Coquelin 
927990d039SMaxime Coquelin /*
937990d039SMaxime Coquelin  * Each virtqueue indirect descriptor list must be physically contiguous.
947990d039SMaxime Coquelin  * To allow us to malloc(9) each list individually, limit the number
957990d039SMaxime Coquelin  * supported to what will fit in one page. With 4KB pages, this is a limit
967990d039SMaxime Coquelin  * of 256 descriptors. If there is ever a need for more, we can switch to
977990d039SMaxime Coquelin  * contigmalloc(9) for the larger allocations, similar to what
987990d039SMaxime Coquelin  * bus_dmamem_alloc(9) does.
997990d039SMaxime Coquelin  *
1007990d039SMaxime Coquelin  * Note the sizeof(struct vring_desc) is 16 bytes.
1017990d039SMaxime Coquelin  */
102924e6b76SThomas Monjalon #define VIRTIO_MAX_INDIRECT ((int)(rte_mem_page_size() / 16))
1037990d039SMaxime Coquelin 
1040c9d6620SMaxime Coquelin /*  Virtio RSS hash types */
1050c9d6620SMaxime Coquelin #define VIRTIO_NET_HASH_TYPE_IPV4	RTE_BIT32(0)
1060c9d6620SMaxime Coquelin #define VIRTIO_NET_HASH_TYPE_TCPV4	RTE_BIT32(1)
1070c9d6620SMaxime Coquelin #define VIRTIO_NET_HASH_TYPE_UDPV4	RTE_BIT32(2)
1080c9d6620SMaxime Coquelin #define VIRTIO_NET_HASH_TYPE_IPV6	RTE_BIT32(3)
1090c9d6620SMaxime Coquelin #define VIRTIO_NET_HASH_TYPE_TCPV6	RTE_BIT32(4)
1100c9d6620SMaxime Coquelin #define VIRTIO_NET_HASH_TYPE_UDPV6	RTE_BIT32(5)
1110c9d6620SMaxime Coquelin #define VIRTIO_NET_HASH_TYPE_IP_EX	RTE_BIT32(6)
1120c9d6620SMaxime Coquelin #define VIRTIO_NET_HASH_TYPE_TCP_EX	RTE_BIT32(7)
1130c9d6620SMaxime Coquelin #define VIRTIO_NET_HASH_TYPE_UDP_EX	RTE_BIT32(8)
1140c9d6620SMaxime Coquelin 
1150c9d6620SMaxime Coquelin #define VIRTIO_NET_HASH_TYPE_MASK ( \
1160c9d6620SMaxime Coquelin 	VIRTIO_NET_HASH_TYPE_IPV4 | \
1170c9d6620SMaxime Coquelin 	VIRTIO_NET_HASH_TYPE_TCPV4 | \
1180c9d6620SMaxime Coquelin 	VIRTIO_NET_HASH_TYPE_UDPV4 | \
1190c9d6620SMaxime Coquelin 	VIRTIO_NET_HASH_TYPE_IPV6 | \
1200c9d6620SMaxime Coquelin 	VIRTIO_NET_HASH_TYPE_TCPV6 | \
1210c9d6620SMaxime Coquelin 	VIRTIO_NET_HASH_TYPE_UDPV6 | \
1220c9d6620SMaxime Coquelin 	VIRTIO_NET_HASH_TYPE_IP_EX | \
1230c9d6620SMaxime Coquelin 	VIRTIO_NET_HASH_TYPE_TCP_EX | \
1240c9d6620SMaxime Coquelin 	VIRTIO_NET_HASH_TYPE_UDP_EX)
1250c9d6620SMaxime Coquelin 
1260c9d6620SMaxime Coquelin 
1279328e105SMaxime Coquelin /* VirtIO device IDs. */
1289328e105SMaxime Coquelin #define VIRTIO_ID_NETWORK  0x01
1299328e105SMaxime Coquelin #define VIRTIO_ID_BLOCK    0x02
1309328e105SMaxime Coquelin #define VIRTIO_ID_CONSOLE  0x03
1319328e105SMaxime Coquelin #define VIRTIO_ID_ENTROPY  0x04
1329328e105SMaxime Coquelin #define VIRTIO_ID_BALLOON  0x05
1339328e105SMaxime Coquelin #define VIRTIO_ID_IOMEMORY 0x06
1349328e105SMaxime Coquelin #define VIRTIO_ID_9P       0x09
1359328e105SMaxime Coquelin 
1369328e105SMaxime Coquelin /* Status byte for guest to report progress. */
1379328e105SMaxime Coquelin #define VIRTIO_CONFIG_STATUS_RESET		0x00
1389328e105SMaxime Coquelin #define VIRTIO_CONFIG_STATUS_ACK		0x01
1399328e105SMaxime Coquelin #define VIRTIO_CONFIG_STATUS_DRIVER		0x02
1409328e105SMaxime Coquelin #define VIRTIO_CONFIG_STATUS_DRIVER_OK		0x04
1419328e105SMaxime Coquelin #define VIRTIO_CONFIG_STATUS_FEATURES_OK	0x08
1429328e105SMaxime Coquelin #define VIRTIO_CONFIG_STATUS_DEV_NEED_RESET	0x40
1439328e105SMaxime Coquelin #define VIRTIO_CONFIG_STATUS_FAILED		0x80
1449328e105SMaxime Coquelin 
1456a504290SMaxime Coquelin /* The bit of the ISR which indicates a device has an interrupt. */
1466a504290SMaxime Coquelin #define VIRTIO_ISR_INTR   0x1
1476a504290SMaxime Coquelin /* The bit of the ISR which indicates a device configuration change. */
1486a504290SMaxime Coquelin #define VIRTIO_ISR_CONFIG 0x2
1496a504290SMaxime Coquelin /* Vector value used to disable MSI for queue. */
1506a504290SMaxime Coquelin #define VIRTIO_MSI_NO_VECTOR 0xFFFF
1516a504290SMaxime Coquelin 
152df968842SMaxime Coquelin /* The alignment to use between consumer and producer parts of vring. */
153df968842SMaxime Coquelin #define VIRTIO_VRING_ALIGN 4096
154df968842SMaxime Coquelin 
1559328e105SMaxime Coquelin /*
1569328e105SMaxime Coquelin  * This structure is just a reference to read net device specific
1579328e105SMaxime Coquelin  * config space; it is just a shadow structure.
1589328e105SMaxime Coquelin  *
1599328e105SMaxime Coquelin  */
160*e7750639SAndre Muezerie struct __rte_packed_begin virtio_net_config {
1619328e105SMaxime Coquelin 	/* The config defining mac address (if VIRTIO_NET_F_MAC) */
1629328e105SMaxime Coquelin 	uint8_t    mac[RTE_ETHER_ADDR_LEN];
1639328e105SMaxime Coquelin 	/* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */
1649328e105SMaxime Coquelin 	uint16_t   status;
1659328e105SMaxime Coquelin 	uint16_t   max_virtqueue_pairs;
1669328e105SMaxime Coquelin 	uint16_t   mtu;
1679328e105SMaxime Coquelin 	/*
1689328e105SMaxime Coquelin 	 * speed, in units of 1Mb. All values 0 to INT_MAX are legal.
1699328e105SMaxime Coquelin 	 * Any other value stands for unknown.
1709328e105SMaxime Coquelin 	 */
1719328e105SMaxime Coquelin 	uint32_t speed;
1729328e105SMaxime Coquelin 	/*
1739328e105SMaxime Coquelin 	 * 0x00 - half duplex
1749328e105SMaxime Coquelin 	 * 0x01 - full duplex
1759328e105SMaxime Coquelin 	 * Any other value stands for unknown.
1769328e105SMaxime Coquelin 	 */
1779328e105SMaxime Coquelin 	uint8_t duplex;
1780c9d6620SMaxime Coquelin 	uint8_t rss_max_key_size;
1790c9d6620SMaxime Coquelin 	uint16_t rss_max_indirection_table_length;
1800c9d6620SMaxime Coquelin 	uint32_t supported_hash_types;
181*e7750639SAndre Muezerie } __rte_packed_end;
1829328e105SMaxime Coquelin 
183f8b60756SMaxime Coquelin struct virtio_hw {
184f8b60756SMaxime Coquelin 	struct virtqueue **vqs;
185f8b60756SMaxime Coquelin 	uint64_t guest_features;
186f8b60756SMaxime Coquelin 	uint16_t vtnet_hdr_size;
187f8b60756SMaxime Coquelin 	uint8_t started;
188f8b60756SMaxime Coquelin 	uint8_t weak_barriers;
189f8b60756SMaxime Coquelin 	uint8_t vlan_strip;
1904e8169ebSIvan Ilchenko 	bool rx_ol_scatter;
191f8b60756SMaxime Coquelin 	uint8_t has_tx_offload;
192f8b60756SMaxime Coquelin 	uint8_t has_rx_offload;
193f8b60756SMaxime Coquelin 	uint8_t use_vec_rx;
194f8b60756SMaxime Coquelin 	uint8_t use_vec_tx;
195f8b60756SMaxime Coquelin 	uint8_t use_inorder_rx;
196f8b60756SMaxime Coquelin 	uint8_t use_inorder_tx;
197f8b60756SMaxime Coquelin 	uint8_t opened;
198f8b60756SMaxime Coquelin 	uint16_t port_id;
199f8b60756SMaxime Coquelin 	uint8_t mac_addr[RTE_ETHER_ADDR_LEN];
2003c3c54cfSIvan Ilchenko 	/*
2013c3c54cfSIvan Ilchenko 	 * Speed is specified via 'speed' devarg or
2023c3c54cfSIvan Ilchenko 	 * negotiated via VIRTIO_NET_F_SPEED_DUPLEX
2033c3c54cfSIvan Ilchenko 	 */
2043c3c54cfSIvan Ilchenko 	bool get_speed_via_feat;
205f8b60756SMaxime Coquelin 	uint32_t speed;  /* link speed in MB */
206f8b60756SMaxime Coquelin 	uint8_t duplex;
2076a504290SMaxime Coquelin 	uint8_t intr_lsc;
208f8b60756SMaxime Coquelin 	uint16_t max_mtu;
2094e8169ebSIvan Ilchenko 	size_t max_rx_pkt_len;
210f8b60756SMaxime Coquelin 	/*
211f8b60756SMaxime Coquelin 	 * App management thread and virtio interrupt handler thread
212f8b60756SMaxime Coquelin 	 * both can change device state, this lock is meant to avoid
213f8b60756SMaxime Coquelin 	 * such a contention.
214f8b60756SMaxime Coquelin 	 */
215f8b60756SMaxime Coquelin 	rte_spinlock_t state_lock;
216f8b60756SMaxime Coquelin 	struct rte_mbuf **inject_pkts;
217f8b60756SMaxime Coquelin 	uint16_t max_queue_pairs;
2180c9d6620SMaxime Coquelin 	uint16_t rss_rx_queues;
2190c9d6620SMaxime Coquelin 	uint32_t rss_hash_types;
2200c9d6620SMaxime Coquelin 	uint16_t *rss_reta;
2210c9d6620SMaxime Coquelin 	uint8_t *rss_key;
222f8b60756SMaxime Coquelin 	uint64_t req_guest_features;
223f8b60756SMaxime Coquelin 	struct virtnet_ctl *cvq;
224ba55c94aSMaxime Coquelin 	bool use_va;
225f8b60756SMaxime Coquelin };
226f8b60756SMaxime Coquelin 
227f8b60756SMaxime Coquelin struct virtio_ops {
228f8b60756SMaxime Coquelin 	void (*read_dev_cfg)(struct virtio_hw *hw, size_t offset, void *dst, int len);
229f8b60756SMaxime Coquelin 	void (*write_dev_cfg)(struct virtio_hw *hw, size_t offset, const void *src, int len);
230f8b60756SMaxime Coquelin 	uint8_t (*get_status)(struct virtio_hw *hw);
231f8b60756SMaxime Coquelin 	void (*set_status)(struct virtio_hw *hw, uint8_t status);
232f8b60756SMaxime Coquelin 	uint64_t (*get_features)(struct virtio_hw *hw);
233f8b60756SMaxime Coquelin 	void (*set_features)(struct virtio_hw *hw, uint64_t features);
234f8b60756SMaxime Coquelin 	int (*features_ok)(struct virtio_hw *hw);
235f8b60756SMaxime Coquelin 	uint8_t (*get_isr)(struct virtio_hw *hw);
236f8b60756SMaxime Coquelin 	uint16_t (*set_config_irq)(struct virtio_hw *hw, uint16_t vec);
237f8b60756SMaxime Coquelin 	uint16_t (*set_queue_irq)(struct virtio_hw *hw, struct virtqueue *vq, uint16_t vec);
238f8b60756SMaxime Coquelin 	uint16_t (*get_queue_num)(struct virtio_hw *hw, uint16_t queue_id);
239f8b60756SMaxime Coquelin 	int (*setup_queue)(struct virtio_hw *hw, struct virtqueue *vq);
240f8b60756SMaxime Coquelin 	void (*del_queue)(struct virtio_hw *hw, struct virtqueue *vq);
241f8b60756SMaxime Coquelin 	void (*notify_queue)(struct virtio_hw *hw, struct virtqueue *vq);
242f8b60756SMaxime Coquelin 	void (*intr_detect)(struct virtio_hw *hw);
243f8b60756SMaxime Coquelin 	int (*dev_close)(struct virtio_hw *hw);
244f8b60756SMaxime Coquelin };
245f8b60756SMaxime Coquelin 
246f8b60756SMaxime Coquelin /*
247f8b60756SMaxime Coquelin  * This structure stores per-process data. Only virtio_ops for now.
248f8b60756SMaxime Coquelin  */
249f8b60756SMaxime Coquelin struct virtio_hw_internal {
250f8b60756SMaxime Coquelin 	const struct virtio_ops *virtio_ops;
251f8b60756SMaxime Coquelin };
252f8b60756SMaxime Coquelin 
253f8b60756SMaxime Coquelin #define VIRTIO_OPS(hw)	(virtio_hw_internal[(hw)->port_id].virtio_ops)
254f8b60756SMaxime Coquelin 
255f8b60756SMaxime Coquelin extern struct virtio_hw_internal virtio_hw_internal[RTE_MAX_ETHPORTS];
256f8b60756SMaxime Coquelin 
257f8b60756SMaxime Coquelin 
258b4f9a45aSMaxime Coquelin static inline int
259b4f9a45aSMaxime Coquelin virtio_with_feature(struct virtio_hw *hw, uint64_t bit)
260b4f9a45aSMaxime Coquelin {
261b4f9a45aSMaxime Coquelin 	return (hw->guest_features & (1ULL << bit)) != 0;
262b4f9a45aSMaxime Coquelin }
263b4f9a45aSMaxime Coquelin 
264b4f9a45aSMaxime Coquelin static inline int
265b4f9a45aSMaxime Coquelin virtio_with_packed_queue(struct virtio_hw *hw)
266b4f9a45aSMaxime Coquelin {
267b4f9a45aSMaxime Coquelin 	return virtio_with_feature(hw, VIRTIO_F_RING_PACKED);
268b4f9a45aSMaxime Coquelin }
269b4f9a45aSMaxime Coquelin 
270b4f9a45aSMaxime Coquelin uint64_t virtio_negotiate_features(struct virtio_hw *hw, uint64_t host_features);
2719328e105SMaxime Coquelin uint8_t virtio_get_status(struct virtio_hw *hw);
2729328e105SMaxime Coquelin void virtio_set_status(struct virtio_hw *hw, uint8_t status);
2739328e105SMaxime Coquelin void virtio_write_dev_config(struct virtio_hw *hw, size_t offset, const void *src, int length);
2749328e105SMaxime Coquelin void virtio_read_dev_config(struct virtio_hw *hw, size_t offset, void *dst, int length);
2759328e105SMaxime Coquelin void virtio_reset(struct virtio_hw *hw);
2769328e105SMaxime Coquelin void virtio_reinit_complete(struct virtio_hw *hw);
2776a504290SMaxime Coquelin uint8_t virtio_get_isr(struct virtio_hw *hw);
278f8b60756SMaxime Coquelin #endif /* _VIRTIO_H_ */
279