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.


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