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.


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