We're finding more undocumented bits. So the bit set test is failing.
[akaros.git] / user / vmm / virtio-mmio.c
1 /*
2  * Virtio MMIO bindings
3  *
4  * Copyright (c) 2011 Linaro Limited
5  *
6  * Author:
7  *  Peter Maydell <peter.maydell@linaro.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <stdio.h>
23 #include <sys/types.h>
24 #include <pthread.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <parlib/arch/arch.h>
28 #include <parlib/ros_debug.h>
29 #include <unistd.h>
30 #include <errno.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <sys/uio.h>
34 #include <stdint.h>
35 #include <err.h>
36 #include <sys/mman.h>
37 #include <ros/vmm.h>
38 #include <vmm/virtio.h>
39 #include <vmm/virtio_mmio.h>
40 #include <vmm/virtio_ids.h>
41 #include <vmm/virtio_config.h>
42
43 int debug_virtio_mmio = 0;
44 #define DPRINTF(fmt, ...) \
45         if (debug_virtio_mmio) { printf("virtio_mmio: " fmt , ## __VA_ARGS__); }
46
47
48 #define VIRT_MAGIC 0x74726976 /* 'virt' */
49 /* version is a real mess. A real mess. I don't understand it at all. Let's stick with 1, which sucks, 
50  * instead of 2, which seems to be not supported right. I think.
51  */
52 #define VIRT_VERSION 1
53 #define VIRT_VENDOR 0x554D4551 /* 'QEMU' */
54
55
56 typedef struct {
57         int state; // not used yet. */
58         uint64_t bar;
59         uint32_t status;
60         int qsel; // queue we are on.
61         int pagesize;
62         int page_shift;
63         int device_features_word; // if this is 1, use the high 32 bits. 
64         int driver_features_word;
65         struct vqdev *vqdev;
66 } mmiostate;
67
68 static mmiostate mmio;
69
70 void register_virtio_mmio(struct vqdev *vqdev, uint64_t virtio_base)
71 {
72         mmio.bar = virtio_base;
73         mmio.vqdev = vqdev;
74 }
75
76 static uint32_t virtio_mmio_read(uint64_t gpa);
77 char *virtio_names[] = {
78         [VIRTIO_MMIO_MAGIC_VALUE] "VIRTIO_MMIO_MAGIC_VALUE",
79         [VIRTIO_MMIO_VERSION] "VIRTIO_MMIO_VERSION",
80         [VIRTIO_MMIO_DEVICE_ID] "VIRTIO_MMIO_DEVICE_ID",
81         [VIRTIO_MMIO_VENDOR_ID] "VIRTIO_MMIO_VENDOR_ID",
82         [VIRTIO_MMIO_DEVICE_FEATURES] "VIRTIO_MMIO_DEVICE_FEATURES",
83         [VIRTIO_MMIO_DEVICE_FEATURES_SEL] "VIRTIO_MMIO_DEVICE_FEATURES_SEL",
84         [VIRTIO_MMIO_DRIVER_FEATURES] "VIRTIO_MMIO_DRIVER_FEATURES",
85         [VIRTIO_MMIO_DRIVER_FEATURES_SEL] "VIRTIO_MMIO_DRIVER_FEATURES_SEL",
86         [VIRTIO_MMIO_GUEST_PAGE_SIZE] "VIRTIO_MMIO_GUEST_PAGE_SIZE",
87         [VIRTIO_MMIO_QUEUE_SEL] "VIRTIO_MMIO_QUEUE_SEL",
88         [VIRTIO_MMIO_QUEUE_NUM_MAX] "VIRTIO_MMIO_QUEUE_NUM_MAX",
89         [VIRTIO_MMIO_QUEUE_NUM] "VIRTIO_MMIO_QUEUE_NUM",
90         [VIRTIO_MMIO_QUEUE_ALIGN] "VIRTIO_MMIO_QUEUE_ALIGN",
91         [VIRTIO_MMIO_QUEUE_PFN] "VIRTIO_MMIO_QUEUE_PFN",
92         [VIRTIO_MMIO_QUEUE_READY] "VIRTIO_MMIO_QUEUE_READY",
93         [VIRTIO_MMIO_QUEUE_NOTIFY] "VIRTIO_MMIO_QUEUE_NOTIFY",
94         [VIRTIO_MMIO_INTERRUPT_STATUS] "VIRTIO_MMIO_INTERRUPT_STATUS",
95         [VIRTIO_MMIO_INTERRUPT_ACK] "VIRTIO_MMIO_INTERRUPT_ACK",
96         [VIRTIO_MMIO_STATUS] "VIRTIO_MMIO_STATUS",
97         [VIRTIO_MMIO_QUEUE_DESC_LOW] "VIRTIO_MMIO_QUEUE_DESC_LOW",
98         [VIRTIO_MMIO_QUEUE_DESC_HIGH] "VIRTIO_MMIO_QUEUE_DESC_HIGH",
99         [VIRTIO_MMIO_QUEUE_AVAIL_LOW] "VIRTIO_MMIO_QUEUE_AVAIL_LOW",
100         [VIRTIO_MMIO_QUEUE_AVAIL_HIGH] "VIRTIO_MMIO_QUEUE_AVAIL_HIGH",
101         [VIRTIO_MMIO_QUEUE_USED_LOW] "VIRTIO_MMIO_QUEUE_USED_LOW",
102         [VIRTIO_MMIO_QUEUE_USED_HIGH] "VIRTIO_MMIO_QUEUE_USED_HIGH",
103         [VIRTIO_MMIO_CONFIG_GENERATION] "VIRTIO_MMIO_CONFIG_GENERATION",
104 };
105
106 /* We're going to attempt to make mmio stateless, since the real machine is in
107  * the guest kernel. From what we know so far, all IO to the mmio space is 32 bits.
108  */
109 static uint32_t virtio_mmio_read(uint64_t gpa)
110 {
111
112         unsigned int offset = gpa - mmio.bar;
113         uint32_t low;
114         
115         DPRINTF("virtio_mmio_read offset %s 0x%x\n", virtio_names[offset],(int)offset);
116
117         /* If no backend is present, we treat most registers as
118          * read-as-zero, except for the magic number, version and
119          * vendor ID. This is not strictly sanctioned by the virtio
120          * spec, but it allows us to provide transports with no backend
121          * plugged in which don't confuse Linux's virtio code: the
122          * probe won't complain about the bad magic number, but the
123          * device ID of zero means no backend will claim it.
124          */
125         if (mmio.vqdev->numvqs == 0) {
126                 switch (offset) {
127                 case VIRTIO_MMIO_MAGIC_VALUE:
128                         return VIRT_MAGIC;
129                 case VIRTIO_MMIO_VERSION:
130                         return VIRT_VERSION;
131                 case VIRTIO_MMIO_VENDOR_ID:
132                         return VIRT_VENDOR;
133                 default:
134                         return 0;
135                 }
136         }
137
138
139     // WTF? Does this happen? 
140     if (offset >= VIRTIO_MMIO_CONFIG) {
141             fprintf(stderr, "Whoa. Reading past mmio config space? What gives?\n");
142             return -1;
143 #if 0
144             offset -= VIRTIO_MMIO_CONFIG;
145             switch (size) {
146             case 1:
147                     return virtio_config_readb(vdev, offset);
148             case 2:
149                     return virtio_config_readw(vdev, offset);
150             case 4:
151                     return virtio_config_readl(vdev, offset);
152             default:
153                     abort();
154             }
155 #endif
156     }
157
158 #if 0
159     if (size != 4) {
160         DPRINTF("wrong size access to register!\n");
161         return 0;
162     }
163 #endif
164     switch (offset) {
165     case VIRTIO_MMIO_MAGIC_VALUE:
166             return VIRT_MAGIC;
167     case VIRTIO_MMIO_VERSION:
168             return VIRT_VERSION;
169     case VIRTIO_MMIO_DEVICE_ID:
170             return mmio.vqdev->dev;
171     case VIRTIO_MMIO_VENDOR_ID:
172             return VIRT_VENDOR;
173     case VIRTIO_MMIO_DEVICE_FEATURES:
174         low = mmio.vqdev->device_features >> ((mmio.device_features_word) ? 32 : 0);
175         DPRINTF("RETURN from 0x%x 32 bits of word %s : 0x%x \n", mmio.vqdev->device_features, 
176                                 mmio.device_features_word ? "high" : "low", low);
177             return low;
178     case VIRTIO_MMIO_QUEUE_NUM_MAX:
179             DPRINTF("For q %d, qnum is %d\n", mmio.qsel, mmio.vqdev->vqs[mmio.qsel].qnum);
180             return mmio.vqdev->vqs[mmio.qsel].maxqnum;
181     case VIRTIO_MMIO_QUEUE_PFN:
182             return mmio.vqdev->vqs[mmio.qsel].pfn;
183     case VIRTIO_MMIO_INTERRUPT_STATUS:
184             return mmio.vqdev->vqs[mmio.qsel].isr;
185     case VIRTIO_MMIO_STATUS:
186             return mmio.vqdev->vqs[mmio.qsel].status;
187     case VIRTIO_MMIO_DEVICE_FEATURES_SEL:
188     case VIRTIO_MMIO_DRIVER_FEATURES:
189     case VIRTIO_MMIO_DRIVER_FEATURES_SEL:
190     case VIRTIO_MMIO_GUEST_PAGE_SIZE:
191     case VIRTIO_MMIO_QUEUE_SEL:
192     case VIRTIO_MMIO_QUEUE_NUM:
193     case VIRTIO_MMIO_QUEUE_ALIGN:
194     case VIRTIO_MMIO_QUEUE_READY:
195     case VIRTIO_MMIO_INTERRUPT_ACK:
196             fprintf(stderr, "read of write-only register@%p\n", (void *)gpa);
197         return 0;
198     default:
199             fprintf(stderr, "bad register offset@%p\n", (void *)gpa);
200         return 0;
201     }
202     return 0;
203 }
204
205 static void virtio_mmio_write(uint64_t gpa, uint32_t value)
206 {
207         uint64_t val64;
208         uint32_t low, high;
209         unsigned int offset = gpa - mmio.bar;
210         
211         DPRINTF("virtio_mmio_write offset %s 0x%x value 0x%x\n", virtio_names[offset], (int)offset, value);
212
213     if (offset >= VIRTIO_MMIO_CONFIG) {
214             fprintf(stderr, "Whoa. Writing past mmio config space? What gives?\n");
215 #if 0
216         offset -= VIRTIO_MMIO_CONFIG;
217         switch (size) {
218         case 1:
219             virtio_config_writeb(vdev, offset, value);
220             break;
221         case 2:
222             virtio_config_writew(vdev, offset, value);
223             break;
224         case 4:
225             virtio_config_writel(vdev, offset, value);
226             break;
227         default:
228             abort();
229         }
230 #endif
231         return;
232     }
233 #if 0
234     if (size != 4) {
235         DPRINTF("wrong size access to register!\n");
236         return;
237     }
238 #endif
239     switch (offset) {
240     case VIRTIO_MMIO_DEVICE_FEATURES_SEL:
241         mmio.device_features_word = value;
242         break;
243     case VIRTIO_MMIO_DEVICE_FEATURES:
244         if (mmio.device_features_word) {
245             /* changing the high word. */
246             low = mmio.vqdev->device_features;
247             high = value;
248         } else {
249             /* changing the low word. */
250             high = (mmio.vqdev->device_features >> 32);
251             low = value;
252         }
253         mmio.vqdev->device_features = ((uint64_t)high << 32) | low;
254         DPRINTF("Set VIRTIO_MMIO_DEVICE_FEATURES to %p\n", mmio.vqdev->device_features);
255         break;
256     case VIRTIO_MMIO_DRIVER_FEATURES:
257         if (mmio.driver_features_word) {
258             /* changing the high word. */
259             low = mmio.vqdev->driver_features;
260             high = value;
261         } else {
262             /* changing the low word. */
263             high = (mmio.vqdev->driver_features >> 32);
264             low = value;
265         }
266         mmio.vqdev->driver_features = ((uint64_t)high << 32) | low;
267         DPRINTF("Set VIRTIO_MMIO_DRIVER_FEATURES to %p\n", mmio.vqdev->driver_features);
268         break;
269     case VIRTIO_MMIO_DRIVER_FEATURES_SEL:
270             mmio.driver_features_word = value;
271         break;
272
273     case VIRTIO_MMIO_GUEST_PAGE_SIZE:
274             mmio.pagesize = value;
275             DPRINTF("guest page size %d bytes\n", mmio.pagesize);
276         break;
277     case VIRTIO_MMIO_QUEUE_SEL:
278             /* don't check it here. Check it on use. Or maybe check it here. Who knows. */
279             if (value < mmio.vqdev->numvqs)
280                     mmio.qsel = value;
281             else
282                     mmio.qsel = -1;
283             break;
284     case VIRTIO_MMIO_QUEUE_NUM:
285         mmio.vqdev->vqs[mmio.qsel].qnum = value;
286         break;
287     case VIRTIO_MMIO_QUEUE_ALIGN:
288         mmio.vqdev->vqs[mmio.qsel].qalign = value;
289         break;
290     case VIRTIO_MMIO_QUEUE_PFN:
291         // failure of vision: they used 32 bit numbers. Geez.
292         // v2 is better, we'll do v1 for now.
293         mmio.vqdev->vqs[mmio.qsel].pfn = value;
294                     // let's kick off the thread and see how it goes?
295                     struct virtio_threadarg *va = malloc(sizeof(*va));
296                     va->arg = &mmio.vqdev->vqs[mmio.qsel];
297
298                     va->arg->virtio = vring_new_virtqueue(mmio.qsel, 
299                                                           mmio.vqdev->vqs[mmio.qsel].qnum,
300                                                           mmio.vqdev->vqs[mmio.qsel].qalign,
301                                                           false, // weak_barriers
302                                                           (void *)(mmio.vqdev->vqs[mmio.qsel].pfn * mmio.vqdev->vqs[mmio.qsel].qalign),
303                                                           NULL, NULL, /* callbacks */
304                                                           mmio.vqdev->vqs[mmio.qsel].name);
305                     fprintf(stderr, "START THE THREAD. pfn is 0x%x, virtio is %p\n", mmio.pagesize, va->arg->virtio);
306                     if (pthread_create(&va->arg->thread, NULL, va->arg->f, va)) {
307                             fprintf(stderr, "pth_create failed for vq %s", va->arg->name);
308                             perror("pth_create");
309                     }
310         break;
311     case VIRTIO_MMIO_QUEUE_NOTIFY:
312             if (value < mmio.vqdev->numvqs) {
313                     mmio.qsel = value;
314             }
315         break;
316     case VIRTIO_MMIO_INTERRUPT_ACK:
317         //vdev->isr &= ~value;
318         //virtio_update_irq(vdev);
319         break;
320     case VIRTIO_MMIO_STATUS:
321         if (!(value & VIRTIO_CONFIG_S_DRIVER_OK)) {
322             printf("VIRTIO_MMIO_STATUS write: NOT OK! 0x%x\n", value);
323         }
324
325         mmio.status |= value & 0xff;
326
327         if (value & VIRTIO_CONFIG_S_DRIVER_OK) {
328             printf("VIRTIO_MMIO_STATUS write: OK! 0x%x\n", value);
329         }
330
331         break;
332     case VIRTIO_MMIO_QUEUE_DESC_LOW:
333             val64 = mmio.vqdev->vqs[mmio.qsel].qdesc;
334             val64 = val64 >> 32;
335             val64 = (val64 <<32) | value;
336             mmio.vqdev->vqs[mmio.qsel].qdesc = val64;
337             DPRINTF("qdesc set low result 0xx%x\n", val64);
338             break;
339             
340     case VIRTIO_MMIO_QUEUE_DESC_HIGH:
341             val64 = (uint32_t) mmio.vqdev->vqs[mmio.qsel].qdesc;
342             mmio.vqdev->vqs[mmio.qsel].qdesc = (((uint64_t) value) <<32) | val64;
343             DPRINTF("qdesc set high result 0xx%x\n", mmio.vqdev->vqs[mmio.qsel].qdesc);
344             break;
345             
346 /* Selected queue's Available Ring address, 64 bits in two halves */
347     case VIRTIO_MMIO_QUEUE_AVAIL_LOW:
348             val64 = mmio.vqdev->vqs[mmio.qsel].qavail;
349             val64 = val64 >> 32;
350             val64 = (val64 <<32) | value;
351             mmio.vqdev->vqs[mmio.qsel].qavail = val64;
352             DPRINTF("qavail set low result 0xx%x\n", val64);
353             break;
354     case VIRTIO_MMIO_QUEUE_AVAIL_HIGH:
355             val64 = (uint32_t) mmio.vqdev->vqs[mmio.qsel].qavail;
356             mmio.vqdev->vqs[mmio.qsel].qavail = (((uint64_t) value) <<32) | val64;
357             DPRINTF("qavail set high result 0xx%x\n", mmio.vqdev->vqs[mmio.qsel].qavail);
358             break;
359             
360 /* Selected queue's Used Ring address, 64 bits in two halves */
361     case VIRTIO_MMIO_QUEUE_USED_LOW:
362             val64 = mmio.vqdev->vqs[mmio.qsel].qused;
363             val64 = val64 >> 32;
364             val64 = (val64 <<32) | value;
365             mmio.vqdev->vqs[mmio.qsel].qused = val64;
366             DPRINTF("qused set low result 0xx%x\n", val64);
367             break;
368     case VIRTIO_MMIO_QUEUE_USED_HIGH:
369             val64 = (uint32_t) mmio.vqdev->vqs[mmio.qsel].qused;
370             mmio.vqdev->vqs[mmio.qsel].qused = (((uint64_t) value) <<32) | val64;
371             DPRINTF("qused set used result 0xx%x\n", mmio.vqdev->vqs[mmio.qsel].qused);
372             break;
373             
374         // for v2. 
375     case VIRTIO_MMIO_QUEUE_READY:
376             if (value) {
377                     // let's kick off the thread and see how it goes?
378                     struct virtio_threadarg *va = malloc(sizeof(*va));
379                     va->arg = &mmio.vqdev->vqs[mmio.qsel];
380                     va->arg->virtio = (void *)(va->arg->pfn * mmio.pagesize);
381                     fprintf(stderr, "START THE THREAD. pfn is 0x%x, virtio is %p\n", mmio.pagesize, va->arg->virtio);
382                     if (pthread_create(&va->arg->thread, NULL, va->arg->f, va)) {
383                             fprintf(stderr, "pth_create failed for vq %s", va->arg->name);
384                             perror("pth_create");
385                     }
386             }
387             break;
388
389     case VIRTIO_MMIO_MAGIC_VALUE:
390     case VIRTIO_MMIO_VERSION:
391     case VIRTIO_MMIO_DEVICE_ID:
392     case VIRTIO_MMIO_VENDOR_ID:
393 //    case VIRTIO_MMIO_HOSTFEATURES:
394     case VIRTIO_MMIO_QUEUE_NUM_MAX:
395     case VIRTIO_MMIO_INTERRUPT_STATUS:
396         DPRINTF("write to readonly register\n");
397         break;
398
399     default:
400         DPRINTF("bad register offset 0x%x\n", offset);
401     }
402
403 }
404
405 static char *modrmreg[] = {"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"};
406
407 void virtio_mmio(struct vmctl *v)
408 {
409         int advance = 3; /* how much to move the IP forward at the end. 3 is a good default. */
410         // All virtio accesses seem to be 32 bits.
411         // valp points to a place to get or put the value. 
412         uint32_t *valp;
413         //DPRINTF("v is %p\n", v);
414         // regp points to the register in hw_trapframe from which
415         // to load or store a result.
416         uint64_t *regp;
417
418         // Duh, which way did he go George? Which way did he go? 
419         // First hit on Google gets you there!
420         // This is the guest physical address of the access.
421         // This is nice, because if we ever go with more complete
422         // instruction decode, knowing this gpa reduces our work:
423         // we don't have to find the source address in registers,
424         // only the register holding or receiving the value.
425         uint64_t gpa = v->gpa;
426         //DPRINTF("gpa is %p\n", gpa);
427
428         // To find out what to do, we have to look at
429         // RIP. Technically, we should read RIP, walk the page tables
430         // to find the PA, and read that. But we're in the kernel, so
431         // we take a shortcut for now: read the low 30 bits and use
432         // that as the kernel PA, or our VA, and see what's
433         // there. Hokey. Works.
434         uint8_t *kva = (void *)(v->regs.tf_rip & 0x3fffffff);
435         //DPRINTF("kva is %p\n", kva);
436
437         if ((kva[0] != 0x8b) && (kva[0] != 0x89)) {
438                 fprintf(stderr, "%s: can't handle instruction 0x%x\n", kva[0]);
439                 return;
440         }
441
442         uint16_t ins = *(uint16_t *)kva;
443         //DPRINTF("ins is %04x\n", ins);
444         
445         int write = (kva[0] == 0x8b) ? 0 : 1;
446         if (write)
447                 valp = (uint32_t *)gpa;
448
449         int mod = kva[1]>>6;
450         switch (mod) {
451                 case 0: 
452                 case 3:
453                         advance = 2;
454                         break;
455                 case 1:
456                         advance = 3;
457                         break;
458                 case 2: 
459                         advance = 6;
460                         break;
461         }
462         /* the dreaded mod/rm byte. */
463         int destreg = (ins>>11) & 7;
464         // Our primitive approach wins big here.
465         // We don't have to decode the register or the offset used
466         // in the computation; that was done by the CPU and is the gpa.
467         // All we need to know is which destination or source register it is.
468         switch (destreg) {
469         case 0:
470                 regp = &v->regs.tf_rax;
471                 break;
472         case 1:
473                 regp = &v->regs.tf_rcx;
474                 break;
475         case 2:
476                 regp = &v->regs.tf_rdx;
477                 break;
478         case 3:
479                 regp = &v->regs.tf_rbx;
480                 break;
481         case 4:
482                 regp = &v->regs.tf_rsp; // uh, right.
483                 break;
484         case 5:
485                 regp = &v->regs.tf_rbp;
486                 break;
487         case 6:
488                 regp = &v->regs.tf_rsi;
489                 break;
490         case 7:
491                 regp = &v->regs.tf_rdi;
492                 break;
493         }
494
495         if (write) {
496                 virtio_mmio_write(gpa, *regp);
497                 DPRINTF("Write: mov %s to %s @%p val %p\n", modrmreg[destreg], virtio_names[(uint8_t)gpa], gpa, *regp);
498         } else {
499                 *regp = virtio_mmio_read(gpa);
500                 DPRINTF("Read: Set %s from %s @%p to %p\n", modrmreg[destreg], virtio_names[(uint8_t)gpa], gpa, *regp);
501         }
502
503         DPRINTF("Advance rip by %d bytes to %p\n", advance, v->regs.tf_rip);
504         v->regs.tf_rip += advance;
505 }