xref: /kvm-unit-tests/lib/virtio.h (revision d73e4521b5c5a13b40dd86aad307cd0b058bb68b)
143402ba5SAndrew Jones #ifndef _VIRTIO_H_
243402ba5SAndrew Jones #define _VIRTIO_H_
343402ba5SAndrew Jones /*
443402ba5SAndrew Jones  * A minimal implementation of virtio.
543402ba5SAndrew Jones  * Structures adapted from the Linux Kernel.
643402ba5SAndrew Jones  *
743402ba5SAndrew Jones  * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com>
843402ba5SAndrew Jones  *
943402ba5SAndrew Jones  * This work is licensed under the terms of the GNU LGPL, version 2.
1043402ba5SAndrew Jones  */
1143402ba5SAndrew Jones #include "libcflat.h"
1243402ba5SAndrew Jones 
1343402ba5SAndrew Jones struct virtio_device_id {
1443402ba5SAndrew Jones 	u32 device;
1543402ba5SAndrew Jones 	u32 vendor;
1643402ba5SAndrew Jones };
1743402ba5SAndrew Jones 
1843402ba5SAndrew Jones struct virtio_device {
1943402ba5SAndrew Jones 	struct virtio_device_id id;
2043402ba5SAndrew Jones 	const struct virtio_config_ops *config;
2143402ba5SAndrew Jones };
2243402ba5SAndrew Jones 
23*d73e4521SAndrew Jones struct virtqueue {
24*d73e4521SAndrew Jones 	void (*callback)(struct virtqueue *vq);
25*d73e4521SAndrew Jones 	const char *name;
26*d73e4521SAndrew Jones 	struct virtio_device *vdev;
27*d73e4521SAndrew Jones 	unsigned int index;
28*d73e4521SAndrew Jones 	unsigned int num_free;
29*d73e4521SAndrew Jones 	void *priv;
30*d73e4521SAndrew Jones };
31*d73e4521SAndrew Jones 
32*d73e4521SAndrew Jones typedef void vq_callback_t(struct virtqueue *);
3343402ba5SAndrew Jones struct virtio_config_ops {
3443402ba5SAndrew Jones 	void (*get)(struct virtio_device *vdev, unsigned offset,
3543402ba5SAndrew Jones 		    void *buf, unsigned len);
3643402ba5SAndrew Jones 	void (*set)(struct virtio_device *vdev, unsigned offset,
3743402ba5SAndrew Jones 		    const void *buf, unsigned len);
38*d73e4521SAndrew Jones 	int (*find_vqs)(struct virtio_device *vdev, unsigned nvqs,
39*d73e4521SAndrew Jones 			struct virtqueue *vqs[],
40*d73e4521SAndrew Jones 			vq_callback_t *callbacks[],
41*d73e4521SAndrew Jones 			const char *names[]);
4243402ba5SAndrew Jones };
4343402ba5SAndrew Jones 
4443402ba5SAndrew Jones static inline u8
4543402ba5SAndrew Jones virtio_config_readb(struct virtio_device *vdev, unsigned offset)
4643402ba5SAndrew Jones {
4743402ba5SAndrew Jones 	u8 val;
4843402ba5SAndrew Jones 	vdev->config->get(vdev, offset, &val, 1);
4943402ba5SAndrew Jones 	return val;
5043402ba5SAndrew Jones }
5143402ba5SAndrew Jones 
5243402ba5SAndrew Jones static inline u16
5343402ba5SAndrew Jones virtio_config_readw(struct virtio_device *vdev, unsigned offset)
5443402ba5SAndrew Jones {
5543402ba5SAndrew Jones 	u16 val;
5643402ba5SAndrew Jones 	vdev->config->get(vdev, offset, &val, 2);
5743402ba5SAndrew Jones 	return val;
5843402ba5SAndrew Jones }
5943402ba5SAndrew Jones 
6043402ba5SAndrew Jones static inline u32
6143402ba5SAndrew Jones virtio_config_readl(struct virtio_device *vdev, unsigned offset)
6243402ba5SAndrew Jones {
6343402ba5SAndrew Jones 	u32 val;
6443402ba5SAndrew Jones 	vdev->config->get(vdev, offset, &val, 4);
6543402ba5SAndrew Jones 	return val;
6643402ba5SAndrew Jones }
6743402ba5SAndrew Jones 
6843402ba5SAndrew Jones static inline void
6943402ba5SAndrew Jones virtio_config_writeb(struct virtio_device *vdev, unsigned offset, u8 val)
7043402ba5SAndrew Jones {
7143402ba5SAndrew Jones 	vdev->config->set(vdev, offset, &val, 1);
7243402ba5SAndrew Jones }
7343402ba5SAndrew Jones 
7443402ba5SAndrew Jones static inline void
7543402ba5SAndrew Jones virtio_config_writew(struct virtio_device *vdev, unsigned offset, u16 val)
7643402ba5SAndrew Jones {
7743402ba5SAndrew Jones 	vdev->config->set(vdev, offset, &val, 2);
7843402ba5SAndrew Jones }
7943402ba5SAndrew Jones 
8043402ba5SAndrew Jones static inline void
8143402ba5SAndrew Jones virtio_config_writel(struct virtio_device *vdev, unsigned offset, u32 val)
8243402ba5SAndrew Jones {
8343402ba5SAndrew Jones 	vdev->config->set(vdev, offset, &val, 4);
8443402ba5SAndrew Jones }
8543402ba5SAndrew Jones 
86*d73e4521SAndrew Jones #define VRING_DESC_F_NEXT	1
87*d73e4521SAndrew Jones #define VRING_DESC_F_WRITE	2
88*d73e4521SAndrew Jones 
89*d73e4521SAndrew Jones struct vring_desc {
90*d73e4521SAndrew Jones 	u64 addr;
91*d73e4521SAndrew Jones 	u32 len;
92*d73e4521SAndrew Jones 	u16 flags;
93*d73e4521SAndrew Jones 	u16 next;
94*d73e4521SAndrew Jones };
95*d73e4521SAndrew Jones 
96*d73e4521SAndrew Jones struct vring_avail {
97*d73e4521SAndrew Jones 	u16 flags;
98*d73e4521SAndrew Jones 	u16 idx;
99*d73e4521SAndrew Jones 	u16 ring[];
100*d73e4521SAndrew Jones };
101*d73e4521SAndrew Jones 
102*d73e4521SAndrew Jones struct vring_used_elem {
103*d73e4521SAndrew Jones 	u32 id;
104*d73e4521SAndrew Jones 	u32 len;
105*d73e4521SAndrew Jones };
106*d73e4521SAndrew Jones 
107*d73e4521SAndrew Jones struct vring_used {
108*d73e4521SAndrew Jones 	u16 flags;
109*d73e4521SAndrew Jones 	u16 idx;
110*d73e4521SAndrew Jones 	struct vring_used_elem ring[];
111*d73e4521SAndrew Jones };
112*d73e4521SAndrew Jones 
113*d73e4521SAndrew Jones struct vring {
114*d73e4521SAndrew Jones 	unsigned int num;
115*d73e4521SAndrew Jones 	struct vring_desc *desc;
116*d73e4521SAndrew Jones 	struct vring_avail *avail;
117*d73e4521SAndrew Jones 	struct vring_used *used;
118*d73e4521SAndrew Jones };
119*d73e4521SAndrew Jones 
120*d73e4521SAndrew Jones struct vring_virtqueue {
121*d73e4521SAndrew Jones 	struct virtqueue vq;
122*d73e4521SAndrew Jones 	struct vring vring;
123*d73e4521SAndrew Jones 	unsigned int free_head;
124*d73e4521SAndrew Jones 	unsigned int num_added;
125*d73e4521SAndrew Jones 	u16 last_used_idx;
126*d73e4521SAndrew Jones 	bool (*notify)(struct virtqueue *vq);
127*d73e4521SAndrew Jones 	void *data[];
128*d73e4521SAndrew Jones };
129*d73e4521SAndrew Jones 
130*d73e4521SAndrew Jones #define to_vvq(_vq) container_of(_vq, struct vring_virtqueue, vq)
131*d73e4521SAndrew Jones 
132*d73e4521SAndrew Jones extern void vring_init(struct vring *vr, unsigned int num, void *p,
133*d73e4521SAndrew Jones 		       unsigned long align);
134*d73e4521SAndrew Jones extern void vring_init_virtqueue(struct vring_virtqueue *vq, unsigned index,
135*d73e4521SAndrew Jones 				 unsigned num, unsigned vring_align,
136*d73e4521SAndrew Jones 				 struct virtio_device *vdev, void *pages,
137*d73e4521SAndrew Jones 				 bool (*notify)(struct virtqueue *),
138*d73e4521SAndrew Jones 				 void (*callback)(struct virtqueue *),
139*d73e4521SAndrew Jones 				 const char *name);
140*d73e4521SAndrew Jones extern int virtqueue_add_outbuf(struct virtqueue *vq, char *buf, size_t len);
141*d73e4521SAndrew Jones extern bool virtqueue_kick(struct virtqueue *vq);
142*d73e4521SAndrew Jones extern void detach_buf(struct vring_virtqueue *vq, unsigned head);
143*d73e4521SAndrew Jones extern void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len);
144*d73e4521SAndrew Jones 
14543402ba5SAndrew Jones extern struct virtio_device *virtio_bind(u32 devid);
14643402ba5SAndrew Jones 
14743402ba5SAndrew Jones #endif /* _VIRTIO_H_ */
148