Add page table walk for guest va to pa translation
[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 #include <ros/arch/mmu.h>
40 #include <ros/arch/trapframe.h>
41
42 int debug_decode = 0;
43 #define DPRINTF(fmt, ...) \
44         if (debug_decode) { printf("decode: " fmt , ## __VA_ARGS__); }
45
46 static char *modrmreg[] = {"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"};
47
48 // Since we at most have to decode less than half of each instruction, I'm trying to be dumb here.
49 // Fortunately, for me, that's not hard.
50 // I'm trying to avoid the whole Big Fun of full instruction decode, and in most of these
51 // cases we only have to know register, address, operation size, and instruction length.
52 // The ugly messiness of the SIB and all that are not yet needed. Maybe they
53 // never will be.
54
55 // Target size -- 1, 2, 4, or 8 bytes. We have yet to see 64 bytes.
56 // TODO: if we ever see it, test the prefix. Since this only supports the low 1M,
57 // that's not likely.
58 static int target(void *insn, int *store)
59 {
60         *store = 0;
61         int s = -1;
62         uint8_t *byte = insn;
63         uint16_t *word = insn;
64
65         if (*byte == 0x66) {
66                 s = target(insn+1,store);
67                 // flip the sense of s.
68                 s = s == 4 ? 2 : 4;
69                 return s;
70         }
71         if (*byte == 0x44) {
72                 byte++;
73                 word++;
74         }
75         switch(*byte) {
76         case 0x3a:
77         case 0x8a:
78         case 0x88:
79                 s = 1;
80                 break;
81         case 0x89:
82         case 0x8b:
83                 // TODO: To really know, for sure, that this is 32 bit, we'd likely have
84                 //       to check the segment descriptor for the guest's current code
85                 //       segment in it's GDT. The D flag (bit 22) determines whether the
86                 //       instruction is using 32 or 16-bit operand size. I'm just going
87                 //       to assume the flag is set (meaning 32 bit operands) for now, in
88                 //       order to make virtio work. But really we should check if we
89                 //       want to know for sure. Note that this hack (changing the below
90                 //       line) only applies to mov instructions.
91                 //
92                 //       And I think there's also a prefix you can use to switch the
93                 //       instruction to 16-bit addressing
94                 //       (address-size override prefix?)
95                 s = 4;
96                 break;
97         case 0x81:
98                 s = 4;
99                 break;
100         case 0x0f:
101         switch(*word) {
102                 case 0xb70f:
103                         s = 2;
104                         break;
105                 default:
106                         fprintf(stderr, "can't get size of %02x/%04x @ %p\n", *byte, *word, byte);
107                         return -1;
108                         break;
109                 }
110                 break;
111         default:
112                 fprintf(stderr, "can't get size of %02x @ %p\n", *byte, byte);
113                 return -1;
114                 break;
115         }
116
117         switch(*byte) {
118         case 0x0f:
119                 break;
120         case 0x3a:
121         case 0x8a:
122         case 0x88:
123         case 0x89:
124         case 0x8b:
125         case 0x81:
126                 *store = !(*byte & 2);
127                 break;
128         default:
129                 fprintf(stderr, "%s: Can't happen. rip is: %p\n", __func__, byte);
130                 break;
131         }
132         return s;
133 }
134
135 char *regname(uint8_t reg)
136 {
137         return modrmreg[reg];
138 }
139
140 static int insize(void *rip)
141 {
142         uint8_t *rip_gpa = rip;
143         int advance = 3;
144         int extra = 0;
145         if (rip_gpa[0] == 0x44) {
146                 extra = 1;
147                 rip_gpa++;
148         }
149
150         /* the dreaded mod/rm byte. */
151         int mod = rip_gpa[1] >> 6;
152         int rm = rip_gpa[1] & 7;
153
154         switch (rip_gpa[0]) {
155         default:
156                 fprintf(stderr, "BUG! %s got 0x%x\n", __func__, rip_gpa[0]);
157         case 0x0f:
158                 break;
159         case 0x81:
160                 advance = 6 + extra;
161                 break;
162         case 0x3a:
163         case 0x8a:
164         case 0x88:
165         case 0x89:
166         case 0x8b:
167                 switch (mod) {
168                 case 0:
169                         advance = 2 + (rm == 4) + extra;
170                         break;
171                 case 1:
172                         advance = 3 + (rm == 4) + extra;
173                         break;
174                 case 2:
175                         advance = 6 + (rm == 4) + extra;
176                         break;
177                 case 3:
178                         advance = 2 + extra;
179                         break;
180                 }
181                 break;
182         }
183         return advance;
184 }
185
186 // This is a very limited function. It's only here to manage virtio-mmio and low memory
187 // pointer loads. I am hoping it won't grow with time. The intent is that we enter it with
188 // and EPT fault from a region that is deliberately left unbacked by any memory. We return
189 // enough info to let you emulate the operation if you want. Because we have the failing physical
190 // address (gpa) the decode is far simpler because we only need to find the register, how many bytes
191 // to move, and how big the instruction is. I thought about bringing in emulate.c from kvm from xen,
192 // but it has way more stuff than we need.
193 // gpa is a pointer to the gpa.
194 // int is the reg index which we can use for printing info.
195 // regp points to the register in hw_trapframe from which
196 // to load or store a result.
197 int decode(struct guest_thread *vm_thread, uint64_t *gpa, uint8_t *destreg,
198            uint64_t **regp, int *store, int *size, int *advance)
199 {
200         struct vm_trapframe *vm_tf = &(vm_thread->uthread.u_ctx.tf.vm_tf);
201         uint8_t *rip_gpa = NULL;
202
203         DPRINTF("v is %p\n", vm_tf);
204
205         // Duh, which way did he go George? Which way did he go?
206         // First hit on Google gets you there!
207         // This is the guest physical address of the access.
208         // This is nice, because if we ever go with more complete
209         // instruction decode, knowing this gpa reduces our work:
210         // we don't have to find the source address in registers,
211         // only the register holding or receiving the value.
212         *gpa = vm_tf->tf_guest_pa;
213         DPRINTF("gpa is %p\n", *gpa);
214
215         DPRINTF("rip is %p\n", vm_tf->tf_rip);
216
217         if (rippa(vm_thread, (uint64_t *)&rip_gpa))
218                 return VM_PAGE_FAULT;
219         DPRINTF("rip_gpa is %p\n", kva);
220
221         // fail fast. If we can't get the size we're done.
222         *size = target(rip_gpa, store);
223         DPRINTF("store is %d\n", *store);
224         if (*size < 0)
225                 return -1;
226
227         *advance = insize(rip_gpa);
228
229         uint16_t ins =
230             *(uint16_t *)(rip_gpa + (kva[0] == 0x44) + (kva[0] == 0x0f));
231         DPRINTF("ins is %04x\n", ins);
232
233         *destreg = (ins>>11) & 7;
234         *destreg += 8 * (rip_gpa[0] == 0x44);
235         // Our primitive approach wins big here.
236         // We don't have to decode the register or the offset used
237         // in the computation; that was done by the CPU and is the gpa.
238         // All we need to know is which destination or source register it is.
239         switch (*destreg) {
240         case 0:
241                 *regp = &vm_tf->tf_rax;
242                 break;
243         case 1:
244                 *regp = &vm_tf->tf_rcx;
245                 break;
246         case 2:
247                 *regp = &vm_tf->tf_rdx;
248                 break;
249         case 3:
250                 *regp = &vm_tf->tf_rbx;
251                 break;
252         case 4:
253                 *regp = &vm_tf->tf_rsp; // uh, right.
254                 break;
255         case 5:
256                 *regp = &vm_tf->tf_rbp;
257                 break;
258         case 6:
259                 *regp = &vm_tf->tf_rsi;
260                 break;
261         case 7:
262                 *regp = &vm_tf->tf_rdi;
263                 break;
264         case 8:
265                 *regp = &vm_tf->tf_r8;
266                 break;
267         case 9:
268                 *regp = &vm_tf->tf_r9;
269                 break;
270         case 10:
271                 *regp = &vm_tf->tf_r10;
272                 break;
273         case 11:
274                 *regp = &vm_tf->tf_r11;
275                 break;
276         case 12:
277                 *regp = &vm_tf->tf_r12;
278                 break;
279         case 13:
280                 *regp = &vm_tf->tf_r13;
281                 break;
282         case 14:
283                 *regp = &vm_tf->tf_r14;
284                 break;
285         case 15:
286                 *regp = &vm_tf->tf_r15;
287                 break;
288         }
289         return 0;
290 }