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.


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