brintos

brintos / linux-shallow public Read only

0
0
Text · 8.5 KiB · f8c20d3 Raw
251 lines · c
1#ifndef _UAPI_LINUX_VIRTIO_RING_H2#define _UAPI_LINUX_VIRTIO_RING_H3/* An interface for efficient virtio implementation, currently for use by KVM,4 * but hopefully others soon.  Do NOT change this since it will5 * break existing servers and clients.6 *7 * This header is BSD licensed so anyone can use the definitions to implement8 * compatible drivers/servers.9 *10 * Redistribution and use in source and binary forms, with or without11 * modification, are permitted provided that the following conditions12 * are met:13 * 1. Redistributions of source code must retain the above copyright14 *    notice, this list of conditions and the following disclaimer.15 * 2. Redistributions in binary form must reproduce the above copyright16 *    notice, this list of conditions and the following disclaimer in the17 *    documentation and/or other materials provided with the distribution.18 * 3. Neither the name of IBM nor the names of its contributors19 *    may be used to endorse or promote products derived from this software20 *    without specific prior written permission.21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE24 * ARE DISCLAIMED.  IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF31 * SUCH DAMAGE.32 *33 * Copyright Rusty Russell IBM Corporation 2007. */34#ifndef __KERNEL__35#include <stdint.h>36#endif37#include <linux/types.h>38#include <linux/virtio_types.h>39 40/* This marks a buffer as continuing via the next field. */41#define VRING_DESC_F_NEXT	142/* This marks a buffer as write-only (otherwise read-only). */43#define VRING_DESC_F_WRITE	244/* This means the buffer contains a list of buffer descriptors. */45#define VRING_DESC_F_INDIRECT	446 47/*48 * Mark a descriptor as available or used in packed ring.49 * Notice: they are defined as shifts instead of shifted values.50 */51#define VRING_PACKED_DESC_F_AVAIL	752#define VRING_PACKED_DESC_F_USED	1553 54/* The Host uses this in used->flags to advise the Guest: don't kick me when55 * you add a buffer.  It's unreliable, so it's simply an optimization.  Guest56 * will still kick if it's out of buffers. */57#define VRING_USED_F_NO_NOTIFY	158/* The Guest uses this in avail->flags to advise the Host: don't interrupt me59 * when you consume a buffer.  It's unreliable, so it's simply an60 * optimization.  */61#define VRING_AVAIL_F_NO_INTERRUPT	162 63/* Enable events in packed ring. */64#define VRING_PACKED_EVENT_FLAG_ENABLE	0x065/* Disable events in packed ring. */66#define VRING_PACKED_EVENT_FLAG_DISABLE	0x167/*68 * Enable events for a specific descriptor in packed ring.69 * (as specified by Descriptor Ring Change Event Offset/Wrap Counter).70 * Only valid if VIRTIO_RING_F_EVENT_IDX has been negotiated.71 */72#define VRING_PACKED_EVENT_FLAG_DESC	0x273 74/*75 * Wrap counter bit shift in event suppression structure76 * of packed ring.77 */78#define VRING_PACKED_EVENT_F_WRAP_CTR	1579 80/* We support indirect buffer descriptors */81#define VIRTIO_RING_F_INDIRECT_DESC	2882 83/* The Guest publishes the used index for which it expects an interrupt84 * at the end of the avail ring. Host should ignore the avail->flags field. */85/* The Host publishes the avail index for which it expects a kick86 * at the end of the used ring. Guest should ignore the used->flags field. */87#define VIRTIO_RING_F_EVENT_IDX		2988 89/* Alignment requirements for vring elements.90 * When using pre-virtio 1.0 layout, these fall out naturally.91 */92#define VRING_AVAIL_ALIGN_SIZE 293#define VRING_USED_ALIGN_SIZE 494#define VRING_DESC_ALIGN_SIZE 1695 96/**97 * struct vring_desc - Virtio ring descriptors,98 * 16 bytes long. These can chain together via @next.99 *100 * @addr: buffer address (guest-physical)101 * @len: buffer length102 * @flags: descriptor flags103 * @next: index of the next descriptor in the chain,104 *        if the VRING_DESC_F_NEXT flag is set. We chain unused105 *        descriptors via this, too.106 */107struct vring_desc {108	__virtio64 addr;109	__virtio32 len;110	__virtio16 flags;111	__virtio16 next;112};113 114struct vring_avail {115	__virtio16 flags;116	__virtio16 idx;117	__virtio16 ring[];118};119 120/* u32 is used here for ids for padding reasons. */121struct vring_used_elem {122	/* Index of start of used descriptor chain. */123	__virtio32 id;124	/* Total length of the descriptor chain which was used (written to) */125	__virtio32 len;126};127 128typedef struct vring_used_elem __attribute__((aligned(VRING_USED_ALIGN_SIZE)))129	vring_used_elem_t;130 131struct vring_used {132	__virtio16 flags;133	__virtio16 idx;134	vring_used_elem_t ring[];135};136 137/*138 * The ring element addresses are passed between components with different139 * alignments assumptions. Thus, we might need to decrease the compiler-selected140 * alignment, and so must use a typedef to make sure the aligned attribute141 * actually takes hold:142 *143 * https://gcc.gnu.org/onlinedocs//gcc/Common-Type-Attributes.html#Common-Type-Attributes144 *145 * When used on a struct, or struct member, the aligned attribute can only146 * increase the alignment; in order to decrease it, the packed attribute must147 * be specified as well. When used as part of a typedef, the aligned attribute148 * can both increase and decrease alignment, and specifying the packed149 * attribute generates a warning.150 */151typedef struct vring_desc __attribute__((aligned(VRING_DESC_ALIGN_SIZE)))152	vring_desc_t;153typedef struct vring_avail __attribute__((aligned(VRING_AVAIL_ALIGN_SIZE)))154	vring_avail_t;155typedef struct vring_used __attribute__((aligned(VRING_USED_ALIGN_SIZE)))156	vring_used_t;157 158struct vring {159	unsigned int num;160 161	vring_desc_t *desc;162 163	vring_avail_t *avail;164 165	vring_used_t *used;166};167 168#ifndef VIRTIO_RING_NO_LEGACY169 170/* The standard layout for the ring is a continuous chunk of memory which looks171 * like this.  We assume num is a power of 2.172 *173 * struct vring174 * {175 *	// The actual descriptors (16 bytes each)176 *	struct vring_desc desc[num];177 *178 *	// A ring of available descriptor heads with free-running index.179 *	__virtio16 avail_flags;180 *	__virtio16 avail_idx;181 *	__virtio16 available[num];182 *	__virtio16 used_event_idx;183 *184 *	// Padding to the next align boundary.185 *	char pad[];186 *187 *	// A ring of used descriptor heads with free-running index.188 *	__virtio16 used_flags;189 *	__virtio16 used_idx;190 *	struct vring_used_elem used[num];191 *	__virtio16 avail_event_idx;192 * };193 */194/* We publish the used event index at the end of the available ring, and vice195 * versa. They are at the end for backwards compatibility. */196#define vring_used_event(vr) ((vr)->avail->ring[(vr)->num])197#define vring_avail_event(vr) (*(__virtio16 *)&(vr)->used->ring[(vr)->num])198 199static inline void vring_init(struct vring *vr, unsigned int num, void *p,200			      unsigned long align)201{202	vr->num = num;203	vr->desc = p;204	vr->avail = (struct vring_avail *)((char *)p + num * sizeof(struct vring_desc));205	vr->used = (void *)(((uintptr_t)&vr->avail->ring[num] + sizeof(__virtio16)206		+ align-1) & ~(align - 1));207}208 209static inline unsigned vring_size(unsigned int num, unsigned long align)210{211	return ((sizeof(struct vring_desc) * num + sizeof(__virtio16) * (3 + num)212		 + align - 1) & ~(align - 1))213		+ sizeof(__virtio16) * 3 + sizeof(struct vring_used_elem) * num;214}215 216#endif /* VIRTIO_RING_NO_LEGACY */217 218/* The following is used with USED_EVENT_IDX and AVAIL_EVENT_IDX */219/* Assuming a given event_idx value from the other side, if220 * we have just incremented index from old to new_idx,221 * should we trigger an event? */222static inline int vring_need_event(__u16 event_idx, __u16 new_idx, __u16 old)223{224	/* Note: Xen has similar logic for notification hold-off225	 * in include/xen/interface/io/ring.h with req_event and req_prod226	 * corresponding to event_idx + 1 and new_idx respectively.227	 * Note also that req_event and req_prod in Xen start at 1,228	 * event indexes in virtio start at 0. */229	return (__u16)(new_idx - event_idx - 1) < (__u16)(new_idx - old);230}231 232struct vring_packed_desc_event {233	/* Descriptor Ring Change Event Offset/Wrap Counter. */234	__le16 off_wrap;235	/* Descriptor Ring Change Event Flags. */236	__le16 flags;237};238 239struct vring_packed_desc {240	/* Buffer Address. */241	__le64 addr;242	/* Buffer Length. */243	__le32 len;244	/* Buffer ID. */245	__le16 id;246	/* The flags depending on descriptor type. */247	__le16 flags;248};249 250#endif /* _UAPI_LINUX_VIRTIO_RING_H */251