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.


d4288a2a606877d723f580ae31ee5c22bcd6b80b
[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 static inline v3_reg_t get_gpr_mask(struct guest_info * info) {
124   switch (info->cpu_mode) {
125   case REAL: 
126     return 0xffff;
127     break;
128   case PROTECTED:
129   case PROTECTED_PG:
130     return 0xffffffff;
131   default:
132     V3_ASSERT(0);
133     return 0;
134   }
135 }
136
137
138 static inline addr_t get_addr_linear(struct guest_info * info, addr_t addr, struct v3_segment * seg) {
139   switch (info->cpu_mode) {
140   case REAL:
141     return addr + (seg->selector << 4);
142     break;
143   case PROTECTED:
144   case PROTECTED_PG:
145     return addr + seg->base;
146     break;
147   default:
148     V3_ASSERT(0);
149     return 0;
150   }
151 }
152
153
154 typedef enum {INVALID_ADDR_TYPE, REG, DISP0, DISP8, DISP16, DISP32} modrm_mode_t;
155 typedef enum {INVALID_REG_SIZE, REG64, REG32, REG16, REG8} reg_size_t;
156 typedef enum {INVALID_OPERAND, REG_OPERAND, MEM_OPERAND} operand_type_t;
157
158 struct v3_gprs;
159
160 static inline addr_t decode_register(struct v3_gprs * gprs, char reg_code, reg_size_t reg_size) {
161   addr_t reg_addr;
162
163   switch (reg_code) {
164   case 0:
165     reg_addr = (addr_t)&(gprs->rax);
166     break;
167   case 1:
168     reg_addr = (addr_t)&(gprs->rcx);
169     break;
170   case 2:
171     reg_addr = (addr_t)&(gprs->rdx);
172     break;
173   case 3:
174     reg_addr = (addr_t)&(gprs->rbx);
175     break;
176   case 4:
177     if (reg_size == REG8) {
178       reg_addr = (addr_t)&(gprs->rax) + 1;
179     } else {
180       reg_addr = (addr_t)&(gprs->rsp);
181     }
182     break;
183   case 5:
184     if (reg_size == REG8) {
185       reg_addr = (addr_t)&(gprs->rcx) + 1;
186     } else {
187       reg_addr = (addr_t)&(gprs->rbp);
188     }
189     break;
190   case 6:
191     if (reg_size == REG8) {
192       reg_addr = (addr_t)&(gprs->rdx) + 1;
193     } else {
194       reg_addr = (addr_t)&(gprs->rsi);
195     }
196     break;
197   case 7:
198     if (reg_size == REG8) {
199       reg_addr = (addr_t)&(gprs->rbx) + 1;
200     } else {
201       reg_addr = (addr_t)&(gprs->rdi);
202     }
203     break;
204   default:
205     reg_addr = 0;
206     break;
207   }
208
209   return reg_addr;
210 }
211
212
213
214 static inline operand_type_t decode_operands16(struct v3_gprs * gprs, // input/output
215                                                char * modrm_instr,       // input
216                                                int * offset,             // output
217                                                addr_t * first_operand,   // output
218                                                addr_t * second_operand,  // output
219                                                reg_size_t reg_size) {    // input
220   
221   struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
222   addr_t base_addr = 0;
223   modrm_mode_t mod_mode = 0;
224   operand_type_t addr_type = INVALID_OPERAND;
225   char * instr_cursor = modrm_instr;
226
227   PrintDebug("ModRM mod=%d\n", modrm->mod);
228
229   instr_cursor += 1;
230
231   if (modrm->mod == 3) {
232     mod_mode = REG;
233     addr_type = REG_OPERAND;
234     PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
235
236     *first_operand = decode_register(gprs, modrm->rm, reg_size);
237
238   } else {
239
240     addr_type = MEM_OPERAND;
241
242     if (modrm->mod == 0) {
243       mod_mode = DISP0;
244     } else if (modrm->mod == 1) {
245       mod_mode = DISP8;
246     } else if (modrm->mod == 2) {
247       mod_mode = DISP16;
248     }
249
250     switch (modrm->rm) {
251     case 0:
252       base_addr = gprs->rbx + gprs->rsi;
253       break;
254     case 1:
255       base_addr = gprs->rbx + gprs->rdi;
256       break;
257     case 2:
258       base_addr = gprs->rbp + gprs->rsi;
259       break;
260     case 3:
261       base_addr = gprs->rbp + gprs->rdi;
262       break;
263     case 4:
264       base_addr = gprs->rsi;
265       break;
266     case 5:
267       base_addr = gprs->rdi;
268       break;
269     case 6:
270       if (modrm->mod == 0) {
271         base_addr = 0;
272         mod_mode = DISP16;
273       } else {
274         base_addr = gprs->rbp;
275       }
276       break;
277     case 7:
278       base_addr = gprs->rbx;
279       break;
280     }
281
282
283
284     if (mod_mode == DISP8) {
285       base_addr += (uchar_t)*(instr_cursor);
286       instr_cursor += 1;
287     } else if (mod_mode == DISP16) {
288       base_addr += (ushort_t)*(instr_cursor);
289       instr_cursor += 2;
290     }
291     
292     *first_operand = base_addr;
293   }
294
295   *offset +=  (instr_cursor - modrm_instr);
296   *second_operand = decode_register(gprs, modrm->reg, reg_size);
297
298   return addr_type;
299 }
300
301
302
303 static inline operand_type_t decode_operands32(struct v3_gprs * gprs, // input/output
304                                                char * modrm_instr,       // input
305                                                int * offset,             // output
306                                                addr_t * first_operand,   // output
307                                                addr_t * second_operand,  // output
308                                                reg_size_t reg_size) {    // input
309   
310   char * instr_cursor = modrm_instr;
311   struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
312   addr_t base_addr = 0;
313   modrm_mode_t mod_mode = 0;
314   uint_t has_sib_byte = 0;
315   operand_type_t addr_type = INVALID_OPERAND;
316
317
318
319   instr_cursor += 1;
320
321   if (modrm->mod == 3) {
322     mod_mode = REG;
323     addr_type = REG_OPERAND;
324     
325     PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
326
327     *first_operand = decode_register(gprs, modrm->rm, reg_size);
328
329   } else {
330
331     addr_type = MEM_OPERAND;
332
333     if (modrm->mod == 0) {
334       mod_mode = DISP0;
335     } else if (modrm->mod == 1) {
336       mod_mode = DISP8;
337     } else if (modrm->mod == 2) {
338       mod_mode = DISP32;
339     }
340     
341     switch (modrm->rm) {
342     case 0:
343       base_addr = gprs->rax;
344       break;
345     case 1:
346       base_addr = gprs->rcx;
347       break;
348     case 2:
349       base_addr = gprs->rdx;
350       break;
351     case 3:
352       base_addr = gprs->rbx;
353       break;
354     case 4:
355       has_sib_byte = 1;
356       break;
357     case 5:
358       if (modrm->mod == 0) {
359         base_addr = 0;
360         mod_mode = DISP32;
361       } else {
362         base_addr = gprs->rbp;
363       }
364       break;
365     case 6:
366       base_addr = gprs->rsi;
367       break;
368     case 7:
369       base_addr = gprs->rdi;
370       break;
371     }
372
373     if (has_sib_byte) {
374       instr_cursor += 1;
375       struct sib_byte * sib = (struct sib_byte *)(instr_cursor);
376       int scale = 1;
377
378       instr_cursor += 1;
379
380
381       if (sib->scale == 1) {
382         scale = 2;
383       } else if (sib->scale == 2) {
384         scale = 4;
385       } else if (sib->scale == 3) {
386         scale = 8;
387       }
388
389
390       switch (sib->index) {
391       case 0:
392         base_addr = gprs->rax;
393         break;
394       case 1:
395         base_addr = gprs->rcx;
396         break;
397       case 2:
398         base_addr = gprs->rdx;
399         break;
400       case 3:
401         base_addr = gprs->rbx;
402         break;
403       case 4:
404         base_addr = 0;
405         break;
406       case 5:
407         base_addr = gprs->rbp;
408         break;
409       case 6:
410         base_addr = gprs->rsi;
411         break;
412       case 7:
413         base_addr = gprs->rdi;
414         break;
415       }
416
417       base_addr *= scale;
418
419
420       switch (sib->base) {
421       case 0:
422         base_addr += gprs->rax;
423         break;
424       case 1:
425         base_addr += gprs->rcx;
426         break;
427       case 2:
428         base_addr += gprs->rdx;
429         break;
430       case 3:
431         base_addr += gprs->rbx;
432         break;
433       case 4:
434         base_addr += gprs->rsp;
435         break;
436       case 5:
437         if (modrm->mod != 0) {
438           base_addr += gprs->rbp;
439         }
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     } 
450
451
452     if (mod_mode == DISP8) {
453       base_addr += (uchar_t)*(instr_cursor);
454       instr_cursor += 1;
455     } else if (mod_mode == DISP32) {
456       base_addr += (uint_t)*(instr_cursor);
457       instr_cursor += 4;
458     }
459     
460
461     *first_operand = base_addr;
462   }
463
464   *offset += (instr_cursor - modrm_instr);
465
466   *second_operand = decode_register(gprs, modrm->reg, reg_size);
467
468   return addr_type;
469 }
470
471
472
473
474 #endif