15129044dSC.J. Collier/*-
25129044dSC.J. Collier *   BSD LICENSE
35129044dSC.J. Collier *
45129044dSC.J. Collier *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
55129044dSC.J. Collier *   All rights reserved.
65129044dSC.J. Collier *
75129044dSC.J. Collier *   Redistribution and use in source and binary forms, with or without
85129044dSC.J. Collier *   modification, are permitted provided that the following conditions
95129044dSC.J. Collier *   are met:
105129044dSC.J. Collier *
115129044dSC.J. Collier *     * Redistributions of source code must retain the above copyright
125129044dSC.J. Collier *       notice, this list of conditions and the following disclaimer.
135129044dSC.J. Collier *     * Redistributions in binary form must reproduce the above copyright
145129044dSC.J. Collier *       notice, this list of conditions and the following disclaimer in
155129044dSC.J. Collier *       the documentation and/or other materials provided with the
165129044dSC.J. Collier *       distribution.
175129044dSC.J. Collier *     * Neither the name of Intel Corporation nor the names of its
185129044dSC.J. Collier *       contributors may be used to endorse or promote products derived
195129044dSC.J. Collier *       from this software without specific prior written permission.
205129044dSC.J. Collier *
215129044dSC.J. Collier *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
225129044dSC.J. Collier *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
235129044dSC.J. Collier *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
245129044dSC.J. Collier *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
255129044dSC.J. Collier *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
265129044dSC.J. Collier *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
275129044dSC.J. Collier *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
285129044dSC.J. Collier *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
295129044dSC.J. Collier *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
305129044dSC.J. Collier *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
315129044dSC.J. Collier *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
325129044dSC.J. Collier */
335129044dSC.J. Collier
345129044dSC.J. Collier#ifndef _VIRTIO_RING_H_
355129044dSC.J. Collier#define _VIRTIO_RING_H_
365129044dSC.J. Collier
375129044dSC.J. Collier#include <stdint.h>
385129044dSC.J. Collier
395129044dSC.J. Collier#include <rte_common.h>
405129044dSC.J. Collier
415129044dSC.J. Collier/* This marks a buffer as continuing via the next field. */
425129044dSC.J. Collier#define VRING_DESC_F_NEXT       1
435129044dSC.J. Collier/* This marks a buffer as write-only (otherwise read-only). */
445129044dSC.J. Collier#define VRING_DESC_F_WRITE      2
455129044dSC.J. Collier/* This means the buffer contains a list of buffer descriptors. */
465129044dSC.J. Collier#define VRING_DESC_F_INDIRECT   4
475129044dSC.J. Collier
485129044dSC.J. Collier/* The Host uses this in used->flags to advise the Guest: don't kick me
495129044dSC.J. Collier * when you add a buffer.  It's unreliable, so it's simply an
505129044dSC.J. Collier * optimization.  Guest will still kick if it's out of buffers. */
515129044dSC.J. Collier#define VRING_USED_F_NO_NOTIFY  1
525129044dSC.J. Collier/* The Guest uses this in avail->flags to advise the Host: don't
535129044dSC.J. Collier * interrupt me when you consume a buffer.  It's unreliable, so it's
545129044dSC.J. Collier * simply an optimization.  */
555129044dSC.J. Collier#define VRING_AVAIL_F_NO_INTERRUPT  1
565129044dSC.J. Collier
575129044dSC.J. Collier/* VirtIO ring descriptors: 16 bytes.
585129044dSC.J. Collier * These can chain together via "next". */
595129044dSC.J. Collierstruct vring_desc {
605129044dSC.J. Collier	uint64_t addr;  /*  Address (guest-physical). */
615129044dSC.J. Collier	uint32_t len;   /* Length. */
625129044dSC.J. Collier	uint16_t flags; /* The flags as indicated above. */
635129044dSC.J. Collier	uint16_t next;  /* We chain unused descriptors via this. */
645129044dSC.J. Collier};
655129044dSC.J. Collier
665129044dSC.J. Collierstruct vring_avail {
675129044dSC.J. Collier	uint16_t flags;
685129044dSC.J. Collier	uint16_t idx;
695129044dSC.J. Collier	uint16_t ring[0];
705129044dSC.J. Collier};
715129044dSC.J. Collier
725129044dSC.J. Collier/* id is a 16bit index. uint32_t is used here for ids for padding reasons. */
735129044dSC.J. Collierstruct vring_used_elem {
745129044dSC.J. Collier	/* Index of start of used descriptor chain. */
755129044dSC.J. Collier	uint32_t id;
765129044dSC.J. Collier	/* Total length of the descriptor chain which was written to. */
775129044dSC.J. Collier	uint32_t len;
785129044dSC.J. Collier};
795129044dSC.J. Collier
805129044dSC.J. Collierstruct vring_used {
815129044dSC.J. Collier	uint16_t flags;
82809f0800SChristian Ehrhardt	volatile uint16_t idx;
835129044dSC.J. Collier	struct vring_used_elem ring[0];
845129044dSC.J. Collier};
855129044dSC.J. Collier
865129044dSC.J. Collierstruct vring {
875129044dSC.J. Collier	unsigned int num;
885129044dSC.J. Collier	struct vring_desc  *desc;
895129044dSC.J. Collier	struct vring_avail *avail;
905129044dSC.J. Collier	struct vring_used  *used;
915129044dSC.J. Collier};
925129044dSC.J. Collier
935129044dSC.J. Collier/* The standard layout for the ring is a continuous chunk of memory which
945129044dSC.J. Collier * looks like this.  We assume num is a power of 2.
955129044dSC.J. Collier *
965129044dSC.J. Collier * struct vring {
975129044dSC.J. Collier *      // The actual descriptors (16 bytes each)
985129044dSC.J. Collier *      struct vring_desc desc[num];
995129044dSC.J. Collier *
1005129044dSC.J. Collier *      // A ring of available descriptor heads with free-running index.
1015129044dSC.J. Collier *      __u16 avail_flags;
1025129044dSC.J. Collier *      __u16 avail_idx;
1035129044dSC.J. Collier *      __u16 available[num];
1045129044dSC.J. Collier *      __u16 used_event_idx;
1055129044dSC.J. Collier *
1065129044dSC.J. Collier *      // Padding to the next align boundary.
1075129044dSC.J. Collier *      char pad[];
1085129044dSC.J. Collier *
1095129044dSC.J. Collier *      // A ring of used descriptor heads with free-running index.
1105129044dSC.J. Collier *      __u16 used_flags;
1115129044dSC.J. Collier *      __u16 used_idx;
1125129044dSC.J. Collier *      struct vring_used_elem used[num];
1135129044dSC.J. Collier *      __u16 avail_event_idx;
1145129044dSC.J. Collier * };
1155129044dSC.J. Collier *
1165129044dSC.J. Collier * NOTE: for VirtIO PCI, align is 4096.
1175129044dSC.J. Collier */
1185129044dSC.J. Collier
1195129044dSC.J. Collier/*
1205129044dSC.J. Collier * We publish the used event index at the end of the available ring, and vice
1215129044dSC.J. Collier * versa. They are at the end for backwards compatibility.
1225129044dSC.J. Collier */
1235129044dSC.J. Collier#define vring_used_event(vr)  ((vr)->avail->ring[(vr)->num])
1245129044dSC.J. Collier#define vring_avail_event(vr) (*(uint16_t *)&(vr)->used->ring[(vr)->num])
1255129044dSC.J. Collier
1265129044dSC.J. Collierstatic inline size_t
1275129044dSC.J. Colliervring_size(unsigned int num, unsigned long align)
1285129044dSC.J. Collier{
1295129044dSC.J. Collier	size_t size;
1305129044dSC.J. Collier
1315129044dSC.J. Collier	size = num * sizeof(struct vring_desc);
1325129044dSC.J. Collier	size += sizeof(struct vring_avail) + (num * sizeof(uint16_t));
1335129044dSC.J. Collier	size = RTE_ALIGN_CEIL(size, align);
1345129044dSC.J. Collier	size += sizeof(struct vring_used) +
1355129044dSC.J. Collier		(num * sizeof(struct vring_used_elem));
1365129044dSC.J. Collier	return size;
1375129044dSC.J. Collier}
1385129044dSC.J. Collier
1395129044dSC.J. Collierstatic inline void
1405129044dSC.J. Colliervring_init(struct vring *vr, unsigned int num, uint8_t *p,
1415129044dSC.J. Collier	unsigned long align)
1425129044dSC.J. Collier{
1435129044dSC.J. Collier	vr->num = num;
1445129044dSC.J. Collier	vr->desc = (struct vring_desc *) p;
1455129044dSC.J. Collier	vr->avail = (struct vring_avail *) (p +
1465129044dSC.J. Collier		num * sizeof(struct vring_desc));
1475129044dSC.J. Collier	vr->used = (void *)
1485129044dSC.J. Collier		RTE_ALIGN_CEIL((uintptr_t)(&vr->avail->ring[num]), align);
1495129044dSC.J. Collier}
1505129044dSC.J. Collier
1515129044dSC.J. Collier/*
1525129044dSC.J. Collier * The following is used with VIRTIO_RING_F_EVENT_IDX.
1535129044dSC.J. Collier * Assuming a given event_idx value from the other size, if we have
1545129044dSC.J. Collier * just incremented index from old to new_idx, should we trigger an
1555129044dSC.J. Collier * event?
1565129044dSC.J. Collier */
1575129044dSC.J. Collierstatic inline int
1585129044dSC.J. Colliervring_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old)
1595129044dSC.J. Collier{
1605129044dSC.J. Collier	return (uint16_t)(new_idx - event_idx - 1) < (uint16_t)(new_idx - old);
1615129044dSC.J. Collier}
1625129044dSC.J. Collier
1635129044dSC.J. Collier#endif /* _VIRTIO_RING_H_ */
164