Move ros/vmx.h to an arch-specific location (XCC)
[akaros.git] / user / vmm / decode.c
1 /*
2  * Copyright 2015 Google Inc.
3  *
4  * This file is part of Akaros.
5  *
6  * Akarosn is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, version 2 of the License.
9  * 
10  * Akaros is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * Lesser GNU General Public License for more details.
14  * 
15  * See COPYING.LESSER for details on the GNU Lesser General Public License.
16  * See COPYING for details on the GNU General Public License.
17  */
18
19 #include <stdio.h>
20 #include <sys/types.h>
21 #include <pthread.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24 #include <parlib/arch/arch.h>
25 #include <parlib/ros_debug.h>
26 #include <unistd.h>
27 #include <errno.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <sys/uio.h>
31 #include <stdint.h>
32 #include <err.h>
33 #include <sys/mman.h>
34 #include <vmm/vmm.h>
35 #include <vmm/virtio.h>
36 #include <vmm/virtio_mmio.h>
37 #include <vmm/virtio_ids.h>
38 #include <vmm/virtio_config.h>
39
40 int debug_decode = 0;
41 #define DPRINTF(fmt, ...) \
42         if (debug_decode) { printf("decode: " fmt , ## __VA_ARGS__); }
43
44 static char *modrmreg[] = {"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"};
45
46 // Since we at most have to decode less than half of each instruction, I'm trying to be dumb here.
47 // Fortunately, for me, that's not hard.
48 // I'm trying to avoid the whole Big Fun of full instruction decode, and in most of these
49 // cases we only have to know register, address, operation size, and instruction length.
50 // The ugly messiness of the SIB and all that are not yet needed. Maybe they
51 // never will be.
52
53 // Target size -- 1, 2, 4, or 8 bytes. We have yet to see 64 bytes. 
54 // TODO: if we ever see it, test the prefix. Since this only supports the low 1M,
55 // that's not likely.
56 static int target(void *insn, int *store) 
57 {
58         *store = 0;
59         int s = -1;
60         uint8_t *byte = insn;
61         uint16_t *word = insn;
62
63         if (*byte == 0x66) {
64                 s = target(insn+1,store);
65                 // flip the sense of s.
66                 s = s == 4 ? 2 : 4;
67                 return s;
68         }
69         if (*byte == 0x44) {
70                 byte++;
71                 word++;
72         }
73         switch(*byte) {
74         case 0x3a:
75         case 0x8a:
76         case 0x88:
77                 s = 1;
78                 break;
79         case 0x89:
80         case 0x8b:
81                 s = 2;
82                 break;
83         case 0x81:
84                 s = 4;  
85                 break;
86         case 0x0f:
87         switch(*word) {
88                 case 0xb70f:
89                         s = 4;
90                         break;
91                 default:
92                         fprintf(stderr, "can't get size of %02x/%04x @ %p\n", *byte, *word, byte);
93                         return -1;
94                         break;
95                 }
96                 break;
97         default:
98                 fprintf(stderr, "can't get size of %02x @ %p\n", *byte, byte);
99                 return -1;
100                 break;
101         }
102
103         switch(*byte) {
104         case 0x3a:
105         case 0x8a:
106         case 0x88:
107         case 0x89:
108         case 0x8b:
109         case 0x81:
110                 *store = !(*byte & 2);
111                 break;
112         default:
113                 fprintf(stderr, "%s: Can't happen\n", __func__);
114                 break;
115         }
116         return s;
117 }
118
119 char *regname(uint8_t reg)
120 {
121         return modrmreg[reg];
122 }
123
124 static int insize(void *rip)
125 {
126         uint8_t *kva = rip;
127         int advance = 3;
128         int extra = 0;
129         if (kva[0] == 0x44) {
130                 extra = 1;
131                 kva++;
132         }
133
134         /* the dreaded mod/rm byte. */
135         int mod = kva[1]>>6;
136         int rm = kva[1] & 7;
137
138         switch(kva[0]) {
139         default: 
140                 fprintf(stderr, "BUG! %s got 0x%x\n", __func__, kva[0]);
141         case 0x0f: 
142                 break;
143         case 0x81:
144                 advance = 6 + extra;
145                 break;
146         case 0x3a:
147         case 0x8a:
148         case 0x88:
149         case 0x89:
150         case 0x8b:
151                 switch (mod) {
152                 case 0: 
153                         advance = 2 + (rm == 4) + extra;
154                         break;
155                 case 1:
156                         advance = 3 + (rm == 4) + extra;
157                         break;
158                 case 2: 
159                         advance = 6 + (rm == 4) + extra;
160                         break;
161                 case 3:
162                         advance = 2 + extra;
163                         break;
164                 }
165                 break;
166         }
167         return advance;
168 }
169
170 // This is a very limited function. It's only here to manage virtio-mmio and low memory
171 // pointer loads. I am hoping it won't grow with time. The intent is that we enter it with
172 // and EPT fault from a region that is deliberately left unbacked by any memory. We return
173 // enough info to let you emulate the operation if you want. Because we have the failing physical
174 // address (gpa) the decode is far simpler because we only need to find the register, how many bytes
175 // to move, and how big the instruction is. I thought about bringing in emulate.c from kvm from xen,
176 // but it has way more stuff than we need.
177 // gpa is a pointer to the gpa. 
178 // int is the reg index which we can use for printing info.
179 // regp points to the register in hw_trapframe from which
180 // to load or store a result.
181 int decode(struct vmctl *v, uint64_t *gpa, uint8_t *destreg, uint64_t **regp, int *store, int *size, int *advance)
182 {
183
184         DPRINTF("v is %p\n", v);
185
186         // Duh, which way did he go George? Which way did he go? 
187         // First hit on Google gets you there!
188         // This is the guest physical address of the access.
189         // This is nice, because if we ever go with more complete
190         // instruction decode, knowing this gpa reduces our work:
191         // we don't have to find the source address in registers,
192         // only the register holding or receiving the value.
193         *gpa = v->gpa;
194         DPRINTF("gpa is %p\n", *gpa);
195
196         // To find out what to do, we have to look at
197         // RIP. Technically, we should read RIP, walk the page tables
198         // to find the PA, and read that. But we're in the kernel, so
199         // we take a shortcut for now: read the low 30 bits and use
200         // that as the kernel PA, or our VA, and see what's
201         // there. Hokey. Works.
202         uint8_t *kva = (void *)(v->regs.tf_rip & 0x3fffffff);
203         DPRINTF("kva is %p\n", kva);
204
205         // fail fast. If we can't get the size we're done.
206         *size = target(kva, store);
207         if (*size < 0)
208                 return -1;
209
210         *advance = insize(kva);
211
212         uint16_t ins = *(uint16_t *)(kva + (kva[0] == 0x44));
213         DPRINTF("ins is %04x\n", ins);
214                 
215         *destreg = (ins>>11) & 7;
216         *destreg += 8*(kva[0] == 0x44);
217         // Our primitive approach wins big here.
218         // We don't have to decode the register or the offset used
219         // in the computation; that was done by the CPU and is the gpa.
220         // All we need to know is which destination or source register it is.
221         switch (*destreg) {
222         case 0:
223                 *regp = &v->regs.tf_rax;
224                 break;
225         case 1:
226                 *regp = &v->regs.tf_rcx;
227                 break;
228         case 2:
229                 *regp = &v->regs.tf_rdx;
230                 break;
231         case 3:
232                 *regp = &v->regs.tf_rbx;
233                 break;
234         case 4:
235                 *regp = &v->regs.tf_rsp; // uh, right.
236                 break;
237         case 5:
238                 *regp = &v->regs.tf_rbp;
239                 break;
240         case 6:
241                 *regp = &v->regs.tf_rsi;
242                 break;
243         case 7:
244                 *regp = &v->regs.tf_rdi;
245                 break;
246         case 8:
247                 *regp = &v->regs.tf_r8;
248                 break;
249         case 9:
250                 *regp = &v->regs.tf_r9;
251                 break;
252         case 10:
253                 *regp = &v->regs.tf_r10;
254                 break;
255         case 11:
256                 *regp = &v->regs.tf_r11;
257                 break;
258         case 12:
259                 *regp = &v->regs.tf_r12;
260                 break;
261         case 13:
262                 *regp = &v->regs.tf_r13;
263                 break;
264         case 14:
265                 *regp = &v->regs.tf_r14;
266                 break;
267         case 15:
268                 *regp = &v->regs.tf_r15;
269                 break;
270         }
271         return 0;
272 }
273
274 #if 0
275 // stupid emulator since what we need is so limited.
276 int emu(struct vmctl *v, uint64_t gpa, uint8_t destreg, uint64_t *regp, int store, int size, int advance)
277 {
278         uint8_t *kva = f->regs.tf_rip;
279
280         if (
281         switch(kva[0]) {
282
283                                 val = *(uint64_t*) (lowmem + gpa); 
284                                 printf("val %p ", val);
285                                 memcpy(regp, &val, size);
286
287 }
288 #endif