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.


Release 1.0
[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     return 0xffffffff;
245   default:
246     V3_ASSERT(0);
247     return 0;
248   }
249 }
250
251
252 static inline addr_t get_addr_linear(struct guest_info * info, addr_t addr, struct v3_segment * seg) {
253   switch (info->cpu_mode) {
254   case REAL:
255     // It appears that the segment values are computed and cached in the vmcb structure 
256     // We Need to check this for Intel
257     /*   return addr + (seg->selector << 4);
258          break;*/
259
260   case PROTECTED:
261     return addr + seg->base;
262     break;
263   default:
264     V3_ASSERT(0);
265     return 0;
266   }
267 }
268
269
270 typedef enum {INVALID_ADDR_TYPE, REG, DISP0, DISP8, DISP16, DISP32} modrm_mode_t;
271 typedef enum {INVALID_REG_SIZE, REG64, REG32, REG16, REG8} reg_size_t;
272
273
274
275
276
277
278 struct v3_gprs;
279
280 static inline addr_t decode_register(struct v3_gprs * gprs, char reg_code, reg_size_t reg_size) {
281   addr_t reg_addr;
282
283   switch (reg_code) {
284   case 0:
285     reg_addr = (addr_t)&(gprs->rax);
286     break;
287   case 1:
288     reg_addr = (addr_t)&(gprs->rcx);
289     break;
290   case 2:
291     reg_addr = (addr_t)&(gprs->rdx);
292     break;
293   case 3:
294     reg_addr = (addr_t)&(gprs->rbx);
295     break;
296   case 4:
297     if (reg_size == REG8) {
298       reg_addr = (addr_t)&(gprs->rax) + 1;
299     } else {
300       reg_addr = (addr_t)&(gprs->rsp);
301     }
302     break;
303   case 5:
304     if (reg_size == REG8) {
305       reg_addr = (addr_t)&(gprs->rcx) + 1;
306     } else {
307       reg_addr = (addr_t)&(gprs->rbp);
308     }
309     break;
310   case 6:
311     if (reg_size == REG8) {
312       reg_addr = (addr_t)&(gprs->rdx) + 1;
313     } else {
314       reg_addr = (addr_t)&(gprs->rsi);
315     }
316     break;
317   case 7:
318     if (reg_size == REG8) {
319       reg_addr = (addr_t)&(gprs->rbx) + 1;
320     } else {
321       reg_addr = (addr_t)&(gprs->rdi);
322     }
323     break;
324   default:
325     reg_addr = 0;
326     break;
327   }
328
329   return reg_addr;
330 }
331
332
333
334 static inline v3_operand_type_t decode_operands16(struct v3_gprs * gprs, // input/output
335                                                char * modrm_instr,       // input
336                                                int * offset,             // output
337                                                addr_t * first_operand,   // output
338                                                addr_t * second_operand,  // output
339                                                reg_size_t reg_size) {    // input
340   
341   struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
342   addr_t base_addr = 0;
343   modrm_mode_t mod_mode = 0;
344   v3_operand_type_t addr_type = INVALID_OPERAND;
345   char * instr_cursor = modrm_instr;
346
347   //  PrintDebug("ModRM mod=%d\n", modrm->mod);
348
349   instr_cursor += 1;
350
351   if (modrm->mod == 3) {
352     mod_mode = REG;
353     addr_type = REG_OPERAND;
354     //PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
355
356     *first_operand = decode_register(gprs, modrm->rm, reg_size);
357
358   } else {
359
360     addr_type = MEM_OPERAND;
361
362     if (modrm->mod == 0) {
363       mod_mode = DISP0;
364     } else if (modrm->mod == 1) {
365       mod_mode = DISP8;
366     } else if (modrm->mod == 2) {
367       mod_mode = DISP16;
368     }
369
370     switch (modrm->rm) {
371     case 0:
372       base_addr = gprs->rbx + gprs->rsi;
373       break;
374     case 1:
375       base_addr = gprs->rbx + gprs->rdi;
376       break;
377     case 2:
378       base_addr = gprs->rbp + gprs->rsi;
379       break;
380     case 3:
381       base_addr = gprs->rbp + gprs->rdi;
382       break;
383     case 4:
384       base_addr = gprs->rsi;
385       break;
386     case 5:
387       base_addr = gprs->rdi;
388       break;
389     case 6:
390       if (modrm->mod == 0) {
391         base_addr = 0;
392         mod_mode = DISP16;
393       } else {
394         base_addr = gprs->rbp;
395       }
396       break;
397     case 7:
398       base_addr = gprs->rbx;
399       break;
400     }
401
402
403
404     if (mod_mode == DISP8) {
405       base_addr += (uchar_t)*(instr_cursor);
406       instr_cursor += 1;
407     } else if (mod_mode == DISP16) {
408       base_addr += (ushort_t)*(instr_cursor);
409       instr_cursor += 2;
410     }
411     
412     *first_operand = base_addr;
413   }
414
415   *offset +=  (instr_cursor - modrm_instr);
416   *second_operand = decode_register(gprs, modrm->reg, reg_size);
417
418   return addr_type;
419 }
420
421
422
423 static inline v3_operand_type_t decode_operands32(struct v3_gprs * gprs, // input/output
424                                                uchar_t * modrm_instr,       // input
425                                                int * offset,             // output
426                                                addr_t * first_operand,   // output
427                                                addr_t * second_operand,  // output
428                                                reg_size_t reg_size) {    // input
429   
430   uchar_t * instr_cursor = modrm_instr;
431   struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
432   addr_t base_addr = 0;
433   modrm_mode_t mod_mode = 0;
434   uint_t has_sib_byte = 0;
435   v3_operand_type_t addr_type = INVALID_OPERAND;
436
437
438
439   instr_cursor += 1;
440
441   if (modrm->mod == 3) {
442     mod_mode = REG;
443     addr_type = REG_OPERAND;
444     
445     //    PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
446
447     *first_operand = decode_register(gprs, modrm->rm, reg_size);
448
449   } else {
450
451     addr_type = MEM_OPERAND;
452
453     if (modrm->mod == 0) {
454       mod_mode = DISP0;
455     } else if (modrm->mod == 1) {
456       mod_mode = DISP8;
457     } else if (modrm->mod == 2) {
458       mod_mode = DISP32;
459     }
460     
461     switch (modrm->rm) {
462     case 0:
463       base_addr = gprs->rax;
464       break;
465     case 1:
466       base_addr = gprs->rcx;
467       break;
468     case 2:
469       base_addr = gprs->rdx;
470       break;
471     case 3:
472       base_addr = gprs->rbx;
473       break;
474     case 4:
475       has_sib_byte = 1;
476       break;
477     case 5:
478       if (modrm->mod == 0) {
479         base_addr = 0;
480         mod_mode = DISP32;
481       } else {
482         base_addr = gprs->rbp;
483       }
484       break;
485     case 6:
486       base_addr = gprs->rsi;
487       break;
488     case 7:
489       base_addr = gprs->rdi;
490       break;
491     }
492
493     if (has_sib_byte) {
494       instr_cursor += 1;
495       struct sib_byte * sib = (struct sib_byte *)(instr_cursor);
496       int scale = 1;
497
498       instr_cursor += 1;
499
500
501       if (sib->scale == 1) {
502         scale = 2;
503       } else if (sib->scale == 2) {
504         scale = 4;
505       } else if (sib->scale == 3) {
506         scale = 8;
507       }
508
509
510       switch (sib->index) {
511       case 0:
512         base_addr = gprs->rax;
513         break;
514       case 1:
515         base_addr = gprs->rcx;
516         break;
517       case 2:
518         base_addr = gprs->rdx;
519         break;
520       case 3:
521         base_addr = gprs->rbx;
522         break;
523       case 4:
524         base_addr = 0;
525         break;
526       case 5:
527         base_addr = gprs->rbp;
528         break;
529       case 6:
530         base_addr = gprs->rsi;
531         break;
532       case 7:
533         base_addr = gprs->rdi;
534         break;
535       }
536
537       base_addr *= scale;
538
539
540       switch (sib->base) {
541       case 0:
542         base_addr += gprs->rax;
543         break;
544       case 1:
545         base_addr += gprs->rcx;
546         break;
547       case 2:
548         base_addr += gprs->rdx;
549         break;
550       case 3:
551         base_addr += gprs->rbx;
552         break;
553       case 4:
554         base_addr += gprs->rsp;
555         break;
556       case 5:
557         if (modrm->mod != 0) {
558           base_addr += gprs->rbp;
559         }
560         break;
561       case 6:
562         base_addr += gprs->rsi;
563         break;
564       case 7:
565         base_addr += gprs->rdi;
566         break;
567       }
568
569     } 
570
571
572     if (mod_mode == DISP8) {
573       base_addr += (uchar_t)*(instr_cursor);
574       instr_cursor += 1;
575     } else if (mod_mode == DISP32) {
576       base_addr += (uint_t)*(instr_cursor);
577       instr_cursor += 4;
578     }
579     
580
581     *first_operand = base_addr;
582   }
583
584   *offset += (instr_cursor - modrm_instr);
585
586   *second_operand = decode_register(gprs, modrm->reg, reg_size);
587
588   return addr_type;
589 }
590
591
592
593 #endif // !__V3VEE__
594
595
596 #endif