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.


added stos instruction to the emulator
[palacios.git] / palacios / include / palacios / vmm_decoder.h
1 /*
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #ifndef __VMM_DECODER_H
21 #define __VMM_DECODER_H
22
23 #ifdef __V3VEE__
24
25 #include <palacios/vm_guest.h>
26 #include <palacios/vmm.h>
27
28
29 typedef enum { V3_INVALID_OP,
30                V3_OP_MOVCR2, V3_OP_MOV2CR, V3_OP_SMSW, V3_OP_LMSW, V3_OP_CLTS,
31                V3_OP_INVLPG,
32                V3_OP_ADC, V3_OP_ADD, V3_OP_AND, V3_OP_OR, V3_OP_XOR, V3_OP_SUB,
33                V3_OP_INC, V3_OP_DEC, V3_OP_NEG, V3_OP_MOV, V3_OP_NOT, V3_OP_XCHG, 
34                V3_OP_SETB, V3_OP_SETBE, V3_OP_SETL, V3_OP_SETLE, V3_OP_SETNB, 
35                V3_OP_SETNBE, V3_OP_SETNL, V3_OP_SETNLE, V3_OP_SETNO, V3_OP_SETNP,
36                V3_OP_SETNS, V3_OP_SETNZ, V3_OP_SETO, V3_OP_SETP, V3_OP_SETS, 
37                V3_OP_SETZ, V3_OP_MOVS, V3_OP_STOS, V3_OP_MOVZX, V3_OP_MOVSX} v3_op_type_t;
38
39
40 typedef enum {INVALID_OPERAND, REG_OPERAND, MEM_OPERAND, IMM_OPERAND} v3_operand_type_t;
41
42 struct x86_operand {
43   addr_t operand;
44   uint_t size;
45   v3_operand_type_t type;
46 };
47
48 struct x86_prefixes {
49   uint_t lock   : 1;  // 0xF0
50   uint_t repne  : 1;  // 0xF2
51   uint_t repnz  : 1;  // 0xF2
52   uint_t rep    : 1;  // 0xF3
53   uint_t repe   : 1;  // 0xF3
54   uint_t repz   : 1;  // 0xF3
55   uint_t cs_override : 1;  // 0x2E
56   uint_t ss_override : 1;  // 0x36
57   uint_t ds_override : 1;  // 0x3E
58   uint_t es_override : 1;  // 0x26
59   uint_t fs_override : 1;  // 0x64
60   uint_t gs_override : 1;  // 0x65
61   uint_t br_not_taken : 1;  // 0x2E
62   uint_t br_taken   : 1;  // 0x3E
63   uint_t op_size     : 1;  // 0x66
64   uint_t addr_size   : 1;  // 0x67
65 };
66
67
68 struct x86_instr {
69   struct x86_prefixes prefixes;
70   uint_t instr_length;
71   v3_op_type_t op_type;
72   uint_t num_operands;
73   struct x86_operand dst_operand;
74   struct x86_operand src_operand;
75   struct x86_operand third_operand;
76   addr_t str_op_length;
77   addr_t is_str_op;
78   void * decoder_data;
79 };
80
81
82 struct basic_instr_info {
83   uint_t instr_length;
84   uint_t op_size;
85   uint_t str_op    : 1;
86   uint_t has_rep : 1;
87 };
88
89
90
91   /************************/
92  /* EXTERNAL DECODER API */
93 /************************/
94 /* 
95    This is an External API definition that must be implemented by a decoder
96 */
97
98
99 /* 
100  * Initializes a decoder
101  */
102 int v3_init_decoder();
103
104 /* 
105  * Decodes an instruction 
106  * All addresses in arguments are in the host address space
107  * instr_ptr is the host address of the instruction 
108  * IMPORTANT: make sure the instr_ptr is in contiguous host memory
109  *   ie. Copy it to a buffer before the call
110  */
111 int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * instr);
112
113 /* 
114  * Encodes an instruction
115  * All addresses in arguments are in the host address space
116  * The instruction is encoded from the struct, and copied into a 15 byte host buffer
117  * referenced by instr_buf
118  * any unused bytes at the end of instr_buf will be filled with nops
119  * IMPORTANT: instr_buf must be allocated and 15 bytes long
120  */
121 int v3_encode(struct guest_info * info, struct x86_instr * instr, char * instr_buf);
122
123
124 /*
125  * Gets the operand size for a memory operation
126  *
127  */
128 int v3_basic_mem_decode(struct guest_info * info, addr_t instr_ptr, struct basic_instr_info * instr_info);
129
130
131
132 /* Removes a rep prefix in place */
133 void v3_strip_rep_prefix(uchar_t * instr, int length);
134 void v3_get_prefixes(uchar_t * instr, struct x86_prefixes * prefixes);
135
136
137 /* 
138  * JRL: Some of this was taken from the Xen sources... 
139  */
140
141 #define PACKED __attribute__((packed))
142
143 #define MODRM_MOD(x) ((x >> 6) & 0x3)
144 #define MODRM_REG(x) ((x >> 3) & 0x7)
145 #define MODRM_RM(x)  (x & 0x7)
146
147 struct modrm_byte {
148   uint_t rm   :   3 PACKED;
149   uint_t reg  :   3 PACKED;
150   uint_t mod  :   2 PACKED;
151 };
152
153
154 #define SIB_BASE(x) ((x >> 6) & 0x3)
155 #define SIB_INDEX(x) ((x >> 3) & 0x7)
156 #define SIB_SCALE(x) (x & 0x7)
157
158 struct sib_byte {
159   uint_t base     :   3 PACKED;
160   uint_t index    :   3 PACKED;
161   uint_t scale    :   2 PACKED;
162 };
163
164
165
166 #define MAKE_INSTR(nm, ...) static  const uchar_t V3_OPCODE_##nm[] = { __VA_ARGS__ }
167
168 /* 
169  * Here's how it works:
170  * First byte: Length. 
171  * Following bytes: Opcode bytes. 
172  * Special case: Last byte, if zero, doesn't need to match. 
173  */
174 MAKE_INSTR(INVD,   2, 0x0f, 0x08);
175 MAKE_INSTR(CPUID,  2, 0x0f, 0xa2);
176 MAKE_INSTR(RDMSR,  2, 0x0f, 0x32);
177 MAKE_INSTR(WRMSR,  2, 0x0f, 0x30);
178 MAKE_INSTR(RDTSC,  2, 0x0f, 0x31);
179 MAKE_INSTR(RDTSCP, 3, 0x0f, 0x01, 0xf9);
180 MAKE_INSTR(CLI,    1, 0xfa);
181 MAKE_INSTR(STI,    1, 0xfb);
182 MAKE_INSTR(RDPMC,  2, 0x0f, 0x33);
183 MAKE_INSTR(CLGI,   3, 0x0f, 0x01, 0xdd);
184 MAKE_INSTR(STGI,   3, 0x0f, 0x01, 0xdc);
185 MAKE_INSTR(VMRUN,  3, 0x0f, 0x01, 0xd8);
186 MAKE_INSTR(VMLOAD, 3, 0x0f, 0x01, 0xda);
187 MAKE_INSTR(VMSAVE, 3, 0x0f, 0x01, 0xdb);
188 MAKE_INSTR(VMCALL, 3, 0x0f, 0x01, 0xd9);
189 MAKE_INSTR(PAUSE,  2, 0xf3, 0x90);
190 MAKE_INSTR(SKINIT, 3, 0x0f, 0x01, 0xde);
191 MAKE_INSTR(MOV2CR, 3, 0x0f, 0x22, 0x00);
192 MAKE_INSTR(MOVCR2, 3, 0x0f, 0x20, 0x00);
193 MAKE_INSTR(MOV2DR, 3, 0x0f, 0x23, 0x00);
194 MAKE_INSTR(MOVDR2, 3, 0x0f, 0x21, 0x00);
195 MAKE_INSTR(PUSHF,  1, 0x9c);
196 MAKE_INSTR(POPF,   1, 0x9d);
197 MAKE_INSTR(RSM,    2, 0x0f, 0xaa);
198 MAKE_INSTR(INVLPG, 3, 0x0f, 0x01, 0x00);
199 MAKE_INSTR(INVLPGA,3, 0x0f, 0x01, 0xdf);
200 MAKE_INSTR(HLT,    1, 0xf4);
201 MAKE_INSTR(CLTS,   2, 0x0f, 0x06);
202 MAKE_INSTR(LMSW,   3, 0x0f, 0x01, 0x00);
203 MAKE_INSTR(SMSW,   3, 0x0f, 0x01, 0x00);
204
205
206 #define PREFIX_LOCK         0xF0
207 #define PREFIX_REPNE        0xF2
208 #define PREFIX_REPNZ        0xF2
209 #define PREFIX_REP          0xF3
210 #define PREFIX_REPE         0xF3
211 #define PREFIX_REPZ         0xF3
212 #define PREFIX_CS_OVERRIDE  0x2E
213 #define PREFIX_SS_OVERRIDE  0x36
214 #define PREFIX_DS_OVERRIDE  0x3E
215 #define PREFIX_ES_OVERRIDE  0x26
216 #define PREFIX_FS_OVERRIDE  0x64
217 #define PREFIX_GS_OVERRIDE  0x65
218 #define PREFIX_BR_NOT_TAKEN 0x2E
219 #define PREFIX_BR_TAKEN     0x3E
220 #define PREFIX_OP_SIZE      0x66
221 #define PREFIX_ADDR_SIZE    0x67
222
223 int v3_opcode_cmp(const uchar_t * op1, const uchar_t * op2);
224
225
226 static inline int is_prefix_byte(uchar_t byte) {
227   switch (byte) {
228   case 0xF0:      // lock
229   case 0xF2:      // REPNE/REPNZ
230   case 0xF3:      // REP or REPE/REPZ
231   case 0x2E:      // CS override or Branch hint not taken (with Jcc instrs)
232   case 0x36:      // SS override
233   case 0x3E:      // DS override or Branch hint taken (with Jcc instrs)
234   case 0x26:      // ES override
235   case 0x64:      // FS override
236   case 0x65:      // GS override
237     //case 0x2E:      // branch not taken hint
238     //  case 0x3E:      // branch taken hint
239   case 0x66:      // operand size override
240   case 0x67:      // address size override
241     return 1;
242     break;
243   default:
244     return 0;
245     break;
246   }
247 }
248
249
250 static inline v3_reg_t get_gpr_mask(struct guest_info * info) {
251   switch (info->cpu_mode) {
252   case REAL: 
253     return 0xffff;
254     break;
255   case PROTECTED:
256   case PROTECTED_PAE:
257     return 0xffffffff;
258   case LONG:
259   case LONG_32_COMPAT:
260   case LONG_16_COMPAT:
261   default:
262     PrintError("Unsupported Address Mode\n");
263     return -1;
264   }
265 }
266
267
268 static inline addr_t get_addr_linear(struct guest_info * info, addr_t addr, struct v3_segment * seg) {
269   switch (info->cpu_mode) {
270   case REAL:
271     // It appears that the segment values are computed and cached in the vmcb structure 
272     // We Need to check this for Intel
273     /*   return addr + (seg->selector << 4);
274          break;*/
275
276   case PROTECTED:
277   case PROTECTED_PAE:
278   case LONG_32_COMPAT:
279     return addr + seg->base;
280     break;
281
282   case LONG:
283     // In long mode the segment bases are disregarded (forced to 0), unless using 
284     // FS or GS, then the base addresses are added
285     return addr + seg->base;
286
287   case LONG_16_COMPAT:
288   default:
289     PrintError("Unsupported CPU Mode: %d\n", info->cpu_mode);
290     return -1;
291   }
292 }
293
294
295 typedef enum {INVALID_ADDR_TYPE, REG, DISP0, DISP8, DISP16, DISP32} modrm_mode_t;
296 typedef enum {INVALID_REG_SIZE, REG64, REG32, REG16, REG8} reg_size_t;
297
298
299
300
301
302
303 struct v3_gprs;
304
305 static inline addr_t decode_register(struct v3_gprs * gprs, char reg_code, reg_size_t reg_size) {
306   addr_t reg_addr;
307
308   switch (reg_code) {
309   case 0:
310     reg_addr = (addr_t)&(gprs->rax);
311     break;
312   case 1:
313     reg_addr = (addr_t)&(gprs->rcx);
314     break;
315   case 2:
316     reg_addr = (addr_t)&(gprs->rdx);
317     break;
318   case 3:
319     reg_addr = (addr_t)&(gprs->rbx);
320     break;
321   case 4:
322     if (reg_size == REG8) {
323       reg_addr = (addr_t)&(gprs->rax) + 1;
324     } else {
325       reg_addr = (addr_t)&(gprs->rsp);
326     }
327     break;
328   case 5:
329     if (reg_size == REG8) {
330       reg_addr = (addr_t)&(gprs->rcx) + 1;
331     } else {
332       reg_addr = (addr_t)&(gprs->rbp);
333     }
334     break;
335   case 6:
336     if (reg_size == REG8) {
337       reg_addr = (addr_t)&(gprs->rdx) + 1;
338     } else {
339       reg_addr = (addr_t)&(gprs->rsi);
340     }
341     break;
342   case 7:
343     if (reg_size == REG8) {
344       reg_addr = (addr_t)&(gprs->rbx) + 1;
345     } else {
346       reg_addr = (addr_t)&(gprs->rdi);
347     }
348     break;
349   default:
350     reg_addr = 0;
351     break;
352   }
353
354   return reg_addr;
355 }
356
357
358
359 static inline v3_operand_type_t decode_operands16(struct v3_gprs * gprs, // input/output
360                                                char * modrm_instr,       // input
361                                                int * offset,             // output
362                                                addr_t * first_operand,   // output
363                                                addr_t * second_operand,  // output
364                                                reg_size_t reg_size) {    // input
365   
366   struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
367   addr_t base_addr = 0;
368   modrm_mode_t mod_mode = 0;
369   v3_operand_type_t addr_type = INVALID_OPERAND;
370   char * instr_cursor = modrm_instr;
371
372   //  PrintDebug("ModRM mod=%d\n", modrm->mod);
373
374   instr_cursor += 1;
375
376   if (modrm->mod == 3) {
377     mod_mode = REG;
378     addr_type = REG_OPERAND;
379     //PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
380
381     *first_operand = decode_register(gprs, modrm->rm, reg_size);
382
383   } else {
384
385     addr_type = MEM_OPERAND;
386
387     if (modrm->mod == 0) {
388       mod_mode = DISP0;
389     } else if (modrm->mod == 1) {
390       mod_mode = DISP8;
391     } else if (modrm->mod == 2) {
392       mod_mode = DISP16;
393     }
394
395     switch (modrm->rm) {
396     case 0:
397       base_addr = gprs->rbx + gprs->rsi;
398       break;
399     case 1:
400       base_addr = gprs->rbx + gprs->rdi;
401       break;
402     case 2:
403       base_addr = gprs->rbp + gprs->rsi;
404       break;
405     case 3:
406       base_addr = gprs->rbp + gprs->rdi;
407       break;
408     case 4:
409       base_addr = gprs->rsi;
410       break;
411     case 5:
412       base_addr = gprs->rdi;
413       break;
414     case 6:
415       if (modrm->mod == 0) {
416         base_addr = 0;
417         mod_mode = DISP16;
418       } else {
419         base_addr = gprs->rbp;
420       }
421       break;
422     case 7:
423       base_addr = gprs->rbx;
424       break;
425     }
426
427
428
429     if (mod_mode == DISP8) {
430       base_addr += (uchar_t)*(instr_cursor);
431       instr_cursor += 1;
432     } else if (mod_mode == DISP16) {
433       base_addr += (ushort_t)*(instr_cursor);
434       instr_cursor += 2;
435     }
436     
437     *first_operand = base_addr;
438   }
439
440   *offset +=  (instr_cursor - modrm_instr);
441   *second_operand = decode_register(gprs, modrm->reg, reg_size);
442
443   return addr_type;
444 }
445
446
447
448 static inline v3_operand_type_t decode_operands32(struct v3_gprs * gprs, // input/output
449                                                uchar_t * modrm_instr,       // input
450                                                int * offset,             // output
451                                                addr_t * first_operand,   // output
452                                                addr_t * second_operand,  // output
453                                                reg_size_t reg_size) {    // input
454   
455   uchar_t * instr_cursor = modrm_instr;
456   struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
457   addr_t base_addr = 0;
458   modrm_mode_t mod_mode = 0;
459   uint_t has_sib_byte = 0;
460   v3_operand_type_t addr_type = INVALID_OPERAND;
461
462
463
464   instr_cursor += 1;
465
466   if (modrm->mod == 3) {
467     mod_mode = REG;
468     addr_type = REG_OPERAND;
469     
470     //    PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
471
472     *first_operand = decode_register(gprs, modrm->rm, reg_size);
473
474   } else {
475
476     addr_type = MEM_OPERAND;
477
478     if (modrm->mod == 0) {
479       mod_mode = DISP0;
480     } else if (modrm->mod == 1) {
481       mod_mode = DISP8;
482     } else if (modrm->mod == 2) {
483       mod_mode = DISP32;
484     }
485     
486     switch (modrm->rm) {
487     case 0:
488       base_addr = gprs->rax;
489       break;
490     case 1:
491        base_addr = gprs->rcx;
492       break;
493     case 2:
494       base_addr = gprs->rdx;
495       break;
496     case 3:
497       base_addr = gprs->rbx;
498       break;
499     case 4:
500       has_sib_byte = 1;
501       break;
502     case 5:
503       if (modrm->mod == 0) {
504         base_addr = 0;
505         mod_mode = DISP32;
506       } else {
507         base_addr = gprs->rbp;
508       }
509       break;
510     case 6:
511       base_addr = gprs->rsi;
512       break;
513     case 7:
514       base_addr = gprs->rdi;
515       break;
516     }
517
518     if (has_sib_byte) {
519       instr_cursor += 1;
520       struct sib_byte * sib = (struct sib_byte *)(instr_cursor);
521       int scale = 1;
522
523       instr_cursor += 1;
524
525
526       if (sib->scale == 1) {
527         scale = 2;
528       } else if (sib->scale == 2) {
529         scale = 4;
530       } else if (sib->scale == 3) {
531         scale = 8;
532       }
533
534
535       switch (sib->index) {
536       case 0:
537         base_addr = gprs->rax;
538         break;
539       case 1:
540         base_addr = gprs->rcx;
541         break;
542       case 2:
543         base_addr = gprs->rdx;
544         break;
545       case 3:
546         base_addr = gprs->rbx;
547         break;
548       case 4:
549         base_addr = 0;
550         break;
551       case 5:
552         base_addr = gprs->rbp;
553         break;
554       case 6:
555         base_addr = gprs->rsi;
556         break;
557       case 7:
558         base_addr = gprs->rdi;
559         break;
560       }
561
562       base_addr *= scale;
563
564
565       switch (sib->base) {
566       case 0:
567         base_addr += gprs->rax;
568         break;
569       case 1:
570         base_addr += gprs->rcx;
571         break;
572       case 2:
573         base_addr += gprs->rdx;
574         break;
575       case 3:
576         base_addr += gprs->rbx;
577         break;
578       case 4:
579         base_addr += gprs->rsp;
580         break;
581       case 5:
582         if (modrm->mod != 0) {
583           base_addr += gprs->rbp;
584         }
585         break;
586       case 6:
587         base_addr += gprs->rsi;
588         break;
589       case 7:
590         base_addr += gprs->rdi;
591         break;
592       }
593
594     } 
595
596
597     if (mod_mode == DISP8) {
598       base_addr += (uchar_t)*(instr_cursor);
599       instr_cursor += 1;
600     } else if (mod_mode == DISP32) {
601       base_addr += (uint_t)*(instr_cursor);
602       instr_cursor += 4;
603     }
604     
605
606     *first_operand = base_addr;
607   }
608
609   *offset += (instr_cursor - modrm_instr);
610
611   *second_operand = decode_register(gprs, modrm->reg, reg_size);
612
613   return addr_type;
614 }
615
616
617
618 #endif // !__V3VEE__
619
620
621 #endif