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.


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