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.


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