Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


6a6c14428f86136f8edc25e1a31fc6bacc7d86d3
[palacios.git] / palacios / include / geekos / vmm_emulate.h
1 #ifndef __VMM_EMULATE_H
2 #define __VMM_EMULATE_H
3 #include <geekos/vm_guest.h>
4
5
6 /*
7  * This is where we do the hideous X86 instruction parsing among other things
8  * We can parse out the instruction prefixes, as well as decode the operands 
9  *
10  * Before we begin I'd just like to say a few words to those that made this possible...
11  *
12  *
13  *                                   _____
14  *                                  ||   ||
15  *                                  |\___/|
16  *                                  |     |
17  *                                  |     |
18  *                                  |     |
19  *                                  |     |
20  *                                  |     |
21  *                                  |     |
22  *                             _____|<--->|_____
23  *                         ___/     |     |      \
24  *                       /    |     |     |     | \
25  *                       |    |     |     |     |  |
26  *                       |    |     |     |     |  |
27  *                       |                      |  |
28  *                       |                      |  |
29  *                       |    Fuck You Intel!     /
30  *                       |                       /
31  *                        \                    /
32  *                         \                  /
33  *                          |                 |
34  *                          |                 |
35  *
36  * That is all.
37  *
38  */
39
40
41 /* JRL: Some of this was taken from the Xen sources... 
42  *
43  */
44
45 #define PACKED __attribute__((packed))
46
47 #define MODRM_MOD(x) ((x >> 6) & 0x3)
48 #define MODRM_REG(x) ((x >> 3) & 0x7)
49 #define MODRM_RM(x)  (x & 0x7)
50
51 struct modrm_byte {
52   uint_t rm   :   3 PACKED;
53   uint_t reg  :   3 PACKED;
54   uint_t mod  :   2 PACKED;
55 };
56
57
58 #define SIB_BASE(x) ((x >> 6) & 0x3)
59 #define SIB_INDEX(x) ((x >> 3) & 0x7)
60 #define SIB_SCALE(x) (x & 0x7)
61
62 struct sib_byte {
63   uint_t base     :   3 PACKED;
64   uint_t index    :   3 PACKED;
65   uint_t scale    :   2 PACKED;
66 };
67
68
69
70 #define MAKE_INSTR(nm, ...) static const uchar_t OPCODE_##nm[] = { __VA_ARGS__ }
71
72 /* 
73  * Here's how it works:
74  * First byte: Length. 
75  * Following bytes: Opcode bytes. 
76  * Special case: Last byte, if zero, doesn't need to match. 
77  */
78 MAKE_INSTR(INVD,   2, 0x0f, 0x08);
79 MAKE_INSTR(CPUID,  2, 0x0f, 0xa2);
80 MAKE_INSTR(RDMSR,  2, 0x0f, 0x32);
81 MAKE_INSTR(WRMSR,  2, 0x0f, 0x30);
82 MAKE_INSTR(RDTSC,  2, 0x0f, 0x31);
83 MAKE_INSTR(RDTSCP, 3, 0x0f, 0x01, 0xf9);
84 MAKE_INSTR(CLI,    1, 0xfa);
85 MAKE_INSTR(STI,    1, 0xfb);
86 MAKE_INSTR(RDPMC,  2, 0x0f, 0x33);
87 MAKE_INSTR(CLGI,   3, 0x0f, 0x01, 0xdd);
88 MAKE_INSTR(STGI,   3, 0x0f, 0x01, 0xdc);
89 MAKE_INSTR(VMRUN,  3, 0x0f, 0x01, 0xd8);
90 MAKE_INSTR(VMLOAD, 3, 0x0f, 0x01, 0xda);
91 MAKE_INSTR(VMSAVE, 3, 0x0f, 0x01, 0xdb);
92 MAKE_INSTR(VMCALL, 3, 0x0f, 0x01, 0xd9);
93 MAKE_INSTR(PAUSE,  2, 0xf3, 0x90);
94 MAKE_INSTR(SKINIT, 3, 0x0f, 0x01, 0xde);
95 MAKE_INSTR(MOV2CR, 3, 0x0f, 0x22, 0x00);
96 MAKE_INSTR(MOVCR2, 3, 0x0f, 0x20, 0x00);
97 MAKE_INSTR(MOV2DR, 3, 0x0f, 0x23, 0x00);
98 MAKE_INSTR(MOVDR2, 3, 0x0f, 0x21, 0x00);
99 MAKE_INSTR(PUSHF,  1, 0x9c);
100 MAKE_INSTR(POPF,   1, 0x9d);
101 MAKE_INSTR(RSM,    2, 0x0f, 0xaa);
102 MAKE_INSTR(INVLPG, 3, 0x0f, 0x01, 0x00);
103 MAKE_INSTR(INVLPGA,3, 0x0f, 0x01, 0xdf);
104 MAKE_INSTR(HLT,    1, 0xf4);
105 MAKE_INSTR(CLTS,   2, 0x0f, 0x06);
106 MAKE_INSTR(LMSW,   3, 0x0f, 0x01, 0x00);
107 MAKE_INSTR(SMSW,   3, 0x0f, 0x01, 0x00);
108
109
110
111 static inline int is_prefix_byte(char byte) {
112   switch (byte) {
113   case 0xF0:      // lock
114   case 0xF2:      // REPNE/REPNZ
115   case 0xF3:      // REP or REPE/REPZ
116   case 0x2E:      // CS override or Branch hint not taken (with Jcc instrs)
117   case 0x36:      // SS override
118   case 0x3E:      // DS override or Branch hint taken (with Jcc instrs)
119   case 0x26:      // ES override
120   case 0x64:      // FS override
121   case 0x65:      // GS override
122     //case 0x2E:      // branch not taken hint
123     //  case 0x3E:      // branch taken hint
124   case 0x66:      // operand size override
125   case 0x67:      // address size override
126     return 1;
127     break;
128   default:
129     return 0;
130     break;
131   }
132 }
133
134 typedef enum {INVALID_ADDR_TYPE, REG, DISP0, DISP8, DISP16, DISP32} modrm_mode_t;
135 typedef enum {INVALID_REG_SIZE, REG64, REG32, REG16, REG8} reg_size_t;
136 typedef enum {INVALID_OPERAND, REG_OPERAND, MEM_OPERAND} operand_type_t;
137
138 struct guest_gprs;
139
140 static inline addr_t decode_register(struct guest_gprs * gprs, char reg_code, reg_size_t reg_size) {
141   addr_t reg_addr;
142
143   switch (reg_code) {
144   case 0:
145     reg_addr = (addr_t)&(gprs->rax);
146     break;
147   case 1:
148     reg_addr = (addr_t)&(gprs->rcx);
149     break;
150   case 2:
151     reg_addr = (addr_t)&(gprs->rdx);
152     break;
153   case 3:
154     reg_addr = (addr_t)&(gprs->rbx);
155     break;
156   case 4:
157     if (reg_size == REG8) {
158       reg_addr = (addr_t)&(gprs->rax) + 1;
159     } else {
160       reg_addr = (addr_t)&(gprs->rsp);
161     }
162     break;
163   case 5:
164     if (reg_size == REG8) {
165       reg_addr = (addr_t)&(gprs->rcx) + 1;
166     } else {
167       reg_addr = (addr_t)&(gprs->rbp);
168     }
169     break;
170   case 6:
171     if (reg_size == REG8) {
172       reg_addr = (addr_t)&(gprs->rdx) + 1;
173     } else {
174       reg_addr = (addr_t)&(gprs->rsi);
175     }
176     break;
177   case 7:
178     if (reg_size == REG8) {
179       reg_addr = (addr_t)&(gprs->rbx) + 1;
180     } else {
181       reg_addr = (addr_t)&(gprs->rdi);
182     }
183     break;
184   default:
185     reg_addr = 0;
186     break;
187   }
188
189   return reg_addr;
190 }
191
192
193
194 static inline operand_type_t decode_operands16(struct guest_gprs * gprs, 
195                                                char * modrm_instr, 
196                                                addr_t * first_operand,
197                                                addr_t * second_operand, 
198                                                reg_size_t reg_size) {
199   
200   struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
201   addr_t base_addr = 0;
202   modrm_mode_t mod_mode = 0;
203   operand_type_t addr_type = INVALID_OPERAND;
204
205   PrintDebug("ModRM mod=%d\n", modrm->mod);
206
207   if (modrm->mod == 3) {
208     mod_mode = REG;
209     addr_type = REG_OPERAND;
210     PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
211
212     *first_operand = decode_register(gprs, modrm->rm, reg_size);
213
214   } else {
215
216     addr_type = MEM_OPERAND;
217
218     if (modrm->mod == 0) {
219       mod_mode = DISP0;
220     } else if (modrm->mod == 1) {
221       mod_mode = DISP8;
222     } else if (modrm->mod == 2) {
223       mod_mode = DISP16;
224     }
225
226     switch (modrm->rm) {
227     case 0:
228       base_addr = gprs->rbx + gprs->rsi;
229       break;
230     case 1:
231       base_addr = gprs->rbx + gprs->rdi;
232       break;
233     case 2:
234       base_addr = gprs->rbp + gprs->rsi;
235       break;
236     case 3:
237       base_addr = gprs->rbp + gprs->rdi;
238       break;
239     case 4:
240       base_addr = gprs->rsi;
241       break;
242     case 5:
243       base_addr = gprs->rdi;
244       break;
245     case 6:
246       if (modrm->mod == 0) {
247         base_addr = 0;
248         mod_mode = DISP16;
249       } else {
250         base_addr = gprs->rbp;
251       }
252       break;
253     case 7:
254       base_addr = gprs->rbx;
255       break;
256     }
257
258     if (mod_mode == DISP8) {
259       base_addr += (uchar_t)*(modrm_instr + 1);
260     } else if (mod_mode == DISP16) {
261       base_addr += (ushort_t)*(modrm_instr + 1);
262     }
263     
264     *first_operand = base_addr;
265   }
266
267   *second_operand = decode_register(gprs, modrm->reg, reg_size);
268
269   return addr_type;
270 }
271
272
273
274 static inline operand_type_t decode_operands32(struct guest_gprs * gprs, 
275                                     char * modrm_instr,
276                                     addr_t * first_operand,
277                                     addr_t * second_operand, 
278                                     reg_size_t reg_size) {
279
280   char * instr_cursor = modrm_instr;
281   struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
282   addr_t base_addr = 0;
283   modrm_mode_t mod_mode = 0;
284   uint_t has_sib_byte = 0;
285   operand_type_t addr_type = INVALID_OPERAND;
286
287   if (modrm->mod == 3) {
288     mod_mode = REG;
289     addr_type = REG_OPERAND;
290     
291     PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
292
293     *first_operand = decode_register(gprs, modrm->rm, reg_size);
294
295   } else {
296
297     addr_type = MEM_OPERAND;
298
299     if (modrm->mod == 0) {
300       mod_mode = DISP0;
301     } else if (modrm->mod == 1) {
302       mod_mode = DISP8;
303     } else if (modrm->mod == 2) {
304       mod_mode = DISP32;
305     }
306     
307     switch (modrm->rm) {
308     case 0:
309       base_addr = gprs->rax;
310       break;
311     case 1:
312       base_addr = gprs->rcx;
313       break;
314     case 2:
315       base_addr = gprs->rdx;
316       break;
317     case 3:
318       base_addr = gprs->rbx;
319       break;
320     case 4:
321       has_sib_byte = 1;
322       break;
323     case 5:
324       if (modrm->mod == 0) {
325         base_addr = 0;
326         mod_mode = DISP32;
327       } else {
328         base_addr = gprs->rbp;
329       }
330       break;
331     case 6:
332       base_addr = gprs->rsi;
333       break;
334     case 7:
335       base_addr = gprs->rdi;
336       break;
337     }
338
339     if (has_sib_byte) {
340       instr_cursor += 1;
341       struct sib_byte * sib = (struct sib_byte *)(instr_cursor);
342       int scale = 1;
343
344
345       if (sib->scale == 1) {
346         scale = 2;
347       } else if (sib->scale == 2) {
348         scale = 4;
349       } else if (sib->scale == 3) {
350         scale = 8;
351       }
352
353
354       switch (sib->index) {
355       case 0:
356         base_addr = gprs->rax;
357         break;
358       case 1:
359         base_addr = gprs->rcx;
360         break;
361       case 2:
362         base_addr = gprs->rdx;
363         break;
364       case 3:
365         base_addr = gprs->rbx;
366         break;
367       case 4:
368         base_addr = 0;
369         break;
370       case 5:
371         base_addr = gprs->rbp;
372         break;
373       case 6:
374         base_addr = gprs->rsi;
375         break;
376       case 7:
377         base_addr = gprs->rdi;
378         break;
379       }
380
381       base_addr *= scale;
382
383
384       switch (sib->base) {
385       case 0:
386         base_addr += gprs->rax;
387         break;
388       case 1:
389         base_addr += gprs->rcx;
390         break;
391       case 2:
392         base_addr += gprs->rdx;
393         break;
394       case 3:
395         base_addr += gprs->rbx;
396         break;
397       case 4:
398         base_addr += gprs->rsp;
399         break;
400       case 5:
401         if (modrm->mod != 0) {
402           base_addr += gprs->rbp;
403         }
404         break;
405       case 6:
406         base_addr += gprs->rsi;
407         break;
408       case 7:
409         base_addr += gprs->rdi;
410         break;
411       }
412
413     } 
414
415     instr_cursor += 1;
416
417     if (mod_mode == DISP8) {
418       base_addr += (uchar_t)*(instr_cursor);
419     } else if (mod_mode == DISP32) {
420       base_addr += (uint_t)*(instr_cursor);
421     }
422     
423
424     *first_operand = base_addr;
425   }
426
427   *second_operand = decode_register(gprs, modrm->reg, reg_size);
428
429   return addr_type;
430 }
431
432
433
434
435 #endif