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