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.


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