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.


added full io support
[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 static const uchar_t PREFIX_LOCK = 0xF0;
111 static const uchar_t PREFIX_REPNE = 0xF2;
112 static const uchar_t PREFIX_REPNZ = 0xF2;
113 static const uchar_t PREFIX_REP = 0xF3;
114 static const uchar_t PREFIX_REPE = 0xF3;
115 static const uchar_t PREFIX_REPZ = 0xF3;
116 static const uchar_t PREFIX_CS_OVERRIDE = 0x2E;
117 static const uchar_t PREFIX_SS_OVERRIDE = 0x36;
118 static const uchar_t PREFIX_DS_OVERRIDE = 0x3E;
119 static const uchar_t PREFIX_ES_OVERRIDE = 0x26;
120 static const uchar_t PREFIX_FS_OVERRIDE = 0x64;
121 static const uchar_t PREFIX_GS_OVERRIDE = 0x65;
122 static const uchar_t PREFIX_BR_NOT_TAKEN = 0x2E;
123 static const uchar_t PREFIX_BR_TAKEN = 0x3E;
124 static const uchar_t PREFIX_OP_SIZE = 0x66;
125 static const uchar_t PREFIX_ADDR_SIZE = 0x67;
126
127
128 static inline int is_prefix_byte(char byte) {
129   switch (byte) {
130   case 0xF0:      // lock
131   case 0xF2:      // REPNE/REPNZ
132   case 0xF3:      // REP or REPE/REPZ
133   case 0x2E:      // CS override or Branch hint not taken (with Jcc instrs)
134   case 0x36:      // SS override
135   case 0x3E:      // DS override or Branch hint taken (with Jcc instrs)
136   case 0x26:      // ES override
137   case 0x64:      // FS override
138   case 0x65:      // GS override
139     //case 0x2E:      // branch not taken hint
140     //  case 0x3E:      // branch taken hint
141   case 0x66:      // operand size override
142   case 0x67:      // address size override
143     return 1;
144     break;
145   default:
146     return 0;
147     break;
148   }
149 }
150
151
152
153 static inline addr_t get_rip_linear(struct guest_info * info, addr_t rip, addr_t cs_base) {
154   switch (info->cpu_mode) {
155   case REAL:
156     return rip + (cs_base << 4);
157     break;
158   case PROTECTED:
159   case PROTECTED_PG:
160     return rip + cs_base;
161     break;
162   default:
163     return 0;
164   }
165 }
166
167
168 typedef enum {INVALID_ADDR_TYPE, REG, DISP0, DISP8, DISP16, DISP32} modrm_mode_t;
169 typedef enum {INVALID_REG_SIZE, REG64, REG32, REG16, REG8} reg_size_t;
170 typedef enum {INVALID_OPERAND, REG_OPERAND, MEM_OPERAND} operand_type_t;
171
172 struct guest_gprs;
173
174 static inline addr_t decode_register(struct guest_gprs * gprs, char reg_code, reg_size_t reg_size) {
175   addr_t reg_addr;
176
177   switch (reg_code) {
178   case 0:
179     reg_addr = (addr_t)&(gprs->rax);
180     break;
181   case 1:
182     reg_addr = (addr_t)&(gprs->rcx);
183     break;
184   case 2:
185     reg_addr = (addr_t)&(gprs->rdx);
186     break;
187   case 3:
188     reg_addr = (addr_t)&(gprs->rbx);
189     break;
190   case 4:
191     if (reg_size == REG8) {
192       reg_addr = (addr_t)&(gprs->rax) + 1;
193     } else {
194       reg_addr = (addr_t)&(gprs->rsp);
195     }
196     break;
197   case 5:
198     if (reg_size == REG8) {
199       reg_addr = (addr_t)&(gprs->rcx) + 1;
200     } else {
201       reg_addr = (addr_t)&(gprs->rbp);
202     }
203     break;
204   case 6:
205     if (reg_size == REG8) {
206       reg_addr = (addr_t)&(gprs->rdx) + 1;
207     } else {
208       reg_addr = (addr_t)&(gprs->rsi);
209     }
210     break;
211   case 7:
212     if (reg_size == REG8) {
213       reg_addr = (addr_t)&(gprs->rbx) + 1;
214     } else {
215       reg_addr = (addr_t)&(gprs->rdi);
216     }
217     break;
218   default:
219     reg_addr = 0;
220     break;
221   }
222
223   return reg_addr;
224 }
225
226
227
228 static inline operand_type_t decode_operands16(struct guest_gprs * gprs, // input/output
229                                                char * modrm_instr,       // input
230                                                int * offset,             // output
231                                                addr_t * first_operand,   // output
232                                                addr_t * second_operand,  // output
233                                                reg_size_t reg_size) {    // input
234   
235   struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
236   addr_t base_addr = 0;
237   modrm_mode_t mod_mode = 0;
238   operand_type_t addr_type = INVALID_OPERAND;
239   char * instr_cursor = modrm_instr;
240
241   PrintDebug("ModRM mod=%d\n", modrm->mod);
242
243   instr_cursor += 1;
244
245   if (modrm->mod == 3) {
246     mod_mode = REG;
247     addr_type = REG_OPERAND;
248     PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
249
250     *first_operand = decode_register(gprs, modrm->rm, reg_size);
251
252   } else {
253
254     addr_type = MEM_OPERAND;
255
256     if (modrm->mod == 0) {
257       mod_mode = DISP0;
258     } else if (modrm->mod == 1) {
259       mod_mode = DISP8;
260     } else if (modrm->mod == 2) {
261       mod_mode = DISP16;
262     }
263
264     switch (modrm->rm) {
265     case 0:
266       base_addr = gprs->rbx + gprs->rsi;
267       break;
268     case 1:
269       base_addr = gprs->rbx + gprs->rdi;
270       break;
271     case 2:
272       base_addr = gprs->rbp + gprs->rsi;
273       break;
274     case 3:
275       base_addr = gprs->rbp + gprs->rdi;
276       break;
277     case 4:
278       base_addr = gprs->rsi;
279       break;
280     case 5:
281       base_addr = gprs->rdi;
282       break;
283     case 6:
284       if (modrm->mod == 0) {
285         base_addr = 0;
286         mod_mode = DISP16;
287       } else {
288         base_addr = gprs->rbp;
289       }
290       break;
291     case 7:
292       base_addr = gprs->rbx;
293       break;
294     }
295
296
297
298     if (mod_mode == DISP8) {
299       base_addr += (uchar_t)*(instr_cursor);
300       instr_cursor += 1;
301     } else if (mod_mode == DISP16) {
302       base_addr += (ushort_t)*(instr_cursor);
303       instr_cursor += 2;
304     }
305     
306     *first_operand = base_addr;
307   }
308
309   *offset +=  (instr_cursor - modrm_instr);
310   *second_operand = decode_register(gprs, modrm->reg, reg_size);
311
312   return addr_type;
313 }
314
315
316
317 static inline operand_type_t decode_operands32(struct guest_gprs * gprs, // input/output
318                                                char * modrm_instr,       // input
319                                                int * offset,             // output
320                                                addr_t * first_operand,   // output
321                                                addr_t * second_operand,  // output
322                                                reg_size_t reg_size) {    // input
323   
324   char * instr_cursor = modrm_instr;
325   struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
326   addr_t base_addr = 0;
327   modrm_mode_t mod_mode = 0;
328   uint_t has_sib_byte = 0;
329   operand_type_t addr_type = INVALID_OPERAND;
330
331
332
333   instr_cursor += 1;
334
335   if (modrm->mod == 3) {
336     mod_mode = REG;
337     addr_type = REG_OPERAND;
338     
339     PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
340
341     *first_operand = decode_register(gprs, modrm->rm, reg_size);
342
343   } else {
344
345     addr_type = MEM_OPERAND;
346
347     if (modrm->mod == 0) {
348       mod_mode = DISP0;
349     } else if (modrm->mod == 1) {
350       mod_mode = DISP8;
351     } else if (modrm->mod == 2) {
352       mod_mode = DISP32;
353     }
354     
355     switch (modrm->rm) {
356     case 0:
357       base_addr = gprs->rax;
358       break;
359     case 1:
360       base_addr = gprs->rcx;
361       break;
362     case 2:
363       base_addr = gprs->rdx;
364       break;
365     case 3:
366       base_addr = gprs->rbx;
367       break;
368     case 4:
369       has_sib_byte = 1;
370       break;
371     case 5:
372       if (modrm->mod == 0) {
373         base_addr = 0;
374         mod_mode = DISP32;
375       } else {
376         base_addr = gprs->rbp;
377       }
378       break;
379     case 6:
380       base_addr = gprs->rsi;
381       break;
382     case 7:
383       base_addr = gprs->rdi;
384       break;
385     }
386
387     if (has_sib_byte) {
388       instr_cursor += 1;
389       struct sib_byte * sib = (struct sib_byte *)(instr_cursor);
390       int scale = 1;
391
392       instr_cursor += 1;
393
394
395       if (sib->scale == 1) {
396         scale = 2;
397       } else if (sib->scale == 2) {
398         scale = 4;
399       } else if (sib->scale == 3) {
400         scale = 8;
401       }
402
403
404       switch (sib->index) {
405       case 0:
406         base_addr = gprs->rax;
407         break;
408       case 1:
409         base_addr = gprs->rcx;
410         break;
411       case 2:
412         base_addr = gprs->rdx;
413         break;
414       case 3:
415         base_addr = gprs->rbx;
416         break;
417       case 4:
418         base_addr = 0;
419         break;
420       case 5:
421         base_addr = gprs->rbp;
422         break;
423       case 6:
424         base_addr = gprs->rsi;
425         break;
426       case 7:
427         base_addr = gprs->rdi;
428         break;
429       }
430
431       base_addr *= scale;
432
433
434       switch (sib->base) {
435       case 0:
436         base_addr += gprs->rax;
437         break;
438       case 1:
439         base_addr += gprs->rcx;
440         break;
441       case 2:
442         base_addr += gprs->rdx;
443         break;
444       case 3:
445         base_addr += gprs->rbx;
446         break;
447       case 4:
448         base_addr += gprs->rsp;
449         break;
450       case 5:
451         if (modrm->mod != 0) {
452           base_addr += gprs->rbp;
453         }
454         break;
455       case 6:
456         base_addr += gprs->rsi;
457         break;
458       case 7:
459         base_addr += gprs->rdi;
460         break;
461       }
462
463     } 
464
465
466     if (mod_mode == DISP8) {
467       base_addr += (uchar_t)*(instr_cursor);
468       instr_cursor += 1;
469     } else if (mod_mode == DISP32) {
470       base_addr += (uint_t)*(instr_cursor);
471       instr_cursor += 4;
472     }
473     
474
475     *first_operand = base_addr;
476   }
477
478   *offset += (instr_cursor - modrm_instr);
479
480   *second_operand = decode_register(gprs, modrm->reg, reg_size);
481
482   return addr_type;
483 }
484
485
486
487
488 #endif