1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25 #pragma once
26 #include <arch/io-mem.h>
27 #include <arch/virtio-base.h>
28 #include <stdbool.h>
29 #include <sys/types.h>
30 #include <trusty/sysdeps.h>
31
32 struct virtio_config;
33
34 /*
35 * Size of virtual queues. This can be dynamic, but since we do not have
36 * memory allocation, supporting dynamic allocation seems like overkill.
37 *
38 * Maximum number of ports we support in multiport of virtual serial console
39 * device is 16. To support 16 ports, vqueue size should be double size of
40 * maximum ports supported, since host would sent port add control event for
41 * all ports in one sequence.
42 */
43 #define VQ_SIZE 32
44
45 /**
46 * struct virtq_desc - VirtIO buffer descriptor
47 * @addr: Physical address of the buffer
48 * @len: Size of the buffer
49 * @flags: Buffer flags, see VIRTQ_DESC_* constants
50 * @next: Used to indicate a chained buffer (not used in our code)
51 *
52 * Buffer descriptor, stored in a descriptor table and referenced in rings
53 */
54 struct virtq_desc {
55 uint64_t addr;
56 uint32_t len;
57 uint16_t flags;
58 uint16_t next;
59 };
60
61 /* Used to indicate a chained descriptor. We aren't doing this */
62 #define VIRTQ_DESC_F_NEXT (1 << 0)
63
64 /* This buffer may be written by the host */
65 #define VIRTQ_DESC_F_WRITE (1 << 1)
66
67 /* This descriptor contains other descriptor ids. We aren't doing this */
68 #define VIRTQ_DESC_F_INDIRECT (1 << 2)
69
70 /**
71 * struct virtq_avail - VirtIO ring of buffers for use by the device
72 * @flags: Features for the ring. We zero this.
73 * @idx: Location we would insert the next buffer, mod VQ_SIZE
74 * @ring: Ring of indexes into the descriptor table.
75 * @used_event: Delay interrupts until idx > used_event if
76 * VIRTIO_F_EVENT_IDX was negotiated.
77 */
78 struct virtq_avail {
79 uint16_t flags;
80 uint16_t idx;
81 uint16_t ring[VQ_SIZE];
82 uint16_t used_event;
83 };
84
85 /**
86 * struct virtq_used_elem - What the device did with a buffer
87 * @id: Descriptor index of the buffer used.
88 * @len: How much of the buffer was used.
89 * NOTE: On Legacy MMIO devices (e.g. our serial ports), this field
90 * may be inaccurate for send requests (and is for our QEMU version).
91 */
92 struct virtq_used_elem {
93 uint32_t id;
94 uint32_t len;
95 };
96
97 /**
98 * struct virtq_used - Ring of buffers used by the device
99 * @flags: Features for the ring. We zero this.
100 * @idx: Location the device would insert the next buffer, mod VQ_SIZE
101 * @ring: Ring of virtq_used_elem, saying what the device has done.
102 * @avail_event: Delay interrupt until idx > avail_event if
103 * VIRTIO_F_EVENT_IDX was negotiated.
104 *
105 * While virtq_used has weaker alignment requirements (4) than PAGE_SIZE in
106 * the current spec, the Legacy spec requires that it be aligned to PAGE_SIZE.
107 */
108 struct virtq_used {
109 uint16_t flags;
110 uint16_t idx;
111 struct virtq_used_elem ring[VQ_SIZE];
112 uint16_t avail_event;
113 } __attribute__((aligned(PAGE_SIZE)));
114
115 /**
116 * struct virtq_raw - Legacy VirtIO layout container
117 * @desc: Table of bufferdescriptors. Indexes/IDs mentioned elsewhere are
118 * indexes into this table.
119 * @avail: Ring of buffers made available to the device
120 * @used: Ring of buffers the device is done processing
121 *
122 * The virtq_raw struct itself must be page aligned because a page frame is
123 * passed to the VirtIO driver to identify the region rather than an address.
124 *
125 * Further, the Legacy spec requires that @avail immediately follow the
126 * descriptor table, and that @used must be at the first page boundary
127 * afterwards.
128 */
129 struct virtq_raw {
130 struct virtq_desc desc[VQ_SIZE];
131 struct virtq_avail avail;
132 struct virtq_used used;
133 } __attribute__((aligned(PAGE_SIZE)));
134 ;
135
136 /* VirtIO Device IDs */
137 #define VIRTIO_DEVICE_ID_RESERVED (0)
138 #define VIRTIO_DEVICE_ID_BLOCK_DEVICE (2)
139 #define VIRTIO_DEVICE_ID_CONSOLE (3)
140
141 /* Flags for the status field of a VirtIO device */
142
143 /* Guest->Host: I have seen this device */
144 #define VIRTIO_STATUS_ACKNOWLEDGE (1)
145
146 /* Guest->Host: I have a driver for this device */
147 #define VIRTIO_STATUS_DRIVER (2)
148
149 /* Guest->Host: Driver is ready to drive the device */
150 #define VIRTIO_STATUS_DRIVER_OK (4)
151
152 /* Guest->Host: Feature negotiation is complete */
153 #define VIRTIO_STATUS_FEATURES_OK (8)
154
155 /* Host->Guest: The device has encountered an error; a reset may recover */
156 #define VIRTIO_STATUS_DEVICE_NEEDS_RESET (64)
157
158 /* Guest->Host: The driver can no longer drive the device */
159 #define VIRTIO_STATUS_FAILED (128)
160
161 /**
162 * struct virtq - VirtIO Queue + bookkeeping information
163 * @num_bufs: How many buffers are in the queue. For now, this is always
164 * VQ_NUM_BUFS.
165 * @queue_id: Which ID this queue has on the device.
166 * @raw: The actual legacy MMIO ring.
167 * @old_used_idx: Last seen value of the used index.
168 * This value is used to track whether there are new buffers to
169 * process.
170 * @vio: Pointer to the MMIO space this virtq is used by.
171 */
172 struct virtq {
173 size_t num_bufs;
174 size_t queue_id;
175 struct virtq_raw* raw;
176 uint16_t old_used_idx;
177 struct virtio_config* vio;
178 };
179
180 /**
181 * virtio_set_features() - Sets the provided features on a VirtIO device
182 * @vio: The device to set the features on
183 * @features: The features to set
184 */
185 void virtio_set_features(struct virtio_config* vio, uint64_t features);
186
187 /**
188 * virtio_get_features() - Gets the possible features on a VirtIO device
189 * @vio: The device to query
190 *
191 * Return: The feature vector supported by the device
192 */
193 uint64_t virtio_get_features(struct virtio_config* vio);
194
195 /**
196 * vq_init() - Initialize a virtq for the provided VirtIO device and sense.
197 * @vq: The uninitialized virtq
198 * @vq_raw: The uninitialized legacy-compatible VirtIO queue
199 * @vio: The VirtIO device the queue is for
200 * @is_input: Whether buffers moving through the queue should be
201 * host->guest (input) or guest->host (output).
202 *
203 * It is reccomended that virtq_raw be statically allocated to avoid alignment
204 * considerations.
205 */
206 void vq_init(struct virtq* vq,
207 struct virtq_raw* raw,
208 struct virtio_config* vio,
209 bool is_input);
210
211 /**
212 * vq_attach() - Attaches an initialized virtq to the specified queue ID
213 * @vq: The virtq to attach
214 * @idx: Which id to attach it on
215 */
216 void vq_attach(struct virtq* vq, uint16_t idx);
217
218 /**
219 * vq_make_avail - Adds the specified descriptor to the available ring
220 * @vq: The virtq we are operating on
221 * @desc_id: Which descriptor to make available to the device
222 */
223 void vq_make_avail(struct virtq* vq, uint16_t desc_id);
224
225 /**
226 * vq_kick - Alerts the device that this virtq has been updated
227 * @vq: The virtq to tell the device about.
228 */
229 void vq_kick(struct virtq* vq);
230
231 /**
232 * vq_ready() - Checks whether the device has processed another buffer.
233 * @vq: The queue to check
234 */
vq_ready(struct virtq * vq)235 static inline bool vq_ready(struct virtq* vq) {
236 return io_read_16(&vq->raw->used.idx) != vq->old_used_idx;
237 }
238
239 /**
240 * vq_wait() - Performs a blocking wait for the device to process a buffer.
241 * @vq: The queue to wait for processing on.
242 */
243 void vq_wait(struct virtq* vq);
244
245 /**
246 * vq_adv() - Acknowledge that the host processed a buffer
247 * @vq: The queue we are acknowledging
248 * Return: The processed buffer's length.
249 * This may be inaccurate for output buffers when in Legacy mode.
250 */
251 uint32_t vq_adv(struct virtq* vq);
252
253 /**
254 * send_vq() - Send a buffer via a virtq.
255 * @vq: The VirtIO queue to send on
256 * @data: The buffer to send
257 * @len: The size of the buffer
258 * Return: Negative on error, size sent on success.
259 */
260 ssize_t send_vq(struct virtq* vq, const char* data, size_t len);
261
262 /**
263 * recv_vq() - Receive data from a VirtIO queue.
264 * @vq: The queue to receive on.
265 * @data: The buffer to write to.
266 * @len: The size of the buffer.
267 * Return: Negative value on error, size received on success.
268 *
269 * Will receive *exactly* one packet (since this is not truly a stream
270 * protocol).
271 */
272 ssize_t recv_vq(struct virtq* vq, char* data, size_t len);
273
274 /**
275 * vq_set_buf_w() - Set a descriptor's buffer, host writable
276 * @vq: The queue to operate on
277 * @desc_id: Which descriptor to set
278 * @data: The buffer to set it to
279 * @len: How big the buffer is
280 */
281 void vq_set_buf_w(struct virtq* vq, uint16_t desc_id, void* data, size_t len);
282
283 /**
284 * vq_set_buf_r() - Set a descriptor's buffer, host readable
285 * @vq: The queue to operate on
286 * @desc_id: Which descriptor to set
287 * @data: The buffer to set it to
288 * @len: How big the buffer is
289 */
290 void vq_set_buf_r(struct virtq* vq,
291 uint16_t desc_id,
292 const void* data,
293 size_t len);
294