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.


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