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.


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