xref: /dpdk/drivers/net/virtio/virtio_ring.h (revision 802a0389b54599b04b5e873dd9bc3db012f3ba65)
15566a3e3SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
25566a3e3SBruce Richardson  * Copyright(c) 2010-2014 Intel Corporation
36c3169a3SBruce Richardson  */
46c3169a3SBruce Richardson 
56c3169a3SBruce Richardson #ifndef _VIRTIO_RING_H_
66c3169a3SBruce Richardson #define _VIRTIO_RING_H_
76c3169a3SBruce Richardson 
86c3169a3SBruce Richardson #include <stdint.h>
96c3169a3SBruce Richardson 
106c3169a3SBruce Richardson #include <rte_common.h>
116c3169a3SBruce Richardson 
126c3169a3SBruce Richardson /* This marks a buffer as continuing via the next field. */
136c3169a3SBruce Richardson #define VRING_DESC_F_NEXT       1
146c3169a3SBruce Richardson /* This marks a buffer as write-only (otherwise read-only). */
156c3169a3SBruce Richardson #define VRING_DESC_F_WRITE      2
166c3169a3SBruce Richardson /* This means the buffer contains a list of buffer descriptors. */
176c3169a3SBruce Richardson #define VRING_DESC_F_INDIRECT   4
1812e9e70cSTiwei Bie 
194c3f5822SJens Freimann /* This flag means the descriptor was made available by the driver */
2012e9e70cSTiwei Bie #define VRING_PACKED_DESC_F_AVAIL	(1 << 7)
214c3f5822SJens Freimann /* This flag means the descriptor was used by the device */
2212e9e70cSTiwei Bie #define VRING_PACKED_DESC_F_USED	(1 << 15)
2312e9e70cSTiwei Bie 
2412e9e70cSTiwei Bie /* Frequently used combinations */
2512e9e70cSTiwei Bie #define VRING_PACKED_DESC_F_AVAIL_USED	(VRING_PACKED_DESC_F_AVAIL | \
2612e9e70cSTiwei Bie 					 VRING_PACKED_DESC_F_USED)
276c3169a3SBruce Richardson 
286c3169a3SBruce Richardson /* The Host uses this in used->flags to advise the Guest: don't kick me
296c3169a3SBruce Richardson  * when you add a buffer.  It's unreliable, so it's simply an
306c3169a3SBruce Richardson  * optimization.  Guest will still kick if it's out of buffers. */
316c3169a3SBruce Richardson #define VRING_USED_F_NO_NOTIFY  1
326c3169a3SBruce Richardson /* The Guest uses this in avail->flags to advise the Host: don't
336c3169a3SBruce Richardson  * interrupt me when you consume a buffer.  It's unreliable, so it's
346c3169a3SBruce Richardson  * simply an optimization.  */
356c3169a3SBruce Richardson #define VRING_AVAIL_F_NO_INTERRUPT  1
366c3169a3SBruce Richardson 
376c3169a3SBruce Richardson /* VirtIO ring descriptors: 16 bytes.
386c3169a3SBruce Richardson  * These can chain together via "next". */
396c3169a3SBruce Richardson struct vring_desc {
406c3169a3SBruce Richardson 	uint64_t addr;  /*  Address (guest-physical). */
416c3169a3SBruce Richardson 	uint32_t len;   /* Length. */
426c3169a3SBruce Richardson 	uint16_t flags; /* The flags as indicated above. */
436c3169a3SBruce Richardson 	uint16_t next;  /* We chain unused descriptors via this. */
446c3169a3SBruce Richardson };
456c3169a3SBruce Richardson 
466c3169a3SBruce Richardson struct vring_avail {
476c3169a3SBruce Richardson 	uint16_t flags;
486c3169a3SBruce Richardson 	uint16_t idx;
49013b4c52SBruce Richardson 	uint16_t ring[];
506c3169a3SBruce Richardson };
516c3169a3SBruce Richardson 
526c3169a3SBruce Richardson /* id is a 16bit index. uint32_t is used here for ids for padding reasons. */
536c3169a3SBruce Richardson struct vring_used_elem {
546c3169a3SBruce Richardson 	/* Index of start of used descriptor chain. */
556c3169a3SBruce Richardson 	uint32_t id;
566c3169a3SBruce Richardson 	/* Total length of the descriptor chain which was written to. */
576c3169a3SBruce Richardson 	uint32_t len;
586c3169a3SBruce Richardson };
596c3169a3SBruce Richardson 
606c3169a3SBruce Richardson struct vring_used {
616c3169a3SBruce Richardson 	uint16_t flags;
62e12a0166STyler Retzlaff 	RTE_ATOMIC(uint16_t) idx;
63013b4c52SBruce Richardson 	struct vring_used_elem ring[];
646c3169a3SBruce Richardson };
656c3169a3SBruce Richardson 
664c3f5822SJens Freimann /* For support of packed virtqueues in Virtio 1.1 the format of descriptors
674c3f5822SJens Freimann  * looks like this.
684c3f5822SJens Freimann  */
694c3f5822SJens Freimann struct vring_packed_desc {
704c3f5822SJens Freimann 	uint64_t addr;
714c3f5822SJens Freimann 	uint32_t len;
724c3f5822SJens Freimann 	uint16_t id;
73e12a0166STyler Retzlaff 	RTE_ATOMIC(uint16_t) flags;
744c3f5822SJens Freimann };
754c3f5822SJens Freimann 
764c3f5822SJens Freimann #define RING_EVENT_FLAGS_ENABLE 0x0
774c3f5822SJens Freimann #define RING_EVENT_FLAGS_DISABLE 0x1
784c3f5822SJens Freimann #define RING_EVENT_FLAGS_DESC 0x2
794c3f5822SJens Freimann struct vring_packed_desc_event {
804c3f5822SJens Freimann 	uint16_t desc_event_off_wrap;
814c3f5822SJens Freimann 	uint16_t desc_event_flags;
824c3f5822SJens Freimann };
834c3f5822SJens Freimann 
844c3f5822SJens Freimann struct vring_packed {
854c3f5822SJens Freimann 	unsigned int num;
86*802a0389SSrujana Challa 	rte_iova_t desc_iova;
874cdc4d98STiwei Bie 	struct vring_packed_desc *desc;
884cdc4d98STiwei Bie 	struct vring_packed_desc_event *driver;
894cdc4d98STiwei Bie 	struct vring_packed_desc_event *device;
904c3f5822SJens Freimann };
914c3f5822SJens Freimann 
926c3169a3SBruce Richardson struct vring {
936c3169a3SBruce Richardson 	unsigned int num;
94*802a0389SSrujana Challa 	rte_iova_t desc_iova;
956c3169a3SBruce Richardson 	struct vring_desc  *desc;
966c3169a3SBruce Richardson 	struct vring_avail *avail;
976c3169a3SBruce Richardson 	struct vring_used  *used;
986c3169a3SBruce Richardson };
996c3169a3SBruce Richardson 
1006c3169a3SBruce Richardson /* The standard layout for the ring is a continuous chunk of memory which
1016c3169a3SBruce Richardson  * looks like this.  We assume num is a power of 2.
1026c3169a3SBruce Richardson  *
1036c3169a3SBruce Richardson  * struct vring {
1046c3169a3SBruce Richardson  *      // The actual descriptors (16 bytes each)
1056c3169a3SBruce Richardson  *      struct vring_desc desc[num];
1066c3169a3SBruce Richardson  *
1076c3169a3SBruce Richardson  *      // A ring of available descriptor heads with free-running index.
1086c3169a3SBruce Richardson  *      __u16 avail_flags;
1096c3169a3SBruce Richardson  *      __u16 avail_idx;
1106c3169a3SBruce Richardson  *      __u16 available[num];
1116c3169a3SBruce Richardson  *      __u16 used_event_idx;
1126c3169a3SBruce Richardson  *
1136c3169a3SBruce Richardson  *      // Padding to the next align boundary.
1146c3169a3SBruce Richardson  *      char pad[];
1156c3169a3SBruce Richardson  *
1166c3169a3SBruce Richardson  *      // A ring of used descriptor heads with free-running index.
1176c3169a3SBruce Richardson  *      __u16 used_flags;
1186c3169a3SBruce Richardson  *      __u16 used_idx;
1196c3169a3SBruce Richardson  *      struct vring_used_elem used[num];
1206c3169a3SBruce Richardson  *      __u16 avail_event_idx;
1216c3169a3SBruce Richardson  * };
1226c3169a3SBruce Richardson  *
1236c3169a3SBruce Richardson  * NOTE: for VirtIO PCI, align is 4096.
1246c3169a3SBruce Richardson  */
1256c3169a3SBruce Richardson 
1266c3169a3SBruce Richardson /*
1276c3169a3SBruce Richardson  * We publish the used event index at the end of the available ring, and vice
1286c3169a3SBruce Richardson  * versa. They are at the end for backwards compatibility.
1296c3169a3SBruce Richardson  */
1306c3169a3SBruce Richardson #define vring_used_event(vr)  ((vr)->avail->ring[(vr)->num])
1316c3169a3SBruce Richardson #define vring_avail_event(vr) (*(uint16_t *)&(vr)->used->ring[(vr)->num])
1326c3169a3SBruce Richardson 
1331e7bd238SStephen Hemminger static inline size_t
vring_size(struct virtio_hw * hw,unsigned int num,unsigned long align)134f803734bSJens Freimann vring_size(struct virtio_hw *hw, unsigned int num, unsigned long align)
1356c3169a3SBruce Richardson {
1361e7bd238SStephen Hemminger 	size_t size;
1376c3169a3SBruce Richardson 
138b4f9a45aSMaxime Coquelin 	if (virtio_with_packed_queue(hw)) {
139f803734bSJens Freimann 		size = num * sizeof(struct vring_packed_desc);
140f803734bSJens Freimann 		size += sizeof(struct vring_packed_desc_event);
141f803734bSJens Freimann 		size = RTE_ALIGN_CEIL(size, align);
142f803734bSJens Freimann 		size += sizeof(struct vring_packed_desc_event);
143f803734bSJens Freimann 		return size;
144f803734bSJens Freimann 	}
145f803734bSJens Freimann 
1466c3169a3SBruce Richardson 	size = num * sizeof(struct vring_desc);
1476c3169a3SBruce Richardson 	size += sizeof(struct vring_avail) + (num * sizeof(uint16_t));
1486c3169a3SBruce Richardson 	size = RTE_ALIGN_CEIL(size, align);
1496c3169a3SBruce Richardson 	size += sizeof(struct vring_used) +
1506c3169a3SBruce Richardson 		(num * sizeof(struct vring_used_elem));
1516c3169a3SBruce Richardson 	return size;
1526c3169a3SBruce Richardson }
1536c3169a3SBruce Richardson static inline void
vring_init_split(struct vring * vr,uint8_t * p,rte_iova_t iova,unsigned long align,unsigned int num)154*802a0389SSrujana Challa vring_init_split(struct vring *vr, uint8_t *p, rte_iova_t iova,
155*802a0389SSrujana Challa 		 unsigned long align, unsigned int num)
1566c3169a3SBruce Richardson {
1576c3169a3SBruce Richardson 	vr->num = num;
1586c3169a3SBruce Richardson 	vr->desc = (struct vring_desc *) p;
159*802a0389SSrujana Challa 	vr->desc_iova = iova;
1606c3169a3SBruce Richardson 	vr->avail = (struct vring_avail *) (p +
1616c3169a3SBruce Richardson 		num * sizeof(struct vring_desc));
1626c3169a3SBruce Richardson 	vr->used = (void *)
1636c3169a3SBruce Richardson 		RTE_ALIGN_CEIL((uintptr_t)(&vr->avail->ring[num]), align);
1646c3169a3SBruce Richardson }
1656c3169a3SBruce Richardson 
166f803734bSJens Freimann static inline void
vring_init_packed(struct vring_packed * vr,uint8_t * p,rte_iova_t iova,unsigned long align,unsigned int num)167*802a0389SSrujana Challa vring_init_packed(struct vring_packed *vr, uint8_t *p, rte_iova_t iova,
168*802a0389SSrujana Challa 		  unsigned long align, unsigned int num)
169f803734bSJens Freimann {
170f803734bSJens Freimann 	vr->num = num;
1714cdc4d98STiwei Bie 	vr->desc = (struct vring_packed_desc *)p;
172*802a0389SSrujana Challa 	vr->desc_iova = iova;
1734cdc4d98STiwei Bie 	vr->driver = (struct vring_packed_desc_event *)(p +
174f803734bSJens Freimann 			vr->num * sizeof(struct vring_packed_desc));
1754cdc4d98STiwei Bie 	vr->device = (struct vring_packed_desc_event *)
1764cdc4d98STiwei Bie 		RTE_ALIGN_CEIL(((uintptr_t)vr->driver +
177f803734bSJens Freimann 				sizeof(struct vring_packed_desc_event)), align);
178f803734bSJens Freimann }
179f803734bSJens Freimann 
1806c3169a3SBruce Richardson /*
1816c3169a3SBruce Richardson  * The following is used with VIRTIO_RING_F_EVENT_IDX.
1826c3169a3SBruce Richardson  * Assuming a given event_idx value from the other size, if we have
1836c3169a3SBruce Richardson  * just incremented index from old to new_idx, should we trigger an
1846c3169a3SBruce Richardson  * event?
1856c3169a3SBruce Richardson  */
1866c3169a3SBruce Richardson static inline int
vring_need_event(uint16_t event_idx,uint16_t new_idx,uint16_t old)1876c3169a3SBruce Richardson vring_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old)
1886c3169a3SBruce Richardson {
1896c3169a3SBruce Richardson 	return (uint16_t)(new_idx - event_idx - 1) < (uint16_t)(new_idx - old);
1906c3169a3SBruce Richardson }
1916c3169a3SBruce Richardson 
1926c3169a3SBruce Richardson #endif /* _VIRTIO_RING_H_ */
193