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.


5b0d10524c7cfc6a8ddc4588b3a0b5cf535fac00
[palacios.git] / palacios / src / palacios / vmm_xed.c
1 #include <palacios/vmm_decoder.h>
2 #include <palacios/vmm_xed.h>
3 #include <xed/xed-interface.h>
4 #include <palacios/vm_guest.h>
5
6 static xed_state_t decoder_state;
7
8
9 // This returns a pointer to a V3_OPCODE_[*] array defined in vmm_decoder.h
10 static int get_opcode(xed_iform_enum_t iform, addr_t * opcode);
11
12 static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, addr_t * v3_reg, uint_t * reg_len);
13
14
15 static int set_decoder_mode(struct guest_info * info, xed_state_t * state) {
16   switch (info->cpu_mode) {
17   case REAL:
18     if (state->mmode != XED_MACHINE_MODE_LEGACY_16) {
19       xed_state_init(state,
20                      XED_MACHINE_MODE_LEGACY_16, 
21                      XED_ADDRESS_WIDTH_16b, 
22                      XED_ADDRESS_WIDTH_16b); 
23     }
24    break;
25   case PROTECTED:
26   case PROTECTED_PAE:
27     if (state->mmode != XED_MACHINE_MODE_LEGACY_32) {
28       xed_state_init(state,
29                      XED_MACHINE_MODE_LEGACY_32, 
30                      XED_ADDRESS_WIDTH_32b, 
31                      XED_ADDRESS_WIDTH_32b);
32     }
33     break;
34   case LONG:
35     if (state->mmode != XED_MACHINE_MODE_LONG_64) {    
36       state->mmode = XED_MACHINE_MODE_LONG_64;
37     }
38     break;
39   default:
40     return -1;
41   }
42   return 0;
43 }
44
45
46
47
48
49 int init_decoder() {
50   xed_tables_init();
51   xed_state_zero(&decoder_state);
52   return 0;
53 }
54
55
56 int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * instr) {
57   xed_decoded_inst_t xed_instr;
58   xed_error_enum_t xed_error;
59
60
61
62   if (set_decoder_mode(info, &decoder_state) == -1) {
63     PrintError("Could not set decoder mode\n");
64     return -1;
65   }
66
67
68
69   xed_decoded_inst_zero_set_mode(&xed_instr, &decoder_state);
70
71   xed_error = xed_decode(&xed_instr, 
72                          REINTERPRET_CAST(const xed_uint8_t *, instr_ptr), 
73                          XED_MAX_INSTRUCTION_BYTES);
74
75
76   if (xed_error != XED_ERROR_NONE) {
77     PrintError("Xed error: %s\n", xed_error_enum_t2str(xed_error));
78     return -1;
79   }
80
81   const xed_inst_t * xi = xed_decoded_inst_inst(&xed_instr);
82   
83   instr->instr_length = xed_decoded_inst_get_length(&xed_instr);
84   instr->num_operands = xed_decoded_inst_noperands(&xed_instr);
85
86   xed_iform_enum_t iform = xed_decoded_inst_get_iform_enum(&xed_instr);
87
88   if (get_opcode(iform, &(instr->opcode)) == -1) {
89     PrintError("Could not get opcode. (iform=%s)\n", xed_iform_enum_t2str(iform));
90     return -1;
91   }
92
93
94
95   PrintDebug("Number of operands: %d\n", instr->num_operands);
96   PrintDebug("INSTR length: %d\n", instr->instr_length);
97
98   // set first operand
99   if (instr->num_operands >= 1) {
100     const xed_operand_t * op = xed_inst_operand(xi, 0);
101     xed_operand_type_enum_t op_type = xed_operand_type(op);
102     xed_operand_enum_t op_enum = xed_operand_name(op);
103
104
105     if (xed_operand_is_register(op_enum)) {
106       xed_reg_enum_t xed_reg =  xed_decoded_inst_get_reg(&xed_instr, op_enum);
107       if (xed_reg_to_v3_reg(info, 
108                             xed_reg, 
109                             &(instr->first_operand.operand), 
110                             &(instr->first_operand.size)) == -1) {
111         
112         PrintError("First operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
113         instr->first_operand.type = INVALID_OPERAND;
114         return -1;
115       }
116
117       instr->first_operand.type = REG_OPERAND;
118       PrintDebug("First Operand: xed_reg=0x%x\n", instr->first_operand.operand);
119
120     } else {
121       PrintError("Unhandled first operand type %s\n", xed_operand_type_enum_t2str(op_type));
122       return -1;
123     }
124   }
125
126   // set second operand
127   if (instr->num_operands >= 2) {
128     const xed_operand_t * op = xed_inst_operand(xi, 1);
129     xed_operand_type_enum_t op_type = xed_operand_type(op);
130     xed_operand_enum_t op_enum = xed_operand_name(op);
131     
132     if (xed_operand_is_register(op_enum)) {
133       xed_reg_enum_t xed_reg =  xed_decoded_inst_get_reg(&xed_instr, op_enum);
134       if (xed_reg_to_v3_reg(info, 
135                             xed_reg, 
136                             &(instr->second_operand.operand), 
137                             &(instr->second_operand.size)) == -1) {
138         
139         PrintError("Second operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
140         instr->second_operand.type = INVALID_OPERAND;
141         return -1;
142       }
143
144       instr->second_operand.type = REG_OPERAND;
145     
146       PrintDebug("Second Operand: xed_reg=0x%x\n", instr->second_operand.operand); 
147     } else {
148       PrintError("Unhandled second operand type %s\n", xed_operand_type_enum_t2str(op_type));
149       return -1;
150     }
151   }
152
153   // set third operand
154   if (instr->num_operands >= 3) {
155     const xed_operand_t * op = xed_inst_operand(xi, 2);
156     xed_operand_type_enum_t op_type = xed_operand_type(op);
157     xed_operand_enum_t op_enum = xed_operand_name(op);
158
159     if (xed_operand_is_register(op_enum)) {
160       xed_reg_enum_t xed_reg =  xed_decoded_inst_get_reg(&xed_instr, op_enum);
161       if (xed_reg_to_v3_reg(info, 
162                             xed_reg, 
163                             &(instr->third_operand.operand), 
164                             &(instr->third_operand.size)) == -1) {
165         
166         PrintError("Third operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
167         instr->third_operand.type = INVALID_OPERAND;
168         return -1;
169       }
170       instr->third_operand.type = REG_OPERAND;
171
172       PrintDebug("Third Operand: xed_reg=0x%x\n", instr->third_operand.operand); 
173     } else {
174       PrintError("Unhandled third operand type %s\n", xed_operand_type_enum_t2str(op_type));
175       return -1;
176     }
177
178
179   }
180
181   /*
182     PrintDebug("category: %s\n", xed_category_enum_t2str(xed_decoded_inst_get_category(&xed_instr)));;
183     PrintDebug("ISA-extension:%s\n ",xed_extension_enum_t2str(xed_decoded_inst_get_extension(&xed_instr)));
184     PrintDebug(" instruction-length: %d\n ", xed_decoded_inst_get_length(&xed_instr));
185     PrintDebug(" operand-size:%d\n ", xed_operand_values_get_effective_operand_width(xed_decoded_inst_operands_const(&xed_instr)));   
186     PrintDebug("address-size:%d\n ", xed_operand_values_get_effective_address_width(xed_decoded_inst_operands_const(&xed_instr))); 
187     PrintDebug("iform-enum-name:%s\n ",xed_iform_enum_t2str(xed_decoded_inst_get_iform_enum(&xed_instr)));
188     PrintDebug("iform-enum-name-dispatch (zero based):%d\n ", xed_decoded_inst_get_iform_enum_dispatch(&xed_instr));
189     PrintDebug("iclass-max-iform-dispatch: %d\n ", xed_iform_max_per_iclass(xed_decoded_inst_get_iclass(&xed_instr)));
190   */  
191   // operands
192   // print_operands(&xed_instr);
193   
194   // memops
195   // print_memops(&xed_instr);
196   
197   // flags
198   //print_flags(&xed_instr);
199   
200   // attributes
201   //print_attributes(&xed_instr);*/
202
203
204
205     return 0;
206 }
207
208
209 int v3_encode(struct guest_info * info, struct x86_instr * instr, char * instr_buf) {
210
211   return -1;
212 }
213
214
215 static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, addr_t * v3_reg, uint_t * reg_len) {
216
217   switch (xed_reg) {
218   case XED_REG_INVALID:
219     *v3_reg = 0;
220     *reg_len = 0;
221     return -1;
222
223     /* 
224      * GPRs
225      */
226   case XED_REG_RAX: 
227     *v3_reg = (addr_t)&(info->vm_regs.rax);
228     *reg_len = 8;
229     break;
230   case XED_REG_EAX:
231     *v3_reg = (addr_t)&(info->vm_regs.rax);
232     *reg_len = 4;
233     break;
234   case XED_REG_AX:
235     *v3_reg = (addr_t)&(info->vm_regs.rax);
236     *reg_len = 2;
237     break;
238   case XED_REG_AH:
239     *v3_reg = (addr_t)(&(info->vm_regs.rax)) + 1;
240     *reg_len = 1;
241     break;
242   case XED_REG_AL:
243     *v3_reg = (addr_t)&(info->vm_regs.rax);
244     *reg_len = 1;
245     break;
246
247   case XED_REG_RCX: 
248     *v3_reg = (addr_t)&(info->vm_regs.rcx);
249     *reg_len = 8;
250     break;
251   case XED_REG_ECX:
252     *v3_reg = (addr_t)&(info->vm_regs.rcx);
253     *reg_len = 4;
254     break;
255   case XED_REG_CX:
256     *v3_reg = (addr_t)&(info->vm_regs.rcx);
257     *reg_len = 2;
258     break;
259   case XED_REG_CH:
260     *v3_reg = (addr_t)(&(info->vm_regs.rcx)) + 1;
261     *reg_len = 1;
262     break;
263   case XED_REG_CL:
264     *v3_reg = (addr_t)&(info->vm_regs.rcx);
265     *reg_len = 1;
266     break;
267
268   case XED_REG_RDX: 
269     *v3_reg = (addr_t)&(info->vm_regs.rdx);
270     *reg_len = 8;
271     break;
272   case XED_REG_EDX:
273     *v3_reg = (addr_t)&(info->vm_regs.rdx);
274     *reg_len = 4;
275     break;
276   case XED_REG_DX:
277     *v3_reg = (addr_t)&(info->vm_regs.rdx);
278     *reg_len = 2;
279     break;
280   case XED_REG_DH:
281     *v3_reg = (addr_t)(&(info->vm_regs.rdx)) + 1;
282     *reg_len = 1;
283     break;
284   case XED_REG_DL:
285     *v3_reg = (addr_t)&(info->vm_regs.rdx);
286     *reg_len = 1;
287     break;
288
289   case XED_REG_RBX: 
290     *v3_reg = (addr_t)&(info->vm_regs.rbx);
291     *reg_len = 8;
292     break;
293   case XED_REG_EBX:
294     *v3_reg = (addr_t)&(info->vm_regs.rbx);
295     *reg_len = 4;
296     break;
297   case XED_REG_BX:
298     *v3_reg = (addr_t)&(info->vm_regs.rbx);
299     *reg_len = 2;
300     break;
301   case XED_REG_BH:
302     *v3_reg = (addr_t)(&(info->vm_regs.rbx)) + 1;
303     *reg_len = 1;
304     break;
305   case XED_REG_BL:
306     *v3_reg = (addr_t)&(info->vm_regs.rbx);
307     *reg_len = 1;
308     break;
309
310
311   case XED_REG_RSP:
312     *v3_reg = (addr_t)&(info->vm_regs.rsp);
313     *reg_len = 8;
314     break;
315   case XED_REG_ESP:
316     *v3_reg = (addr_t)&(info->vm_regs.rsp);
317     *reg_len = 4;
318     break;
319   case XED_REG_SP:
320     *v3_reg = (addr_t)&(info->vm_regs.rsp);
321     *reg_len = 2;
322     break;
323   case XED_REG_SPL:
324     *v3_reg = (addr_t)&(info->vm_regs.rsp);
325     *reg_len = 1;
326     break;
327
328   case XED_REG_RBP:
329     *v3_reg = (addr_t)&(info->vm_regs.rbp);
330     *reg_len = 8;
331     break;
332   case XED_REG_EBP:
333     *v3_reg = (addr_t)&(info->vm_regs.rbp);
334     *reg_len = 4;
335     break;
336   case XED_REG_BP:
337     *v3_reg = (addr_t)&(info->vm_regs.rbp);
338     *reg_len = 2;
339     break;
340   case XED_REG_BPL:
341     *v3_reg = (addr_t)&(info->vm_regs.rbp);
342     *reg_len = 1;
343     break;
344
345
346
347   case XED_REG_RSI:
348     *v3_reg = (addr_t)&(info->vm_regs.rsi);
349     *reg_len = 8;
350     break;
351   case XED_REG_ESI:
352     *v3_reg = (addr_t)&(info->vm_regs.rsi);
353     *reg_len = 4;
354     break;
355   case XED_REG_SI:
356     *v3_reg = (addr_t)&(info->vm_regs.rsi);
357     *reg_len = 2;
358     break;
359   case XED_REG_SIL:
360     *v3_reg = (addr_t)&(info->vm_regs.rsi);
361     *reg_len = 1;
362     break;
363
364
365   case XED_REG_RDI:
366     *v3_reg = (addr_t)&(info->vm_regs.rdi);
367     *reg_len = 8;
368     break;
369   case XED_REG_EDI:
370     *v3_reg = (addr_t)&(info->vm_regs.rdi);
371     *reg_len = 4;
372     break;
373   case XED_REG_DI:
374     *v3_reg = (addr_t)&(info->vm_regs.rdi);
375     *reg_len = 2;
376     break;
377   case XED_REG_DIL:
378     *v3_reg = (addr_t)&(info->vm_regs.rdi);
379     *reg_len = 1;
380     break;
381
382
383     /* 
384      *  CTRL REGS
385      */
386   case XED_REG_RIP:
387     *v3_reg = (addr_t)&(info->rip);
388     *reg_len = 8;
389     break;
390   case XED_REG_EIP:
391     *v3_reg = (addr_t)&(info->rip);
392     *reg_len = 4;
393     break;  
394   case XED_REG_IP:
395     *v3_reg = (addr_t)&(info->rip);
396     *reg_len = 2;
397     break;
398
399   case XED_REG_FLAGS:
400     *v3_reg = (addr_t)&(info->ctrl_regs.rflags);
401     *reg_len = 2;
402     break;
403   case XED_REG_EFLAGS:
404     *v3_reg = (addr_t)&(info->ctrl_regs.rflags);
405     *reg_len = 4;
406     break;
407   case XED_REG_RFLAGS:
408     *v3_reg = (addr_t)&(info->ctrl_regs.rflags);
409     *reg_len = 8;
410     break;
411
412   case XED_REG_CR0:
413     *v3_reg = (addr_t)&(info->ctrl_regs.cr0);
414     *reg_len = 4;
415     break;
416   case XED_REG_CR2:
417     *v3_reg = (addr_t)&(info->ctrl_regs.cr2);
418     *reg_len = 4;
419     break;
420   case XED_REG_CR3:
421     *v3_reg = (addr_t)&(info->ctrl_regs.cr3);
422     *reg_len = 4;
423     break;
424   case XED_REG_CR4:
425     *v3_reg = (addr_t)&(info->ctrl_regs.cr4);
426     *reg_len = 4;
427     break;
428   case XED_REG_CR8:
429     *v3_reg = (addr_t)&(info->ctrl_regs.cr8);
430     *reg_len = 4;
431     break;
432
433   case XED_REG_CR1:
434   case XED_REG_CR5:
435   case XED_REG_CR6:
436   case XED_REG_CR7:
437   case XED_REG_CR9:
438   case XED_REG_CR10:
439   case XED_REG_CR11:
440   case XED_REG_CR12:
441   case XED_REG_CR13:
442   case XED_REG_CR14:
443   case XED_REG_CR15:
444     return -1;
445
446
447
448
449     /* 
450      * SEGMENT REGS
451      */
452   case XED_REG_CS:
453     *v3_reg = (addr_t)&(info->segments.cs.selector);
454     *reg_len = 16;
455     break;
456   case XED_REG_DS:
457     *v3_reg = (addr_t)&(info->segments.ds.selector);
458     *reg_len = 16;
459     break;
460   case XED_REG_ES:
461     *v3_reg = (addr_t)&(info->segments.es.selector);
462     *reg_len = 16;
463     break;
464   case XED_REG_SS:
465     *v3_reg = (addr_t)&(info->segments.ss.selector);
466     *reg_len = 16;
467     break;
468   case XED_REG_FS:
469     *v3_reg = (addr_t)&(info->segments.fs.selector);
470     *reg_len = 16;
471     break;
472   case XED_REG_GS:
473     *v3_reg = (addr_t)&(info->segments.fs.selector);
474     *reg_len = 16;
475     break;
476
477
478   case XED_REG_GDTR:
479   case XED_REG_LDTR:
480   case XED_REG_IDTR:
481   case XED_REG_TR:
482     PrintError("Segment selector operand... Don't know how to handle this...\n");
483     return -1;
484
485     /* 
486      *  DEBUG REGS
487      */
488   case XED_REG_DR0:
489   case XED_REG_DR1:
490   case XED_REG_DR2:
491   case XED_REG_DR3:
492   case XED_REG_DR4:
493   case XED_REG_DR5:
494   case XED_REG_DR6:
495   case XED_REG_DR7:
496   case XED_REG_DR8:
497   case XED_REG_DR9:
498   case XED_REG_DR10:
499   case XED_REG_DR11:
500   case XED_REG_DR12:
501   case XED_REG_DR13:
502   case XED_REG_DR14:
503   case XED_REG_DR15:
504     return -1;
505
506
507
508
509   case XED_REG_R8:
510   case XED_REG_R8D:
511   case XED_REG_R8W:
512   case XED_REG_R8B:
513
514   case XED_REG_R9:
515   case XED_REG_R9D:
516   case XED_REG_R9W:
517   case XED_REG_R9B:
518
519   case XED_REG_R10:
520   case XED_REG_R10D:
521   case XED_REG_R10W:
522   case XED_REG_R10B:
523
524   case XED_REG_R11:
525   case XED_REG_R11D:
526   case XED_REG_R11W:
527   case XED_REG_R11B:
528
529   case XED_REG_R12:
530   case XED_REG_R12D:
531   case XED_REG_R12W:
532   case XED_REG_R12B:
533
534   case XED_REG_R13:
535   case XED_REG_R13D:
536   case XED_REG_R13W:
537   case XED_REG_R13B:
538
539   case XED_REG_R14:
540   case XED_REG_R14D:
541   case XED_REG_R14W:
542   case XED_REG_R14B:
543
544   case XED_REG_R15:
545   case XED_REG_R15D:
546   case XED_REG_R15W:
547   case XED_REG_R15B:
548
549   case XED_REG_XMM0:
550   case XED_REG_XMM1:
551   case XED_REG_XMM2:
552   case XED_REG_XMM3:
553   case XED_REG_XMM4:
554   case XED_REG_XMM5:
555   case XED_REG_XMM6:
556   case XED_REG_XMM7:
557   case XED_REG_XMM8:
558   case XED_REG_XMM9:
559   case XED_REG_XMM10:
560   case XED_REG_XMM11:
561   case XED_REG_XMM12:
562   case XED_REG_XMM13:
563   case XED_REG_XMM14:
564   case XED_REG_XMM15:
565
566   case XED_REG_MMX0:
567   case XED_REG_MMX1:
568   case XED_REG_MMX2:
569   case XED_REG_MMX3:
570   case XED_REG_MMX4:
571   case XED_REG_MMX5:
572   case XED_REG_MMX6:
573   case XED_REG_MMX7:
574
575   case XED_REG_ST0:
576   case XED_REG_ST1:
577   case XED_REG_ST2:
578   case XED_REG_ST3:
579   case XED_REG_ST4:
580   case XED_REG_ST5:
581   case XED_REG_ST6:
582   case XED_REG_ST7:
583
584   case XED_REG_ONE:
585   case XED_REG_STACKPUSH:
586   case XED_REG_STACKPOP:
587     
588   case XED_REG_TSC:
589   case XED_REG_TSCAUX:
590   case XED_REG_MSRS:
591
592   case XED_REG_X87CONTROL:
593   case XED_REG_X87STATUS:
594   case XED_REG_X87TOP:
595   case XED_REG_X87TAG:
596   case XED_REG_X87PUSH:
597   case XED_REG_X87POP:
598   case XED_REG_X87POP2:
599
600   case XED_REG_MXCSR:
601
602   case XED_REG_TMP0:
603   case XED_REG_TMP1:
604   case XED_REG_TMP2:
605   case XED_REG_TMP3:
606   case XED_REG_TMP4:
607   case XED_REG_TMP5:
608   case XED_REG_TMP6:
609   case XED_REG_TMP7:
610   case XED_REG_TMP8:
611   case XED_REG_TMP9:
612   case XED_REG_TMP10:
613   case XED_REG_TMP11:
614   case XED_REG_TMP12:
615   case XED_REG_TMP13:
616   case XED_REG_TMP14:
617   case XED_REG_TMP15:
618
619   case XED_REG_LAST:
620
621   case XED_REG_ERROR:
622     // error??
623     return -1;
624
625   }
626
627
628   return 0;
629 }
630
631
632
633 static int get_opcode(xed_iform_enum_t iform, addr_t * opcode) {
634
635   switch (iform) {
636   case XED_IFORM_MOV_CR_GPR64_CR:
637   case XED_IFORM_MOV_CR_GPR32_CR:
638     *opcode = (addr_t)&V3_OPCODE_MOVCR2;
639     break;
640
641   case XED_IFORM_MOV_CR_CR_GPR64:
642   case XED_IFORM_MOV_CR_CR_GPR32:
643     *opcode = (addr_t)&V3_OPCODE_MOV2CR;
644     break;
645
646
647   case XED_IFORM_LMSW_GPR16:
648     *opcode = (addr_t)&V3_OPCODE_LMSW;
649     break;
650
651   case XED_IFORM_CLTS:
652     *opcode = (addr_t)&V3_OPCODE_CLTS;
653     break;
654
655   default:
656     *opcode = 0;
657     return -1;
658   }
659
660   return 0;
661 }