xref: /kvm-unit-tests/lib/virtio.h (revision 49f758b8a983e49b4537ea2726e8a83a0d5632ad)
1 #ifndef _VIRTIO_H_
2 #define _VIRTIO_H_
3 /*
4  * A minimal implementation of virtio.
5  * Structures adapted from the Linux Kernel.
6  *
7  * Copyright (C) 2017, Red Hat Inc, Andrew Jones <drjones@redhat.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2.
10  */
11 #include "libcflat.h"
12 
13 #define VIRTIO_ID_CONSOLE 3
14 
15 struct virtio_device_id {
16 	u32 device;
17 	u32 vendor;
18 };
19 
20 struct virtio_device {
21 	struct virtio_device_id id;
22 	const struct virtio_config_ops *config;
23 };
24 
25 struct virtqueue {
26 	void (*callback)(struct virtqueue *vq);
27 	const char *name;
28 	struct virtio_device *vdev;
29 	unsigned int index;
30 	unsigned int num_free;
31 	void *priv;
32 };
33 
34 typedef void vq_callback_t(struct virtqueue *);
35 struct virtio_config_ops {
36 	void (*get)(struct virtio_device *vdev, unsigned offset,
37 		    void *buf, unsigned len);
38 	void (*set)(struct virtio_device *vdev, unsigned offset,
39 		    const void *buf, unsigned len);
40 	int (*find_vqs)(struct virtio_device *vdev, unsigned nvqs,
41 			struct virtqueue *vqs[],
42 			vq_callback_t *callbacks[],
43 			const char *names[]);
44 };
45 
46 static inline u8
virtio_config_readb(struct virtio_device * vdev,unsigned offset)47 virtio_config_readb(struct virtio_device *vdev, unsigned offset)
48 {
49 	u8 val;
50 	vdev->config->get(vdev, offset, &val, 1);
51 	return val;
52 }
53 
54 static inline u16
virtio_config_readw(struct virtio_device * vdev,unsigned offset)55 virtio_config_readw(struct virtio_device *vdev, unsigned offset)
56 {
57 	u16 val;
58 	vdev->config->get(vdev, offset, &val, 2);
59 	return val;
60 }
61 
62 static inline u32
virtio_config_readl(struct virtio_device * vdev,unsigned offset)63 virtio_config_readl(struct virtio_device *vdev, unsigned offset)
64 {
65 	u32 val;
66 	vdev->config->get(vdev, offset, &val, 4);
67 	return val;
68 }
69 
70 static inline void
virtio_config_writeb(struct virtio_device * vdev,unsigned offset,u8 val)71 virtio_config_writeb(struct virtio_device *vdev, unsigned offset, u8 val)
72 {
73 	vdev->config->set(vdev, offset, &val, 1);
74 }
75 
76 static inline void
virtio_config_writew(struct virtio_device * vdev,unsigned offset,u16 val)77 virtio_config_writew(struct virtio_device *vdev, unsigned offset, u16 val)
78 {
79 	vdev->config->set(vdev, offset, &val, 2);
80 }
81 
82 static inline void
virtio_config_writel(struct virtio_device * vdev,unsigned offset,u32 val)83 virtio_config_writel(struct virtio_device *vdev, unsigned offset, u32 val)
84 {
85 	vdev->config->set(vdev, offset, &val, 4);
86 }
87 
88 #define VRING_DESC_F_NEXT	1
89 #define VRING_DESC_F_WRITE	2
90 
91 struct vring_desc {
92 	u64 addr;
93 	u32 len;
94 	u16 flags;
95 	u16 next;
96 };
97 
98 struct vring_avail {
99 	u16 flags;
100 	u16 idx;
101 	u16 ring[];
102 };
103 
104 struct vring_used_elem {
105 	u32 id;
106 	u32 len;
107 };
108 
109 struct vring_used {
110 	u16 flags;
111 	u16 idx;
112 	struct vring_used_elem ring[];
113 };
114 
115 struct vring {
116 	unsigned int num;
117 	struct vring_desc *desc;
118 	struct vring_avail *avail;
119 	struct vring_used *used;
120 };
121 
122 struct vring_virtqueue {
123 	struct virtqueue vq;
124 	struct vring vring;
125 	unsigned int free_head;
126 	unsigned int num_added;
127 	u16 last_used_idx;
128 	bool (*notify)(struct virtqueue *vq);
129 	void *data[];
130 };
131 
132 #define to_vvq(_vq) container_of(_vq, struct vring_virtqueue, vq)
133 
134 extern void vring_init(struct vring *vr, unsigned int num, void *p,
135 		       unsigned long align);
136 extern void vring_init_virtqueue(struct vring_virtqueue *vq, unsigned index,
137 				 unsigned num, unsigned vring_align,
138 				 struct virtio_device *vdev, void *pages,
139 				 bool (*notify)(struct virtqueue *),
140 				 void (*callback)(struct virtqueue *),
141 				 const char *name);
142 extern int virtqueue_add_outbuf(struct virtqueue *vq, char *buf,
143 				unsigned int len);
144 extern bool virtqueue_kick(struct virtqueue *vq);
145 extern void detach_buf(struct vring_virtqueue *vq, unsigned head);
146 extern void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len);
147 
148 extern struct virtio_device *virtio_bind(u32 devid);
149 
150 #endif /* _VIRTIO_H_ */
151