110388SAndreas.Sandberg@ARM.com#ifndef _VIRTIO_RING_H 210388SAndreas.Sandberg@ARM.com#define _VIRTIO_RING_H 310388SAndreas.Sandberg@ARM.com/* An interface for efficient virtio implementation, currently for use by KVM 410388SAndreas.Sandberg@ARM.com * and lguest, but hopefully others soon. Do NOT change this since it will 510388SAndreas.Sandberg@ARM.com * break existing servers and clients. 610388SAndreas.Sandberg@ARM.com * 710388SAndreas.Sandberg@ARM.com * This header is BSD licensed so anyone can use the definitions to implement 810388SAndreas.Sandberg@ARM.com * compatible drivers/servers. 910388SAndreas.Sandberg@ARM.com * 1010388SAndreas.Sandberg@ARM.com * Redistribution and use in source and binary forms, with or without 1110388SAndreas.Sandberg@ARM.com * modification, are permitted provided that the following conditions 1210388SAndreas.Sandberg@ARM.com * are met: 1310388SAndreas.Sandberg@ARM.com * 1. Redistributions of source code must retain the above copyright 1410388SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer. 1510388SAndreas.Sandberg@ARM.com * 2. Redistributions in binary form must reproduce the above copyright 1610388SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer in the 1710388SAndreas.Sandberg@ARM.com * documentation and/or other materials provided with the distribution. 1810388SAndreas.Sandberg@ARM.com * 3. Neither the name of IBM nor the names of its contributors 1910388SAndreas.Sandberg@ARM.com * may be used to endorse or promote products derived from this software 2010388SAndreas.Sandberg@ARM.com * without specific prior written permission. 2110388SAndreas.Sandberg@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND 2210388SAndreas.Sandberg@ARM.com * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2310388SAndreas.Sandberg@ARM.com * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2410388SAndreas.Sandberg@ARM.com * ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE 2510388SAndreas.Sandberg@ARM.com * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2610388SAndreas.Sandberg@ARM.com * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2710388SAndreas.Sandberg@ARM.com * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2810388SAndreas.Sandberg@ARM.com * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2910388SAndreas.Sandberg@ARM.com * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3010388SAndreas.Sandberg@ARM.com * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3110388SAndreas.Sandberg@ARM.com * SUCH DAMAGE. 3210388SAndreas.Sandberg@ARM.com * 3310388SAndreas.Sandberg@ARM.com * Copyright Rusty Russell IBM Corporation 2007. */ 3410388SAndreas.Sandberg@ARM.com#include <stdint.h> 3510388SAndreas.Sandberg@ARM.com 3610388SAndreas.Sandberg@ARM.com/* This marks a buffer as continuing via the next field. */ 3710388SAndreas.Sandberg@ARM.com#define VRING_DESC_F_NEXT 1 3810388SAndreas.Sandberg@ARM.com/* This marks a buffer as write-only (otherwise read-only). */ 3910388SAndreas.Sandberg@ARM.com#define VRING_DESC_F_WRITE 2 4010388SAndreas.Sandberg@ARM.com/* This means the buffer contains a list of buffer descriptors. */ 4110388SAndreas.Sandberg@ARM.com#define VRING_DESC_F_INDIRECT 4 4210388SAndreas.Sandberg@ARM.com 4310388SAndreas.Sandberg@ARM.com/* The Host uses this in used->flags to advise the Guest: don't kick me when 4410388SAndreas.Sandberg@ARM.com * you add a buffer. It's unreliable, so it's simply an optimization. Guest 4510388SAndreas.Sandberg@ARM.com * will still kick if it's out of buffers. */ 4610388SAndreas.Sandberg@ARM.com#define VRING_USED_F_NO_NOTIFY 1 4710388SAndreas.Sandberg@ARM.com/* The Guest uses this in avail->flags to advise the Host: don't interrupt me 4810388SAndreas.Sandberg@ARM.com * when you consume a buffer. It's unreliable, so it's simply an 4910388SAndreas.Sandberg@ARM.com * optimization. */ 5010388SAndreas.Sandberg@ARM.com#define VRING_AVAIL_F_NO_INTERRUPT 1 5110388SAndreas.Sandberg@ARM.com 5210388SAndreas.Sandberg@ARM.com/* We support indirect buffer descriptors */ 5310388SAndreas.Sandberg@ARM.com#define VIRTIO_RING_F_INDIRECT_DESC 28 5410388SAndreas.Sandberg@ARM.com 5510388SAndreas.Sandberg@ARM.com/* The Guest publishes the used index for which it expects an interrupt 5610388SAndreas.Sandberg@ARM.com * at the end of the avail ring. Host should ignore the avail->flags field. */ 5710388SAndreas.Sandberg@ARM.com/* The Host publishes the avail index for which it expects a kick 5810388SAndreas.Sandberg@ARM.com * at the end of the used ring. Guest should ignore the used->flags field. */ 5910388SAndreas.Sandberg@ARM.com#define VIRTIO_RING_F_EVENT_IDX 29 6010388SAndreas.Sandberg@ARM.com 6110388SAndreas.Sandberg@ARM.com/* Virtio ring descriptors: 16 bytes. These can chain together via "next". */ 6210388SAndreas.Sandberg@ARM.comstruct vring_desc { 6310388SAndreas.Sandberg@ARM.com /* Address (guest-physical). */ 6410388SAndreas.Sandberg@ARM.com uint64_t addr; 6510388SAndreas.Sandberg@ARM.com /* Length. */ 6610388SAndreas.Sandberg@ARM.com uint32_t len; 6710388SAndreas.Sandberg@ARM.com /* The flags as indicated above. */ 6810388SAndreas.Sandberg@ARM.com uint16_t flags; 6910388SAndreas.Sandberg@ARM.com /* We chain unused descriptors via this, too */ 7010388SAndreas.Sandberg@ARM.com uint16_t next; 7110388SAndreas.Sandberg@ARM.com}; 7210388SAndreas.Sandberg@ARM.com 7310388SAndreas.Sandberg@ARM.comstruct vring_avail { 7410388SAndreas.Sandberg@ARM.com uint16_t flags; 7510388SAndreas.Sandberg@ARM.com uint16_t idx; 7610388SAndreas.Sandberg@ARM.com uint16_t ring[]; 7710388SAndreas.Sandberg@ARM.com}; 7810388SAndreas.Sandberg@ARM.com 7910388SAndreas.Sandberg@ARM.com/* u32 is used here for ids for padding reasons. */ 8010388SAndreas.Sandberg@ARM.comstruct vring_used_elem { 8110388SAndreas.Sandberg@ARM.com /* Index of start of used descriptor chain. */ 8210388SAndreas.Sandberg@ARM.com uint32_t id; 8310388SAndreas.Sandberg@ARM.com /* Total length of the descriptor chain which was used (written to) */ 8410388SAndreas.Sandberg@ARM.com uint32_t len; 8510388SAndreas.Sandberg@ARM.com}; 8610388SAndreas.Sandberg@ARM.com 8710388SAndreas.Sandberg@ARM.comstruct vring_used { 8810388SAndreas.Sandberg@ARM.com uint16_t flags; 8910388SAndreas.Sandberg@ARM.com uint16_t idx; 9010388SAndreas.Sandberg@ARM.com struct vring_used_elem ring[]; 9110388SAndreas.Sandberg@ARM.com}; 9210388SAndreas.Sandberg@ARM.com 9310388SAndreas.Sandberg@ARM.comstruct vring { 9410388SAndreas.Sandberg@ARM.com unsigned int num; 9510388SAndreas.Sandberg@ARM.com 9610388SAndreas.Sandberg@ARM.com struct vring_desc *desc; 9710388SAndreas.Sandberg@ARM.com 9810388SAndreas.Sandberg@ARM.com struct vring_avail *avail; 9910388SAndreas.Sandberg@ARM.com 10010388SAndreas.Sandberg@ARM.com struct vring_used *used; 10110388SAndreas.Sandberg@ARM.com}; 10210388SAndreas.Sandberg@ARM.com 10310388SAndreas.Sandberg@ARM.com/* The standard layout for the ring is a continuous chunk of memory which looks 10410388SAndreas.Sandberg@ARM.com * like this. We assume num is a power of 2. 10510388SAndreas.Sandberg@ARM.com * 10610388SAndreas.Sandberg@ARM.com * struct vring 10710388SAndreas.Sandberg@ARM.com * { 10810388SAndreas.Sandberg@ARM.com * // The actual descriptors (16 bytes each) 10910388SAndreas.Sandberg@ARM.com * struct vring_desc desc[num]; 11010388SAndreas.Sandberg@ARM.com * 11110388SAndreas.Sandberg@ARM.com * // A ring of available descriptor heads with free-running index. 11210388SAndreas.Sandberg@ARM.com * uint16_t avail_flags; 11310388SAndreas.Sandberg@ARM.com * uint16_t avail_idx; 11410388SAndreas.Sandberg@ARM.com * uint16_t available[num]; 11510388SAndreas.Sandberg@ARM.com * uint16_t used_event_idx; 11610388SAndreas.Sandberg@ARM.com * 11710388SAndreas.Sandberg@ARM.com * // Padding to the next align boundary. 11810388SAndreas.Sandberg@ARM.com * char pad[]; 11910388SAndreas.Sandberg@ARM.com * 12010388SAndreas.Sandberg@ARM.com * // A ring of used descriptor heads with free-running index. 12110388SAndreas.Sandberg@ARM.com * uint16_t used_flags; 12210388SAndreas.Sandberg@ARM.com * uint16_t used_idx; 12310388SAndreas.Sandberg@ARM.com * struct vring_used_elem used[num]; 12410388SAndreas.Sandberg@ARM.com * uint16_t avail_event_idx; 12510388SAndreas.Sandberg@ARM.com * }; 12610388SAndreas.Sandberg@ARM.com */ 12710388SAndreas.Sandberg@ARM.com/* We publish the used event index at the end of the available ring, and vice 12810388SAndreas.Sandberg@ARM.com * versa. They are at the end for backwards compatibility. */ 12910388SAndreas.Sandberg@ARM.com#define vring_used_event(vr) ((vr)->avail->ring[(vr)->num]) 13010388SAndreas.Sandberg@ARM.com#define vring_avail_event(vr) (*(uint16_t *)&(vr)->used->ring[(vr)->num]) 13110388SAndreas.Sandberg@ARM.com 13210388SAndreas.Sandberg@ARM.comstatic inline void vring_init(struct vring *vr, unsigned int num, void *p, 13310388SAndreas.Sandberg@ARM.com unsigned long align) 13410388SAndreas.Sandberg@ARM.com{ 13510388SAndreas.Sandberg@ARM.com vr->num = num; 13610388SAndreas.Sandberg@ARM.com vr->desc = (struct vring_desc *)p; 13710388SAndreas.Sandberg@ARM.com vr->avail = (struct vring_avail *)((uint8_t*)p + num*sizeof(struct vring_desc)); 13810388SAndreas.Sandberg@ARM.com vr->used = (struct vring_used *)(((unsigned long)&vr->avail->ring[num] + sizeof(uint16_t) 13910388SAndreas.Sandberg@ARM.com + align-1) & ~(align - 1)); 14010388SAndreas.Sandberg@ARM.com} 14110388SAndreas.Sandberg@ARM.com 14210388SAndreas.Sandberg@ARM.comstatic inline unsigned vring_size(unsigned int num, unsigned long align) 14310388SAndreas.Sandberg@ARM.com{ 14410388SAndreas.Sandberg@ARM.com return ((sizeof(struct vring_desc) * num + sizeof(uint16_t) * (3 + num) 14510388SAndreas.Sandberg@ARM.com + align - 1) & ~(align - 1)) 14610388SAndreas.Sandberg@ARM.com + sizeof(uint16_t) * 3 + sizeof(struct vring_used_elem) * num; 14710388SAndreas.Sandberg@ARM.com} 14810388SAndreas.Sandberg@ARM.com 14910388SAndreas.Sandberg@ARM.com/* The following is used with USED_EVENT_IDX and AVAIL_EVENT_IDX */ 15010388SAndreas.Sandberg@ARM.com/* Assuming a given event_idx value from the other size, if 15110388SAndreas.Sandberg@ARM.com * we have just incremented index from old to new_idx, 15210388SAndreas.Sandberg@ARM.com * should we trigger an event? */ 15310388SAndreas.Sandberg@ARM.comstatic inline int vring_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old) 15410388SAndreas.Sandberg@ARM.com{ 15510388SAndreas.Sandberg@ARM.com /* Note: Xen has similar logic for notification hold-off 15610388SAndreas.Sandberg@ARM.com * in include/xen/interface/io/ring.h with req_event and req_prod 15710388SAndreas.Sandberg@ARM.com * corresponding to event_idx + 1 and new_idx respectively. 15810388SAndreas.Sandberg@ARM.com * Note also that req_event and req_prod in Xen start at 1, 15910388SAndreas.Sandberg@ARM.com * event indexes in virtio start at 0. */ 16010388SAndreas.Sandberg@ARM.com return (uint16_t)(new_idx - event_idx - 1) < (uint16_t)(new_idx - old); 16110388SAndreas.Sandberg@ARM.com} 16210388SAndreas.Sandberg@ARM.com 16310388SAndreas.Sandberg@ARM.com#endif /* _VIRTIO_RING_H */ 164