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.


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