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.


update
[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 typedef enum {INVALID_ADDR_TYPE, REG, DISP0, DISP8, DISP16, DISP32} modrm_mode_t;
154 typedef enum {INVALID_REG_SIZE, REG64, REG32, REG16, REG8} reg_size_t;
155 typedef enum {INVALID_OPERAND, REG_OPERAND, MEM_OPERAND} operand_type_t;
156
157 struct guest_gprs;
158
159 static inline addr_t decode_register(struct guest_gprs * gprs, char reg_code, reg_size_t reg_size) {
160   addr_t reg_addr;
161
162   switch (reg_code) {
163   case 0:
164     reg_addr = (addr_t)&(gprs->rax);
165     break;
166   case 1:
167     reg_addr = (addr_t)&(gprs->rcx);
168     break;
169   case 2:
170     reg_addr = (addr_t)&(gprs->rdx);
171     break;
172   case 3:
173     reg_addr = (addr_t)&(gprs->rbx);
174     break;
175   case 4:
176     if (reg_size == REG8) {
177       reg_addr = (addr_t)&(gprs->rax) + 1;
178     } else {
179       reg_addr = (addr_t)&(gprs->rsp);
180     }
181     break;
182   case 5:
183     if (reg_size == REG8) {
184       reg_addr = (addr_t)&(gprs->rcx) + 1;
185     } else {
186       reg_addr = (addr_t)&(gprs->rbp);
187     }
188     break;
189   case 6:
190     if (reg_size == REG8) {
191       reg_addr = (addr_t)&(gprs->rdx) + 1;
192     } else {
193       reg_addr = (addr_t)&(gprs->rsi);
194     }
195     break;
196   case 7:
197     if (reg_size == REG8) {
198       reg_addr = (addr_t)&(gprs->rbx) + 1;
199     } else {
200       reg_addr = (addr_t)&(gprs->rdi);
201     }
202     break;
203   default:
204     reg_addr = 0;
205     break;
206   }
207
208   return reg_addr;
209 }
210
211
212
213 static inline operand_type_t decode_operands16(struct guest_gprs * gprs, // input/output
214                                                char * modrm_instr,       // input
215                                                int * offset,             // output
216                                                addr_t * first_operand,   // output
217                                                addr_t * second_operand,  // output
218                                                reg_size_t reg_size) {    // input
219   
220   struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
221   addr_t base_addr = 0;
222   modrm_mode_t mod_mode = 0;
223   operand_type_t addr_type = INVALID_OPERAND;
224   char * instr_cursor = modrm_instr;
225
226   PrintDebug("ModRM mod=%d\n", modrm->mod);
227
228   instr_cursor += 1;
229
230   if (modrm->mod == 3) {
231     mod_mode = REG;
232     addr_type = REG_OPERAND;
233     PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
234
235     *first_operand = decode_register(gprs, modrm->rm, reg_size);
236
237   } else {
238
239     addr_type = MEM_OPERAND;
240
241     if (modrm->mod == 0) {
242       mod_mode = DISP0;
243     } else if (modrm->mod == 1) {
244       mod_mode = DISP8;
245     } else if (modrm->mod == 2) {
246       mod_mode = DISP16;
247     }
248
249     switch (modrm->rm) {
250     case 0:
251       base_addr = gprs->rbx + gprs->rsi;
252       break;
253     case 1:
254       base_addr = gprs->rbx + gprs->rdi;
255       break;
256     case 2:
257       base_addr = gprs->rbp + gprs->rsi;
258       break;
259     case 3:
260       base_addr = gprs->rbp + gprs->rdi;
261       break;
262     case 4:
263       base_addr = gprs->rsi;
264       break;
265     case 5:
266       base_addr = gprs->rdi;
267       break;
268     case 6:
269       if (modrm->mod == 0) {
270         base_addr = 0;
271         mod_mode = DISP16;
272       } else {
273         base_addr = gprs->rbp;
274       }
275       break;
276     case 7:
277       base_addr = gprs->rbx;
278       break;
279     }
280
281
282
283     if (mod_mode == DISP8) {
284       base_addr += (uchar_t)*(instr_cursor);
285       instr_cursor += 1;
286     } else if (mod_mode == DISP16) {
287       base_addr += (ushort_t)*(instr_cursor);
288       instr_cursor += 2;
289     }
290     
291     *first_operand = base_addr;
292   }
293
294   *offset +=  (instr_cursor - modrm_instr);
295   *second_operand = decode_register(gprs, modrm->reg, reg_size);
296
297   return addr_type;
298 }
299
300
301
302 static inline operand_type_t decode_operands32(struct guest_gprs * gprs, // input/output
303                                                char * modrm_instr,       // input
304                                                int * offset,             // output
305                                                addr_t * first_operand,   // output
306                                                addr_t * second_operand,  // output
307                                                reg_size_t reg_size) {    // input
308   
309   char * instr_cursor = modrm_instr;
310   struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
311   addr_t base_addr = 0;
312   modrm_mode_t mod_mode = 0;
313   uint_t has_sib_byte = 0;
314   operand_type_t addr_type = INVALID_OPERAND;
315
316
317
318   instr_cursor += 1;
319
320   if (modrm->mod == 3) {
321     mod_mode = REG;
322     addr_type = REG_OPERAND;
323     
324     PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
325
326     *first_operand = decode_register(gprs, modrm->rm, reg_size);
327
328   } else {
329
330     addr_type = MEM_OPERAND;
331
332     if (modrm->mod == 0) {
333       mod_mode = DISP0;
334     } else if (modrm->mod == 1) {
335       mod_mode = DISP8;
336     } else if (modrm->mod == 2) {
337       mod_mode = DISP32;
338     }
339     
340     switch (modrm->rm) {
341     case 0:
342       base_addr = gprs->rax;
343       break;
344     case 1:
345       base_addr = gprs->rcx;
346       break;
347     case 2:
348       base_addr = gprs->rdx;
349       break;
350     case 3:
351       base_addr = gprs->rbx;
352       break;
353     case 4:
354       has_sib_byte = 1;
355       break;
356     case 5:
357       if (modrm->mod == 0) {
358         base_addr = 0;
359         mod_mode = DISP32;
360       } else {
361         base_addr = gprs->rbp;
362       }
363       break;
364     case 6:
365       base_addr = gprs->rsi;
366       break;
367     case 7:
368       base_addr = gprs->rdi;
369       break;
370     }
371
372     if (has_sib_byte) {
373       instr_cursor += 1;
374       struct sib_byte * sib = (struct sib_byte *)(instr_cursor);
375       int scale = 1;
376
377       instr_cursor += 1;
378
379
380       if (sib->scale == 1) {
381         scale = 2;
382       } else if (sib->scale == 2) {
383         scale = 4;
384       } else if (sib->scale == 3) {
385         scale = 8;
386       }
387
388
389       switch (sib->index) {
390       case 0:
391         base_addr = gprs->rax;
392         break;
393       case 1:
394         base_addr = gprs->rcx;
395         break;
396       case 2:
397         base_addr = gprs->rdx;
398         break;
399       case 3:
400         base_addr = gprs->rbx;
401         break;
402       case 4:
403         base_addr = 0;
404         break;
405       case 5:
406         base_addr = gprs->rbp;
407         break;
408       case 6:
409         base_addr = gprs->rsi;
410         break;
411       case 7:
412         base_addr = gprs->rdi;
413         break;
414       }
415
416       base_addr *= scale;
417
418
419       switch (sib->base) {
420       case 0:
421         base_addr += gprs->rax;
422         break;
423       case 1:
424         base_addr += gprs->rcx;
425         break;
426       case 2:
427         base_addr += gprs->rdx;
428         break;
429       case 3:
430         base_addr += gprs->rbx;
431         break;
432       case 4:
433         base_addr += gprs->rsp;
434         break;
435       case 5:
436         if (modrm->mod != 0) {
437           base_addr += gprs->rbp;
438         }
439         break;
440       case 6:
441         base_addr += gprs->rsi;
442         break;
443       case 7:
444         base_addr += gprs->rdi;
445         break;
446       }
447
448     } 
449
450
451     if (mod_mode == DISP8) {
452       base_addr += (uchar_t)*(instr_cursor);
453       instr_cursor += 1;
454     } else if (mod_mode == DISP32) {
455       base_addr += (uint_t)*(instr_cursor);
456       instr_cursor += 4;
457     }
458     
459
460     *first_operand = base_addr;
461   }
462
463   *offset += (instr_cursor - modrm_instr);
464
465   *second_operand = decode_register(gprs, modrm->reg, reg_size);
466
467   return addr_type;
468 }
469
470
471
472
473 #endif