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.


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