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.


format fix
[palacios.git] / palacios / src / palacios / vmm_v3dec.c
1 /* 
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #include <palacios/vmm_decoder.h>
21 #include <palacios/vmm_instr_decoder.h>
22
23
24 #define MASK(val, length) ({                                            \
25             ullong_t mask = 0x0LL;                                      \
26             switch (length) {                                           \
27                 case 1:                                                 \
28                     mask = 0x00000000000000ffLL;                        \
29                     break;                                              \
30                 case 2:                                                 \
31                     mask = 0x000000000000ffffLL;                        \
32                     break;                                              \
33                 case 4:                                                 \
34                     mask = 0x00000000ffffffffLL;                        \
35                     break;                                              \
36                 case 8:                                                 \
37                     mask = 0xffffffffffffffffLL;                        \
38                     break;                                              \
39             }                                                           \
40             val & mask;                                                 \
41         })
42
43 static v3_op_type_t op_form_to_type(op_form_t form);
44 static int parse_operands(struct guest_info * core, uint8_t * instr_ptr, struct x86_instr * instr, op_form_t form);
45
46
47 int v3_disasm(struct guest_info * info, void *instr_ptr, addr_t * rip, int mark) {
48     return -1;
49 }
50
51
52 int v3_init_decoder(struct guest_info * core) { 
53     return 0;
54 }
55
56
57 int v3_deinit_decoder(struct guest_info * core) {
58     return 0;
59 }
60
61
62 int v3_encode(struct guest_info * info, struct x86_instr * instr, uint8_t * instr_buf) {
63     return -1;
64 }
65
66
67 int v3_decode(struct guest_info * core, addr_t instr_ptr, struct x86_instr * instr) {
68     op_form_t form = INVALID_INSTR; 
69     int ret = 0;
70     int length = 0;
71
72
73     V3_Print("Decoding Instruction at %p\n", (void *)instr_ptr);
74
75     memset(instr, 0, sizeof(struct x86_instr));
76
77     // scan for prefixes
78     length = v3_get_prefixes((uint8_t *)instr_ptr, &(instr->prefixes));
79
80
81     // REX prefix
82     if (v3_get_vm_cpu_mode(core) == LONG) {
83         if ((*(uint8_t *)(instr_ptr + length) & 0xf0) == 0x40) {
84             *(uint8_t *)&(instr->prefixes.rex) = *(uint8_t *)(instr_ptr + length);
85             length += 1;
86         }
87     }
88
89
90     form = op_code_to_form((uint8_t *)(instr_ptr + length), &length);
91
92
93     V3_Print("\t decoded as (%s)\n", op_form_to_str(form));
94
95     if (form == INVALID_INSTR) {
96         PrintError("Could not find instruction form (%x)\n", *(uint32_t *)(instr_ptr + length));
97         return -1;
98     }
99
100     instr->op_type = op_form_to_type(form);
101
102     ret = parse_operands(core, (uint8_t *)(instr_ptr + length), instr, form);
103
104     if (ret == -1) {
105         PrintError("Could not parse instruction operands\n");
106         return -1;
107     }
108     length += ret;
109     
110
111     instr->instr_length += length;
112
113
114     v3_print_instr(instr);
115
116     return 0;
117 }
118
119
120 static int parse_operands(struct guest_info * core, uint8_t * instr_ptr, 
121                           struct x86_instr * instr, op_form_t form) {
122     // get operational mode of the guest for operand width
123     uint8_t operand_width = get_operand_width(core, instr, form);
124     uint8_t addr_width = get_addr_width(core, instr);
125     int ret = 0;
126     uint8_t * instr_start = instr_ptr;
127     
128
129     PrintDebug("\tOperand width=%d, Addr width=%d\n", operand_width, addr_width);
130
131     switch (form) {
132         case ADC_IMM2_8:
133         case ADD_IMM2_8:
134         case AND_IMM2_8:
135         case OR_IMM2_8:
136         case SUB_IMM2_8:
137         case XOR_IMM2_8:
138         case MOV_IMM2_8:
139         case ADC_IMM2:
140         case ADD_IMM2:
141         case AND_IMM2:  
142         case OR_IMM2:
143         case SUB_IMM2:
144         case XOR_IMM2: 
145         case MOV_IMM2:{
146             uint8_t reg_code = 0;
147
148             instr->dst_operand.size = operand_width;
149
150             ret = decode_rm_operand(core, instr_ptr, instr, &(instr->dst_operand), &reg_code);
151
152             if (ret == -1) {
153                 PrintError("Error decoding operand\n");
154                 return -1;
155             }
156
157             instr_ptr += ret;
158
159             instr->src_operand.type = IMM_OPERAND;
160             instr->src_operand.size = operand_width;
161
162             if (operand_width == 1) {
163                 instr->src_operand.operand = *(uint8_t *)instr_ptr;
164             } else if (operand_width == 2) {
165                 instr->src_operand.operand = *(uint16_t *)instr_ptr;
166             } else if (operand_width == 4) {
167                 instr->src_operand.operand = *(uint32_t *)instr_ptr;
168             } else {
169                 PrintError("Illegal operand width (%d)\n", operand_width);
170                 return -1;
171             }
172
173             instr_ptr += operand_width;
174
175             instr->num_operands = 2;
176
177             break;
178         }
179         case ADC_2MEM_8:
180         case ADD_2MEM_8:
181         case AND_2MEM_8:
182         case OR_2MEM_8:
183         case SUB_2MEM_8:
184         case XOR_2MEM_8:
185         case MOV_2MEM_8:
186         case ADC_2MEM:
187         case ADD_2MEM:
188         case AND_2MEM:
189         case OR_2MEM:
190         case SUB_2MEM:
191         case XOR_2MEM:
192         case MOV_2MEM: {
193             uint8_t reg_code = 0;
194
195             instr->dst_operand.size = operand_width;
196
197             ret = decode_rm_operand(core, instr_ptr, instr, &(instr->dst_operand), &reg_code);
198
199             if (ret == -1) {
200                 PrintError("Error decoding operand\n");
201                 return -1;
202             }
203
204             instr_ptr += ret;
205
206             instr->src_operand.type = REG_OPERAND;
207             instr->src_operand.size = operand_width;
208
209             decode_gpr(core, reg_code, &(instr->src_operand));
210
211             instr->num_operands = 2;
212             break;
213         }
214         case ADC_MEM2_8:
215         case ADD_MEM2_8:
216         case AND_MEM2_8:
217         case OR_MEM2_8:
218         case SUB_MEM2_8:
219         case XOR_MEM2_8:
220         case MOV_MEM2_8:
221         case ADC_MEM2:
222         case ADD_MEM2:
223         case AND_MEM2:
224         case OR_MEM2:
225         case SUB_MEM2:
226         case XOR_MEM2:
227         case MOV_MEM2: {
228             uint8_t reg_code = 0;
229             instr->src_operand.size = operand_width;
230
231             ret = decode_rm_operand(core, instr_ptr, instr, &(instr->src_operand), &reg_code);
232
233             if (ret == -1) {
234                 PrintError("Error decoding operand\n");
235                 return -1;
236             }
237
238             instr_ptr += ret;
239
240             instr->dst_operand.size = operand_width;
241             instr->dst_operand.type = REG_OPERAND;
242             decode_gpr(core, reg_code, &(instr->dst_operand));
243
244             instr->num_operands = 2;
245
246             break;
247         }
248         case ADC_IMM2SX_8:
249         case ADD_IMM2SX_8:
250         case AND_IMM2SX_8:
251         case OR_IMM2SX_8:
252         case SUB_IMM2SX_8:
253         case XOR_IMM2SX_8: {
254             uint8_t reg_code = 0;
255             instr->src_operand.size = operand_width;
256
257             ret = decode_rm_operand(core, instr_ptr, instr, &(instr->src_operand), &reg_code);
258
259             if (ret == -1) {
260                 PrintError("Error decoding operand\n");
261                 return -1;
262             }
263
264             instr_ptr += ret;
265
266             instr->src_operand.type = IMM_OPERAND;
267             instr->src_operand.size = operand_width;
268             instr->src_operand.operand = *(sint8_t *)instr_ptr;  // sign extend.
269
270             instr_ptr += 1;
271
272             instr->num_operands = 2;
273
274             break;
275         }
276         case MOVS:
277         case MOVS_8: {
278             instr->is_str_op = 1;
279             
280             if (instr->prefixes.rep == 1) {
281                 instr->str_op_length = MASK(core->vm_regs.rcx, operand_width);
282             } else {
283                 instr->str_op_length = 1;
284             }
285
286             // Source: DS:(E)SI
287             // Destination: ES:(E)DI
288
289             instr->src_operand.type = MEM_OPERAND;
290             instr->src_operand.size = operand_width;
291             instr->src_operand.operand = get_addr_linear(core,  MASK(core->vm_regs.rsi, addr_width), &(core->segments.ds));
292
293             instr->dst_operand.type = MEM_OPERAND;
294             instr->dst_operand.size = operand_width;
295             instr->dst_operand.operand = get_addr_linear(core, MASK(core->vm_regs.rdi, addr_width), &(core->segments.es));
296
297             instr->num_operands = 2;
298
299             break;
300
301             case MOV_2CR: {
302                 uint8_t reg_code = 0;
303
304                 instr->src_operand.size = operand_width;
305
306                 ret = decode_rm_operand(core, instr_ptr, instr, &(instr->src_operand),
307                                         &reg_code);
308
309                 if (ret == -1) {
310                     PrintError("Error decoding operand for (%s)\n", op_form_to_str(form));
311                     return -1;
312                 }
313                 
314                 instr_ptr += ret;
315
316                 instr->dst_operand.type = REG_OPERAND;
317                 instr->dst_operand.size = operand_width;
318                 decode_cr(core, reg_code, &(instr->dst_operand));
319
320                 instr->num_operands = 2;
321                 break;
322             }
323             case MOV_CR2: {
324                 uint8_t reg_code = 0;
325
326                 instr->dst_operand.size = operand_width;
327
328                 ret = decode_rm_operand(core, instr_ptr, instr, &(instr->dst_operand),
329                                         &reg_code);
330
331                 if (ret == -1) {
332                     PrintError("Error decoding operand for (%s)\n", op_form_to_str(form));
333                     return -1;
334                 }
335
336                 instr_ptr += ret;
337                 
338                 instr->src_operand.type = REG_OPERAND;
339                 instr->src_operand.size = operand_width;
340                 decode_cr(core, reg_code, &(instr->src_operand));
341
342                 instr->num_operands = 2;
343                 break;
344             }
345             case STOS:
346             case STOS_8: {
347                 instr->is_str_op = 1;
348                 
349                 if (instr->prefixes.rep == 1) {
350                     instr->str_op_length = MASK(core->vm_regs.rcx, operand_width);
351                 } else {
352                     instr->str_op_length = 1;
353                 }
354                 
355                 instr->src_operand.size = operand_width;
356                 instr->src_operand.type = REG_OPERAND;
357                 instr->src_operand.operand = (addr_t)&(core->vm_regs.rax);
358
359                 instr->dst_operand.type = MEM_OPERAND;
360                 instr->dst_operand.size = operand_width;
361                 instr->dst_operand.operand = get_addr_linear(core, MASK(core->vm_regs.rdi, addr_width), &(core->segments.es));
362
363                 instr->num_operands = 2;
364
365                 break;
366             }
367             case INVLPG: {
368                 uint8_t reg_code = 0;
369
370                 // We use the dst operand here to maintain bug-for-bug compatibility with XED
371
372                 instr->dst_operand.size = operand_width;
373
374                 ret = decode_rm_operand(core, instr_ptr, instr, &(instr->dst_operand), &reg_code);
375
376                 if (ret == -1) {
377                     PrintError("Error decoding operand for (%s)\n", op_form_to_str(form));
378                     return -1;
379                 }
380
381                 instr_ptr += ret;
382
383                 instr->num_operands = 1;
384                 break;
385             }
386             case CLTS: {
387                 // no operands. 
388                 break;
389
390             }
391         }
392         default:
393             PrintError("Invalid Instruction form: %s\n", op_form_to_str(form));
394             return -1;
395     }
396
397     return (instr_ptr - instr_start);
398 }
399
400
401 static v3_op_type_t op_form_to_type(op_form_t form) { 
402     switch (form) {
403         case LMSW:
404             return V3_OP_LMSW;
405         case SMSW:
406             return V3_OP_SMSW;
407         case CLTS:
408             return V3_OP_CLTS;
409         case INVLPG:
410             return V3_OP_INVLPG;
411
412         case MOV_CR2:
413             return V3_OP_MOVCR2;
414         case MOV_2CR:
415             return V3_OP_MOV2CR;
416
417
418         case MOV_MEM2_8:
419         case MOV_MEM2:
420         case MOV_2MEM_8:
421         case MOV_2MEM:
422         case MOV_MEM2AL_8:
423         case MOV_MEM2AX:
424         case MOV_AL2MEM_8:
425         case MOV_AX2MEM:
426         case MOV_IMM2_8:
427         case MOV_IMM2:
428             return V3_OP_MOV;
429
430         case MOVS_8:
431         case MOVS:
432             return V3_OP_MOVS;
433
434         case MOVSX_8:
435         case MOVSX:
436             return V3_OP_MOVSX;
437
438         case MOVZX_8:
439         case MOVZX:
440             return V3_OP_MOVZX;
441
442
443             
444         case ADC_2MEM_8:
445         case ADC_2MEM:
446         case ADC_MEM2_8:
447         case ADC_MEM2:
448         case ADC_IMM2_8:
449         case ADC_IMM2:
450         case ADC_IMM2SX_8:
451             return V3_OP_ADC;
452
453
454         case ADD_2MEM_8:
455         case ADD_2MEM:
456         case ADD_MEM2_8:
457         case ADD_MEM2:
458         case ADD_IMM2_8:
459         case ADD_IMM2:
460         case ADD_IMM2SX_8:
461             return V3_OP_ADD;
462
463         case AND_MEM2_8:
464         case AND_MEM2:
465         case AND_2MEM_8:
466         case AND_2MEM:
467         case AND_IMM2_8:
468         case AND_IMM2:
469         case AND_IMM2SX_8:
470             return V3_OP_AND;
471
472         case OR_2MEM_8:
473         case OR_2MEM:
474         case OR_MEM2_8:
475         case OR_MEM2:
476         case OR_IMM2_8:
477         case OR_IMM2:
478         case OR_IMM2SX_8:
479             return V3_OP_OR;
480
481         case SUB_2MEM_8:
482         case SUB_2MEM:
483         case SUB_MEM2_8:
484         case SUB_MEM2:
485         case SUB_IMM2_8:
486         case SUB_IMM2:
487         case SUB_IMM2SX_8:
488             return V3_OP_SUB;
489
490         case XOR_2MEM_8:
491         case XOR_2MEM:
492         case XOR_MEM2_8:
493         case XOR_MEM2:
494         case XOR_IMM2_8:
495         case XOR_IMM2:
496         case XOR_IMM2SX_8:
497             return V3_OP_XOR;
498
499         case INC_8:
500         case INC:
501             return V3_OP_INC;
502
503         case DEC_8:
504         case DEC:
505             return V3_OP_DEC;
506
507         case NEG_8:
508         case NEG: 
509             return V3_OP_NEG;
510
511         case NOT_8:
512         case NOT:
513             return V3_OP_NOT;
514
515         case XCHG_8:
516         case XCHG:
517             return V3_OP_XCHG;
518             
519         case SETB:
520             return V3_OP_SETB;
521         case SETBE:
522             return V3_OP_SETBE;
523         case SETL:
524             return V3_OP_SETL;
525         case SETLE:
526             return V3_OP_SETLE;
527         case SETNB:
528             return V3_OP_SETNB;
529         case SETNBE:
530             return V3_OP_SETNBE;
531         case SETNL:
532             return V3_OP_SETNL;
533         case SETNLE:
534             return V3_OP_SETNLE;
535         case SETNO:
536             return V3_OP_SETNO;
537         case SETNP:
538             return V3_OP_SETNP;
539         case SETNS:
540             return V3_OP_SETNS;
541         case SETNZ:
542             return V3_OP_SETNZ;
543         case SETP:
544             return V3_OP_SETP;
545         case SETS:
546             return V3_OP_SETS;
547         case SETZ:
548             return V3_OP_SETZ;
549         case SETO:
550             return V3_OP_SETO;
551             
552         case STOS_8:
553         case STOS:
554             return V3_OP_STOS;
555
556         case HLT:
557         case PUSHF:
558         case POPF:
559         case MOV_DR2:
560         case MOV_2DR:
561         case MOV_SR2:
562         case MOV_2SR:
563
564         default:
565             return V3_INVALID_OP;
566
567     }
568 }