VMM: Modify lguest helpers for our virtio
[akaros.git] / user / vmm / virtio_lguest_helpers.c
1 /* Virtio helper functions from linux/tools/lguest/lguest.c
2  *
3  * Copyright (C) 1991-2016, the Linux Kernel authors
4  * Copyright (c) 2016 Google Inc.
5  *
6  * Author:
7  *  Rusty Russell <rusty@rustcorp.com.au>
8  *  Michael Taufen <mtaufen@gmail.com>
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation; either version 2 of
13  * the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * The code from lguest.c has been modified for Akaros.
21  *
22  * Original linux/tools/lguest/lguest.c:
23  *   https://github.com/torvalds/linux/blob/v4.5/tools/lguest/lguest.c
24  *   most recent hash on the file as of v4.5 tag:
25  *     e523caa601f4a7c2fa1ecd040db921baf7453798
26  */
27
28
29 #include <sys/eventfd.h>
30 #include <sys/uio.h>
31 #include <ros/arch/membar.h>
32 #include <ros/arch/mmu.h>
33 #include <vmm/virtio.h>
34 #include <vmm/virtio_ids.h>
35 #include <vmm/virtio_config.h>
36
37 // The purpose is to make sure the addresses provided by the guest are not
38 // outside the bounds of the guest's memory.
39 // Based on _check_pointer in Linux's lguest.c, which came with
40 // the following comment:
41 /*L:200
42  * Device Handling.
43  *
44  * When the Guest gives us a buffer, it sends an array of addresses and sizes.
45  * We need to make sure it's not trying to reach into the Launcher itself, so
46  * we have a convenient routine which checks it and exits with an error message
47  * if something funny is going on:
48  */
49 void *virtio_check_pointer(struct virtio_vq *vq, uint64_t addr,
50                            uint32_t size, char *file, uint32_t line)
51 {
52         // We check that the pointer + the size doesn't wrap around, and that the
53         // pointer + the size isn't past the top of the guest's address space.
54         // UVPT is the top of the guest's address space, and is included from
55         // ros/arch/mmu64.h via ros/arch/mmu.h.
56         if ((addr + size) < addr || (addr + size) > UVPT)
57                 VIRTIO_DRI_ERRX(vq->vqdev,
58                         "Driver provided an invalid address or size (addr:0x%x sz:%u).\n"
59                         "  Location: %s:%d", addr, size, file, line);
60
61         return (void *)addr;
62 }
63
64
65 // For traversing the chain of descriptors
66 // Based on next_desc Linux's lguest.c, which came with the following comment:
67 /*
68  * Each buffer in the virtqueues is actually a chain of descriptors.  This
69  * function returns the next descriptor in the chain, or vq->vring.num if we're
70  * at the end.
71  */
72 static uint32_t next_desc(struct vring_desc *desc, uint32_t i, uint32_t max,
73                 struct virtio_vq *vq) // The vq is just for the error message.
74 {
75         uint32_t next;
76
77         // No more in the chain, so return max to signal that we reached the end
78         if (!(desc[i].flags & VRING_DESC_F_NEXT))
79                 return max;
80
81         next = desc[i].next;
82
83         // TODO: Figure out why lguest had the memory barrier here.
84         //       DO NOT REMOVE UNLESS YOU KNOW WHY!
85         wmb_f();
86
87         if (next >= max)
88                 VIRTIO_DRI_ERRX(vq->vqdev,
89                         "The next descriptor index in the chain provided by the driver is outside the bounds of the maximum allowed size of its queue.");
90
91         return next;
92 }
93
94 // Adds descriptor chain to the used ring of the vq
95 // Based on add_used in Linux's lguest.c, which came with the following comment:
96 /*
97  * After we've used one of their buffers, we tell the Guest about it.  Sometime
98  * later we'll want to send them an interrupt using trigger_irq(); note that
99  * wait_for_vq_desc() does that for us if it has to wait.
100  */
101 void virtio_add_used_desc(struct virtio_vq *vq, uint32_t head, uint32_t len)
102 {
103         // virtio-v1.0-cs04 s4.2.2.1 MMIO Device Register Layout
104         if (!vq->qready)
105                 VIRTIO_DEV_ERRX(vq->vqdev,
106                         "The device may not process queues with QueueReady set to 0x0.\n"
107                         "  See virtio-v1.0-cs04 s4.2.2.1 MMIO Device Register Layout");
108
109         // NOTE: len is the total length of the descriptor chain (in bytes)
110         //       that was written to.
111         //       So you should pass 0 if you didn't write anything, and pass
112         //       the number of bytes you wrote otherwise.
113         vq->vring.used->ring[vq->vring.used->idx % vq->vring.num].id = head;
114         vq->vring.used->ring[vq->vring.used->idx % vq->vring.num].len = len;
115
116         // virtio-v1.0-cs04 s2.4.8.2 The Virtqueue Used Ring
117         // TODO: Take note, Barret is thinking about renaming our wmb() to wwmb()
118         // The device MUST set len prior to updating the used idx, hence wmb()
119         wmb();
120         vq->vring.used->idx++;
121 }
122
123 // Based on wait_for_vq_desc in Linux's'lguest.c, which came with
124 // the following comment:
125 /*
126  * This looks in the virtqueue for the first available buffer, and converts
127  * it to an iovec for convenient access.  Since descriptors consist of some
128  * number of output then some number of input descriptors, it's actually two
129  * iovecs, but we pack them into one and note how many of each there were.
130  *
131  * This function waits if necessary, and returns the descriptor number found.
132  */
133 uint32_t virtio_next_avail_vq_desc(struct virtio_vq *vq, struct iovec iov[],
134                             uint32_t *olen, uint32_t *ilen)
135 {
136 // TODO: Need to make sure we don't overflow iov. Right now we're just kind of
137 //       trusting that whoever provided the iov made it at least as big as
138 //       qnum_max, but maybe we shouldn't be that trusting.
139         uint32_t i, head, max;
140         struct vring_desc *desc;
141         eventfd_t event;
142
143         while (vq->last_avail == vq->vring.avail->idx) {
144                 // We know the ring has updated when idx advances. We check == because
145                 // idx is allowed to wrap around eventually.
146
147                 // NOTE: lguest kicks the guest with an irq before they wait on the
148                 //       eventfd. Instead, I delegate that responsibility to the
149                 //       queue service functions.
150
151                 // We're about to wait on the eventfd, so we need to tell the guest
152                 // that we want a notification when it adds new buffers for
153                 // us to process.
154                 vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
155
156                 // If the guest added an available buffer while we were unsetting
157                 // the VRING_USED_F_NO_NOTIFY flag, we'll break out here and process
158                 // the new buffer.
159                 wrmb();
160                 if (vq->last_avail != vq->vring.avail->idx) {
161                         vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
162                         break;
163                 }
164
165                 if (eventfd_read(vq->eventfd, &event))
166                         VIRTIO_DEV_ERRX(vq->vqdev,
167                                 "eventfd read failed while waiting for available descriptors\n");
168
169                 // We don't need the guest to notify us about new buffers unless
170                 // we're waiting on the eventfd, because we will detect the
171                 // updated vq->vring.avail->idx.
172                 vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
173         }
174
175         // NOTE: lguest is a bit cryptic about why they check for this.
176         //       They just say, "Check it isn't doing very strange things with
177         //       descriptor numbers."
178         //       I added the reason I believe they do it in this comment and
179         //       the below error message.
180         // The guest can't have incremented idx more than vring.num times since
181         // we last incremented vq->last_avail, because it would have run out of
182         // places to put descriptors after incrementing exactly vring.num times
183         // (prior to our next vq->last_avail++)
184         if ((vq->vring.avail->idx - vq->last_avail) > vq->vring.num)
185                 VIRTIO_DRI_ERRX(vq->vqdev,
186                         "The driver advanced vq->vring.avail->idx from %u to %u, which have a difference greater than the capacity of a queue. The idx is supposed to increase by 1 for each descriptor chain added to the available ring; the driver should have run out of room and thus been forced to wait for us to catch up!",
187                         vq->last_avail, vq->vring.avail);
188
189         // lguest says here:
190         /*
191          * Make sure we read the descriptor number *after* we read the ring
192          * update; don't let the cpu or compiler change the order.
193          */
194         rmb();
195
196         // Mod because it's a *ring*. lguest said:
197         /*
198          * Grab the next descriptor number they're advertising, and increment
199          * the index we've seen.
200          */
201         head = vq->vring.avail->ring[vq->last_avail % vq->vring.num];
202         vq->last_avail++;
203
204         if (head >= vq->vring.num)
205                 VIRTIO_DRI_ERRX(vq->vqdev,
206                         "The index of the head of the descriptor chain provided by the driver is after the end of the queue.");
207
208         // Don't know how many output buffers or input buffers there are yet,
209         // this depends on the descriptor chain.
210         *olen = *ilen = 0;
211
212         // Since vring.num is the size of the queue, max is the max descriptors
213         // that should be in a descriptor chain. If we find more than that, the
214         // driver is doing something wrong.
215         max = vq->vring.num;
216         desc = vq->vring.desc;
217         i = head;
218
219         // NOTE: (from lguest)
220         /*
221          * We have to read the descriptor after we read the descriptor number,
222          * but there's a data dependency there so the CPU shouldn't reorder
223          * that: no rmb() required.
224          */
225         // Mike: The descriptor number is stored in i; what lguest means is
226         //       that data must flow from avail_ring to head to i before i
227         //       is used to index into desc.
228
229         do {
230                 // If it's an indirect descriptor, it points at a table of descriptors
231                 // provided by the guest driver. The descriptors in that table are
232                 // still chained, so we can ultimately handle them the same way as
233                 // direct descriptors.
234                 if (desc[i].flags & VRING_DESC_F_INDIRECT) {
235
236                         // virtio-v1.0-cs04 s2.4.5.3.1 Indirect Descriptors
237                         if (!(vq->vqdev->dri_feat & (1<<VIRTIO_RING_F_INDIRECT_DESC)))
238                                 VIRTIO_DRI_ERRX(vq->vqdev,
239                                         "The driver must not set the INDIRECT flag on a descriptor if the INDIRECT_DESC feature was not negotiated.\n"
240                                         "  See virtio-v1.0-cs04 s2.4.5.3.1 Indirect Descriptors");
241
242                         // NOTE: desc is only modified when we detect an indirect
243                         //       descriptor, so our implementation works whether there is an
244                         //       indirect descriptor at the very beginning OR at the very
245                         //       end of the chain (virtio-v1.0-cs04 s2.4.5.3.2 compliant)
246                         // virtio-v1.0-cs04 s2.4.5.3.1 Indirect Descriptors
247                         if (desc != vq->vring.desc)
248                                 VIRTIO_DRI_ERRX(vq->vqdev,
249                                         "The driver must not set the INDIRECT flag on a descriptor within an indirect descriptor.\n"
250                                         "  See virtio-v1.0-cs04 s2.4.5.3.1 Indirect Descriptors");
251
252                         // virtio-v1.0-cs04 s2.4.5.3.1 Indirect Descriptors
253                         if (desc[i].flags & VRING_DESC_F_NEXT)
254                                 VIRTIO_DRI_ERRX(vq->vqdev,
255                                         "The driver must not set both the INDIRECT and NEXT flags on a descriptor.\n"
256                                         "  See virtio-v1.0-cs04 s2.4.5.3.1 Indirect Descriptors");
257
258                         // nonzero mod indicates wrong table size
259                         if (desc[i].len % sizeof(struct vring_desc))
260                                 VIRTIO_DRI_ERRX(vq->vqdev,
261                                         "The size of a vring descriptor does not evenly divide the length of the indirect table provided by the driver. Bad table size.");
262
263                         // NOTE: virtio-v1.0-cs04 s2.4.5.3.2 Indirect Descriptors
264                         //       says that the device MUST ignore the write-only flag in the
265                         //       descriptor that refers to an indirect table. So we ignore.
266
267                         max = desc[i].len / sizeof(struct vring_desc);
268                         desc = virtio_check_pointer(vq, desc[i].addr, desc[i].len,
269                                                     __FILE__, __LINE__);
270
271                         // Now that desc is pointing at the table of indirect descriptors,
272                         // we set i to 0 so that we can start walking that table
273                         i = 0;
274
275                         // virtio-v1.0-cs04 s2.4.5.3.1 Indirect Descriptors
276                         if (max > vq->vring.num) {
277                                 VIRTIO_DRI_ERRX(vq->vqdev,
278                                         "The driver must not create a descriptor chain longer than the queue size of the device.\n"
279                                         "  See virtio-v1.0-cs04 s2.4.5.3.1 Indirect Descriptors");
280                         }
281                 }
282
283                 // Now build the scatterlist of buffers for the device to process
284                 iov[*olen + *ilen].iov_len = desc[i].len;
285                 iov[*olen + *ilen].iov_base = virtio_check_pointer(vq, desc[i].addr,
286                                                                    desc[i].len,
287                                                                    __FILE__, __LINE__);
288
289                 if (desc[i].flags & VRING_DESC_F_WRITE) {
290                         // input descriptor, increment *ilen
291                         (*ilen)++;
292                 }
293                 else {
294                         // virtio-v1.0-cs04 s2.4.4.2 Message Framing
295                         if (*ilen) {
296                                 VIRTIO_DRI_ERRX(vq->vqdev,
297                                         "Device detected an output descriptor after an input descriptor. The driver must place any device-writeable descriptor elements after all device-readable descriptor elements.\n"
298                                         "  See virtio-v1.0-cs04 s2.4.4.2 Message Framing");
299                         }
300
301                         (*olen)++;
302                 }
303
304                 // virtio-v1.0-cs04 s2.4.5.2 The Virtqueue Descriptor Table
305                 if (*olen + *ilen > max) {
306                         VIRTIO_DRI_ERRX(vq->vqdev,
307                                 "The driver must ensure that there are no loops in the descriptor chain it provides! The combined length of readable and writeable buffers was greater than the number of elements in the queue.\n"
308                                 "  See virtio-v1.0-cs04 s2.4.5.2 The Virtqueue Descriptor Table");
309                 }
310
311
312         } while ((i = next_desc(desc, i, max, vq)) != max);
313
314         return head;
315
316 }
317
318 // Based on check_virtqueue from lguest.c
319 // We call this when the driver writes 0x1 to QueueReady
320 void virtio_check_vring(struct virtio_vq *vq)
321 {
322         // First make sure that the pointers on the vring are all valid:
323         virtio_check_pointer(vq, (uint64_t)vq->vring.desc,
324                              sizeof(*vq->vring.desc) * vq->vring.num,
325                              __FILE__, __LINE__);
326         virtio_check_pointer(vq, (uint64_t)vq->vring.avail,
327                              sizeof(*vq->vring.avail) * vq->vring.num,
328                              __FILE__, __LINE__);
329         virtio_check_pointer(vq, (uint64_t)vq->vring.used,
330                              sizeof(*vq->vring.used) * vq->vring.num,
331                              __FILE__, __LINE__);
332
333
334         // virtio-v1.0-cs04 s2.4.9.1 Virtqueue Notification Suppression
335         if (vq->vring.used->flags != 0)
336                 VIRTIO_DRI_ERRX(vq->vqdev,
337                         "The driver must initialize the flags field of the used ring to 0 when allocating the used ring.\n"
338                         "  See virtio-v1.0-cs04 s2.4.9.1 Virtqueue Notification Suppression");
339 }