Begin work on true virtio mmio Kill tests/vmrunkernel.c Our makefiles, plus emacs...
[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 = 1;
44 #define DPRINTF(fmt, ...) \
45         if (debug_virtio_mmio) { printf("virtio_mmio: " fmt , ## __VA_ARGS__); }
46
47
48 #define VIRT_MAGIC 0x74726976 /* 'virt' */
49 #define VIRT_VERSION 2
50 #define VIRT_VENDOR 0x554D4551 /* 'QEMU' */
51
52
53 typedef struct {
54         int state; // not used yet. */
55         uint64_t bar;
56         uint32_t status;
57         int qsel; // queue we are on.
58         int pagesize;
59         int page_shift;
60         int host_features_sel;
61         int guest_features_sel;
62         struct vqdev *vqdev;
63 } mmiostate;
64
65 static mmiostate mmio;
66
67 void register_virtio_mmio(struct vqdev *vqdev, uint64_t virtio_base)
68 {
69         mmio.bar = virtio_base;
70         mmio.vqdev = vqdev;
71 }
72
73 static uint32_t virtio_mmio_read(uint64_t gpa);
74 char *virtio_names[] = {
75         [VIRTIO_MMIO_MAGIC_VALUE] "VIRTIO_MMIO_MAGIC_VALUE",
76         [VIRTIO_MMIO_VERSION] "VIRTIO_MMIO_VERSION",
77         [VIRTIO_MMIO_DEVICE_ID] "VIRTIO_MMIO_DEVICE_ID",
78         [VIRTIO_MMIO_VENDOR_ID] "VIRTIO_MMIO_VENDOR_ID",
79         [VIRTIO_MMIO_DEVICE_FEATURES] "VIRTIO_MMIO_DEVICE_FEATURES",
80         [VIRTIO_MMIO_DEVICE_FEATURES_SEL] "VIRTIO_MMIO_DEVICE_FEATURES_SEL",
81         [VIRTIO_MMIO_DRIVER_FEATURES] "VIRTIO_MMIO_DRIVER_FEATURES",
82         [VIRTIO_MMIO_DRIVER_FEATURES_SEL] "VIRTIO_MMIO_DRIVER_FEATURES_SEL",
83         [VIRTIO_MMIO_GUEST_PAGE_SIZE] "VIRTIO_MMIO_GUEST_PAGE_SIZE",
84         [VIRTIO_MMIO_QUEUE_SEL] "VIRTIO_MMIO_QUEUE_SEL",
85         [VIRTIO_MMIO_QUEUE_NUM_MAX] "VIRTIO_MMIO_QUEUE_NUM_MAX",
86         [VIRTIO_MMIO_QUEUE_NUM] "VIRTIO_MMIO_QUEUE_NUM",
87         [VIRTIO_MMIO_QUEUE_ALIGN] "VIRTIO_MMIO_QUEUE_ALIGN",
88         [VIRTIO_MMIO_QUEUE_PFN] "VIRTIO_MMIO_QUEUE_PFN",
89         [VIRTIO_MMIO_QUEUE_READY] "VIRTIO_MMIO_QUEUE_READY",
90         [VIRTIO_MMIO_QUEUE_NOTIFY] "VIRTIO_MMIO_QUEUE_NOTIFY",
91         [VIRTIO_MMIO_INTERRUPT_STATUS] "VIRTIO_MMIO_INTERRUPT_STATUS",
92         [VIRTIO_MMIO_INTERRUPT_ACK] "VIRTIO_MMIO_INTERRUPT_ACK",
93         [VIRTIO_MMIO_STATUS] "VIRTIO_MMIO_STATUS",
94         [VIRTIO_MMIO_QUEUE_DESC_LOW] "VIRTIO_MMIO_QUEUE_DESC_LOW",
95         [VIRTIO_MMIO_QUEUE_DESC_HIGH] "VIRTIO_MMIO_QUEUE_DESC_HIGH",
96         [VIRTIO_MMIO_QUEUE_AVAIL_LOW] "VIRTIO_MMIO_QUEUE_AVAIL_LOW",
97         [VIRTIO_MMIO_QUEUE_AVAIL_HIGH] "VIRTIO_MMIO_QUEUE_AVAIL_HIGH",
98         [VIRTIO_MMIO_QUEUE_USED_LOW] "VIRTIO_MMIO_QUEUE_USED_LOW",
99         [VIRTIO_MMIO_QUEUE_USED_HIGH] "VIRTIO_MMIO_QUEUE_USED_HIGH",
100         [VIRTIO_MMIO_CONFIG_GENERATION] "VIRTIO_MMIO_CONFIG_GENERATION",
101 };
102
103 /* We're going to attempt to make mmio stateless, since the real machine is in
104  * the guest kernel. From what we know so far, all IO to the mmio space is 32 bits.
105  */
106 static uint32_t virtio_mmio_read(uint64_t gpa)
107 {
108
109         unsigned int offset = gpa - mmio.bar;
110         
111         DPRINTF("virtio_mmio_read offset %s 0x%x\n", virtio_names[offset],(int)offset);
112
113         /* If no backend is present, we treat most registers as
114          * read-as-zero, except for the magic number, version and
115          * vendor ID. This is not strictly sanctioned by the virtio
116          * spec, but it allows us to provide transports with no backend
117          * plugged in which don't confuse Linux's virtio code: the
118          * probe won't complain about the bad magic number, but the
119          * device ID of zero means no backend will claim it.
120          */
121         if (mmio.vqdev->numvqs == 0) {
122                 switch (offset) {
123                 case VIRTIO_MMIO_MAGIC_VALUE:
124                         return VIRT_MAGIC;
125                 case VIRTIO_MMIO_VERSION:
126                         return VIRT_VERSION;
127                 case VIRTIO_MMIO_VENDOR_ID:
128                         return VIRT_VENDOR;
129                 default:
130                         return 0;
131                 }
132         }
133
134
135     // WTF? Does this happen? 
136     if (offset >= VIRTIO_MMIO_CONFIG) {
137             fprintf(stderr, "Whoa. Reading past mmio config space? What gives?\n");
138             return -1;
139 #if 0
140             offset -= VIRTIO_MMIO_CONFIG;
141             switch (size) {
142             case 1:
143                     return virtio_config_readb(vdev, offset);
144             case 2:
145                     return virtio_config_readw(vdev, offset);
146             case 4:
147                     return virtio_config_readl(vdev, offset);
148             default:
149                     abort();
150             }
151 #endif
152     }
153
154 #if 0
155     if (size != 4) {
156         DPRINTF("wrong size access to register!\n");
157         return 0;
158     }
159 #endif
160 DPRINTF("FUCK 0x%x\n", offset);
161 fprintf(stderr, "FUCK2 0x%x\n", offset);
162     switch (offset) {
163     case VIRTIO_MMIO_MAGIC_VALUE:
164             return VIRT_MAGIC;
165     case VIRTIO_MMIO_VERSION:
166             return VIRT_VERSION;
167     case VIRTIO_MMIO_DEVICE_ID:
168             return mmio.vqdev->dev;
169     case VIRTIO_MMIO_VENDOR_ID:
170             return VIRT_VENDOR;
171     case VIRTIO_MMIO_DEVICE_FEATURES:
172 // ???      if (proxy->host_features_sel) {
173 //          return 0;
174 //          }
175         printf("FUCK %x\n", mmio.vqdev->features);
176         DPRINTF("RETURN 0x%x \n", mmio.vqdev->features);
177             return mmio.vqdev->features;
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         unsigned int offset = gpa - mmio.bar;
209         
210         DPRINTF("virtio_mmio_write offset %s 0x%x value 0x%x\n", virtio_names[offset], (int)offset, value);
211
212     if (offset >= VIRTIO_MMIO_CONFIG) {
213             fprintf(stderr, "Whoa. Writing past mmio config space? What gives?\n");
214 #if 0
215         offset -= VIRTIO_MMIO_CONFIG;
216         switch (size) {
217         case 1:
218             virtio_config_writeb(vdev, offset, value);
219             break;
220         case 2:
221             virtio_config_writew(vdev, offset, value);
222             break;
223         case 4:
224             virtio_config_writel(vdev, offset, value);
225             break;
226         default:
227             abort();
228         }
229 #endif
230         return;
231     }
232 #if 0
233     if (size != 4) {
234         DPRINTF("wrong size access to register!\n");
235         return;
236     }
237 #endif
238     switch (offset) {
239     case VIRTIO_MMIO_DEVICE_FEATURES_SEL:
240         mmio.host_features_sel = value;
241         break;
242         /* what's the difference here? Maybe FEATURES is the one you offer. */
243     case VIRTIO_MMIO_DRIVER_FEATURES:
244         if (!mmio.guest_features_sel) {
245             mmio.guest_features_sel = value;
246         }
247         break;
248     case VIRTIO_MMIO_DRIVER_FEATURES_SEL:
249             mmio.guest_features_sel = value;
250         break;
251
252     case VIRTIO_MMIO_GUEST_PAGE_SIZE:
253             mmio.pagesize = value;
254             DPRINTF("guest page size %d bytes\n", mmio.pagesize);
255         break;
256     case VIRTIO_MMIO_QUEUE_SEL:
257             /* don't check it here. Check it on use. Or maybe check it here. Who knows. */
258             if (value < mmio.vqdev->numvqs)
259                     mmio.qsel = value;
260             else
261                     mmio.qsel = -1;
262             break;
263     case VIRTIO_MMIO_QUEUE_NUM:
264         mmio.vqdev->vqs[mmio.qsel].qnum = value;
265         break;
266     case VIRTIO_MMIO_QUEUE_ALIGN:
267         mmio.vqdev->vqs[mmio.qsel].qalign = value;
268         break;
269     case VIRTIO_MMIO_QUEUE_PFN:
270         // failure of vision: they used 32 bit numbers. Geez.
271         // v2 is better, we'll do v1 for now.
272         mmio.vqdev->vqs[mmio.qsel].pfn = value;
273                     // let's kick off the thread and see how it goes?
274                     struct virtio_threadarg *va = malloc(sizeof(*va));
275                     va->arg = &mmio.vqdev->vqs[mmio.qsel];
276                     va->arg->virtio = (void *)(va->arg->pfn * mmio.pagesize);
277                     fprintf(stderr, "START THE THREAD. pfn is 0x%x, virtio is %p\n", mmio.pagesize, va->arg->virtio);
278                     if (pthread_create(&va->arg->thread, NULL, va->arg->f, va)) {
279                             fprintf(stderr, "pth_create failed for vq %s", va->arg->name);
280                             perror("pth_create");
281                     }
282         break;
283     case VIRTIO_MMIO_QUEUE_NOTIFY:
284             if (value < mmio.vqdev->numvqs) {
285                     mmio.qsel = value;
286             }
287         break;
288     case VIRTIO_MMIO_INTERRUPT_ACK:
289         //vdev->isr &= ~value;
290         //virtio_update_irq(vdev);
291         break;
292     case VIRTIO_MMIO_STATUS:
293         if (!(value & VIRTIO_CONFIG_S_DRIVER_OK)) {
294             printf("VIRTIO_MMIO_STATUS write: NOT OK! 0x%x\n", value);
295         }
296
297         mmio.status |= value & 0xff;
298
299         if (value & VIRTIO_CONFIG_S_DRIVER_OK) {
300             printf("VIRTIO_MMIO_STATUS write: OK! 0x%x\n", value);
301         }
302
303         break;
304     case VIRTIO_MMIO_QUEUE_DESC_LOW:
305             val64 = mmio.vqdev->vqs[mmio.qsel].qdesc;
306             val64 = val64 >> 32;
307             val64 = (val64 <<32) | value;
308             mmio.vqdev->vqs[mmio.qsel].qdesc = val64;
309             DPRINTF("qdesc set low result 0xx%x\n", val64);
310             break;
311             
312     case VIRTIO_MMIO_QUEUE_DESC_HIGH:
313             val64 = (uint32_t) mmio.vqdev->vqs[mmio.qsel].qdesc;
314             mmio.vqdev->vqs[mmio.qsel].qdesc = (((uint64_t) value) <<32) | val64;
315             DPRINTF("qdesc set high result 0xx%x\n", mmio.vqdev->vqs[mmio.qsel].qdesc);
316             break;
317             
318 /* Selected queue's Available Ring address, 64 bits in two halves */
319     case VIRTIO_MMIO_QUEUE_AVAIL_LOW:
320             val64 = mmio.vqdev->vqs[mmio.qsel].qavail;
321             val64 = val64 >> 32;
322             val64 = (val64 <<32) | value;
323             mmio.vqdev->vqs[mmio.qsel].qavail = val64;
324             DPRINTF("qavail set low result 0xx%x\n", val64);
325             break;
326     case VIRTIO_MMIO_QUEUE_AVAIL_HIGH:
327             val64 = (uint32_t) mmio.vqdev->vqs[mmio.qsel].qavail;
328             mmio.vqdev->vqs[mmio.qsel].qavail = (((uint64_t) value) <<32) | val64;
329             DPRINTF("qavail set high result 0xx%x\n", mmio.vqdev->vqs[mmio.qsel].qavail);
330             break;
331             
332 /* Selected queue's Used Ring address, 64 bits in two halves */
333     case VIRTIO_MMIO_QUEUE_USED_LOW:
334             val64 = mmio.vqdev->vqs[mmio.qsel].qused;
335             val64 = val64 >> 32;
336             val64 = (val64 <<32) | value;
337             mmio.vqdev->vqs[mmio.qsel].qused = val64;
338             DPRINTF("qused set low result 0xx%x\n", val64);
339             break;
340     case VIRTIO_MMIO_QUEUE_USED_HIGH:
341             val64 = (uint32_t) mmio.vqdev->vqs[mmio.qsel].qused;
342             mmio.vqdev->vqs[mmio.qsel].qused = (((uint64_t) value) <<32) | val64;
343             DPRINTF("qused set used result 0xx%x\n", mmio.vqdev->vqs[mmio.qsel].qused);
344             break;
345             
346         // for v2. 
347     case VIRTIO_MMIO_QUEUE_READY:
348             if (value) {
349                     // let's kick off the thread and see how it goes?
350                     struct virtio_threadarg *va = malloc(sizeof(*va));
351                     va->arg = &mmio.vqdev->vqs[mmio.qsel];
352                     va->arg->virtio = (void *)(va->arg->pfn * mmio.pagesize);
353                     fprintf(stderr, "START THE THREAD. pfn is 0x%x, virtio is %p\n", mmio.pagesize, va->arg->virtio);
354                     if (pthread_create(&va->arg->thread, NULL, va->arg->f, va)) {
355                             fprintf(stderr, "pth_create failed for vq %s", va->arg->name);
356                             perror("pth_create");
357                     }
358             }
359             break;
360
361     case VIRTIO_MMIO_MAGIC_VALUE:
362     case VIRTIO_MMIO_VERSION:
363     case VIRTIO_MMIO_DEVICE_ID:
364     case VIRTIO_MMIO_VENDOR_ID:
365 //    case VIRTIO_MMIO_HOSTFEATURES:
366     case VIRTIO_MMIO_QUEUE_NUM_MAX:
367     case VIRTIO_MMIO_INTERRUPT_STATUS:
368         DPRINTF("write to readonly register\n");
369         break;
370
371     default:
372         DPRINTF("bad register offset 0x%x\n", offset);
373     }
374
375 }
376
377 static char *modrmreg[] = {"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"};
378
379 void virtio_mmio(struct vmctl *v)
380 {
381         int advance = 3; /* how much to move the IP forward at the end. 3 is a good default. */
382         // All virtio accesses seem to be 32 bits.
383         // valp points to a place to get or put the value. 
384         uint32_t *valp;
385         //DPRINTF("v is %p\n", v);
386         // regp points to the register in hw_trapframe from which
387         // to load or store a result.
388         uint64_t *regp;
389
390         // Duh, which way did he go George? Which way did he go? 
391         // First hit on Google gets you there!
392         // This is the guest physical address of the access.
393         // This is nice, because if we ever go with more complete
394         // instruction decode, knowing this gpa reduces our work:
395         // we don't have to find the source address in registers,
396         // only the register holding or receiving the value.
397         uint64_t gpa = v->gpa;
398         //DPRINTF("gpa is %p\n", gpa);
399
400         // To find out what to do, we have to look at
401         // RIP. Technically, we should read RIP, walk the page tables
402         // to find the PA, and read that. But we're in the kernel, so
403         // we take a shortcut for now: read the low 30 bits and use
404         // that as the kernel PA, or our VA, and see what's
405         // there. Hokey. Works.
406         uint8_t *kva = (void *)(v->regs.tf_rip & 0x3fffffff);
407         //DPRINTF("kva is %p\n", kva);
408
409         if ((kva[0] != 0x8b) && (kva[0] != 0x89)) {
410                 fprintf(stderr, "%s: can't handle instruction 0x%x\n", kva[0]);
411                 return;
412         }
413
414         uint16_t ins = *(uint16_t *)kva;
415         //DPRINTF("ins is %04x\n", ins);
416         
417         int write = (kva[0] == 0x8b) ? 0 : 1;
418         if (write)
419                 valp = (uint32_t *)gpa;
420
421         int mod = kva[1]>>6;
422         switch (mod) {
423                 case 0: 
424                 case 3:
425                         advance = 2;
426                         break;
427                 case 1:
428                         advance = 3;
429                         break;
430                 case 2: 
431                         advance = 6;
432                         break;
433         }
434         /* the dreaded mod/rm byte. */
435         int destreg = (ins>>11) & 7;
436         // Our primitive approach wins big here.
437         // We don't have to decode the register or the offset used
438         // in the computation; that was done by the CPU and is the gpa.
439         // All we need to know is which destination or source register it is.
440         switch (destreg) {
441         case 0:
442                 regp = &v->regs.tf_rax;
443                 break;
444         case 1:
445                 regp = &v->regs.tf_rcx;
446                 break;
447         case 2:
448                 regp = &v->regs.tf_rdx;
449                 break;
450         case 3:
451                 regp = &v->regs.tf_rbx;
452                 break;
453         case 4:
454                 regp = &v->regs.tf_rsp; // uh, right.
455                 break;
456         case 5:
457                 regp = &v->regs.tf_rbp;
458                 break;
459         case 6:
460                 regp = &v->regs.tf_rsi;
461                 break;
462         case 7:
463                 regp = &v->regs.tf_rdi;
464                 break;
465         }
466
467         if (write) {
468                 virtio_mmio_write(gpa, *regp);
469                 DPRINTF("Write: mov %s to %s @%p val %p\n", modrmreg[destreg], virtio_names[(uint8_t)gpa], gpa, *regp);
470         } else {
471                 *regp = virtio_mmio_read(gpa);
472                 DPRINTF("Read: Set %s from %s @%p to %p\n", modrmreg[destreg], virtio_names[(uint8_t)gpa], gpa, *regp);
473         }
474
475         DPRINTF("Advance rip by %d bytes to %p\n", advance, v->regs.tf_rip);
476         v->regs.tf_rip += advance;
477 }