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