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.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
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.
14 * Author: Jack Lange <jarusl@cs.northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20 #ifdef __DECODER_TEST__
21 #include "vmm_decoder.h"
23 #include <xed/xed-interface.h>
27 #include <palacios/vmm_decoder.h>
28 #include <palacios/vmm_xed.h>
29 #include <xed/xed-interface.h>
30 #include <palacios/vm_guest.h>
31 #include <palacios/vmm.h>
36 static xed_state_t decoder_state;
38 #define GPR_REGISTER 0
39 #define SEGMENT_REGISTER 1
40 #define CTRL_REGISTER 2
41 #define DEBUG_REGISTER 3
45 /* Disgusting mask hack...
46 I can't think right now, so we'll do it this way...
48 static const ullong_t mask_1 = 0x00000000000000ffLL;
49 static const ullong_t mask_2 = 0x000000000000ffffLL;
50 static const ullong_t mask_4 = 0x00000000ffffffffLL;
51 static const ullong_t mask_8 = 0xffffffffffffffffLL;
54 #define MASK(val, length) ({ \
55 ullong_t mask = 0x0LL; \
68 struct memory_operand {
76 uint_t displacement_size;
77 ullong_t displacement;
82 // This returns a pointer to a V3_OPCODE_[*] array defined in vmm_decoder.h
83 static int get_opcode(xed_iform_enum_t iform, addr_t * opcode);
85 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);
86 static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xed_instr, uint_t index, struct x86_operand * operand);
88 static int set_decoder_mode(struct guest_info * info, xed_state_t * state) {
89 switch (info->cpu_mode) {
91 if (state->mmode != XED_MACHINE_MODE_LEGACY_16) {
93 XED_MACHINE_MODE_LEGACY_16,
94 XED_ADDRESS_WIDTH_16b,
95 XED_ADDRESS_WIDTH_16b);
100 if (state->mmode != XED_MACHINE_MODE_LEGACY_32) {
101 xed_state_init(state,
102 XED_MACHINE_MODE_LEGACY_32,
103 XED_ADDRESS_WIDTH_32b,
104 XED_ADDRESS_WIDTH_32b);
108 if (state->mmode != XED_MACHINE_MODE_LONG_64) {
109 state->mmode = XED_MACHINE_MODE_LONG_64;
118 int is_flags_reg(xed_reg_enum_t xed_reg) {
133 xed_state_zero(&decoder_state);
139 int v3_basic_mem_decode(struct guest_info * info, addr_t instr_ptr, struct basic_instr_info * instr_info) {
140 xed_decoded_inst_t xed_instr;
141 xed_error_enum_t xed_error;
144 if (set_decoder_mode(info, &decoder_state) == -1) {
145 PrintError("Could not set decoder mode\n");
150 xed_decoded_inst_zero_set_mode(&xed_instr, &decoder_state);
152 xed_error = xed_decode(&xed_instr,
153 REINTERPRET_CAST(const xed_uint8_t *, instr_ptr),
154 XED_MAX_INSTRUCTION_BYTES);
156 if (xed_error != XED_ERROR_NONE) {
157 PrintError("Xed error: %s\n", xed_error_enum_t2str(xed_error));
161 instr_info->instr_length = xed_decoded_inst_get_length(&xed_instr);
164 if (xed_decoded_inst_number_of_memory_operands(&xed_instr) == 0) {
165 PrintError("Tried to decode memory operation with no memory operands\n");
169 instr_info->op_size = xed_decoded_inst_get_memory_operand_length(&xed_instr, 0);
172 xed_category_enum_t cat = xed_decoded_inst_get_category(&xed_instr);
173 if (cat == XED_CATEGORY_STRINGOP) {
174 instr_info->str_op = 1;
176 instr_info->str_op = 0;
179 xed_operand_values_t * operands = xed_decoded_inst_operands(&xed_instr);
180 if (xed_operand_values_has_real_rep(operands)) {
181 instr_info->has_rep = 1;
183 instr_info->has_rep = 0;
191 int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * instr) {
192 xed_decoded_inst_t xed_instr;
193 xed_error_enum_t xed_error;
197 if (set_decoder_mode(info, &decoder_state) == -1) {
198 PrintError("Could not set decoder mode\n");
204 xed_decoded_inst_zero_set_mode(&xed_instr, &decoder_state);
206 xed_error = xed_decode(&xed_instr,
207 REINTERPRET_CAST(const xed_uint8_t *, instr_ptr),
208 XED_MAX_INSTRUCTION_BYTES);
211 if (xed_error != XED_ERROR_NONE) {
212 PrintError("Xed error: %s\n", xed_error_enum_t2str(xed_error));
216 const xed_inst_t * xi = xed_decoded_inst_inst(&xed_instr);
218 instr->instr_length = xed_decoded_inst_get_length(&xed_instr);
219 instr->num_operands = xed_decoded_inst_noperands(&xed_instr);
221 xed_iform_enum_t iform = xed_decoded_inst_get_iform_enum(&xed_instr);
224 PrintDebug("iform=%s\n", xed_iform_enum_t2str(iform));
227 if (instr->num_operands > 3) {
228 PrintDebug("Special Case Not Handled\n");
231 } else if (instr->num_operands == 3) {
232 const xed_operand_t * op = xed_inst_operand(xi, 2);
233 xed_operand_enum_t op_enum = xed_operand_name(op);
235 if ((!xed_operand_is_register(op_enum)) ||
236 (!is_flags_reg(xed_decoded_inst_get_reg(&xed_instr, op_enum)))) {
238 PrintDebug("Special Case not handled\n");
247 if (get_opcode(iform, &(instr->opcode)) == -1) {
248 PrintDebug("Could not get opcode. (iform=%s)\n", xed_iform_enum_t2str(iform));
255 //PrintDebug("Number of operands: %d\n", instr->num_operands);
256 //PrintDebug("INSTR length: %d\n", instr->instr_length);
259 if (instr->num_operands >= 1) {
260 const xed_operand_t * op = xed_inst_operand(xi, 0);
261 xed_operand_enum_t op_enum = xed_operand_name(op);
263 struct x86_operand * v3_op = NULL;
265 if (xed_operand_written(op)) {
266 v3_op = &(instr->dst_operand);
268 v3_op = &(instr->src_operand);
272 if (xed_operand_is_register(op_enum)) {
273 xed_reg_enum_t xed_reg = xed_decoded_inst_get_reg(&xed_instr, op_enum);
274 int v3_reg_type = xed_reg_to_v3_reg(info,
279 if (v3_reg_type == -1) {
280 PrintError("First operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
281 v3_op->type = INVALID_OPERAND;
283 } else if (v3_reg_type == SEGMENT_REGISTER) {
284 struct v3_segment * seg_reg = (struct v3_segment *)(v3_op->operand);
285 v3_op->operand = (addr_t)&(seg_reg->selector);
288 v3_op->type = REG_OPERAND;
293 case XED_OPERAND_MEM0:
296 struct x86_operand * operand = &(instr->dst_operand);
298 if (xed_decoded_inst_mem_read(&xed_instr, 0)) {
299 operand = &(instr->src_operand);
300 } else if (xed_decoded_inst_mem_written(&xed_instr, 0)) {
301 operand = &(instr->dst_operand);
305 if (get_memory_operand(info, &xed_instr, 0, v3_op) == -1) {
306 PrintError("Could not get first memory operand\n");
312 case XED_OPERAND_MEM1:
313 case XED_OPERAND_IMM1:
315 PrintError("Illegal Operand Order\n");
319 case XED_OPERAND_IMM0:
320 case XED_OPERAND_AGEN:
321 case XED_OPERAND_PTR:
322 case XED_OPERAND_RELBR:
324 PrintError("Unhandled Operand Type\n");
332 // set second operand
333 if (instr->num_operands >= 2) {
334 const xed_operand_t * op = xed_inst_operand(xi, 1);
335 // xed_operand_type_enum_t op_type = xed_operand_type(op);
336 xed_operand_enum_t op_enum = xed_operand_name(op);
338 struct x86_operand * v3_op;
340 if (xed_operand_written(op)) {
341 v3_op = &(instr->dst_operand);
343 v3_op = &(instr->src_operand);
347 if (xed_operand_is_register(op_enum)) {
348 xed_reg_enum_t xed_reg = xed_decoded_inst_get_reg(&xed_instr, op_enum);
349 int v3_reg_type = xed_reg_to_v3_reg(info,
353 if (v3_reg_type == -1) {
354 PrintError("Second operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
355 v3_op->type = INVALID_OPERAND;
357 } else if (v3_reg_type == SEGMENT_REGISTER) {
358 struct v3_segment * seg_reg = (struct v3_segment *)(v3_op->operand);
359 v3_op->operand = (addr_t)&(seg_reg->selector);
362 v3_op->type = REG_OPERAND;
369 case XED_OPERAND_MEM0:
373 if (xed_decoded_inst_mem_read(&xed_instr, 0)) {
374 v3_op = &(instr->src_operand);
375 } else if (xed_decoded_inst_mem_written(&xed_instr, 0)) {
376 v3_op = &(instr->dst_operand);
380 if (get_memory_operand(info, &xed_instr, 0, v3_op) == -1) {
381 PrintError("Could not get first memory operand\n");
387 case XED_OPERAND_IMM0:
389 instr->src_operand.size = xed_decoded_inst_get_immediate_width(&xed_instr);
391 if (instr->src_operand.size > 4) {
392 PrintError("Unhandled 64 bit immediates\n");
395 instr->src_operand.operand = xed_decoded_inst_get_unsigned_immediate(&xed_instr);
397 instr->src_operand.type = IMM_OPERAND;
402 case XED_OPERAND_MEM1:
403 case XED_OPERAND_IMM1:
405 PrintError("Illegal Operand Order\n");
408 case XED_OPERAND_AGEN:
409 case XED_OPERAND_PTR:
410 case XED_OPERAND_RELBR:
412 PrintError("Unhandled Operand Type\n");
420 if (instr->num_operands >= 3) {
421 const xed_operand_t * op = xed_inst_operand(xi, 2);
422 // xed_operand_type_enum_t op_type = xed_operand_type(op);
423 xed_operand_enum_t op_enum = xed_operand_name(op);
425 if (xed_operand_is_register(op_enum)) {
426 xed_reg_enum_t xed_reg = xed_decoded_inst_get_reg(&xed_instr, op_enum);
427 int v3_reg_type = xed_reg_to_v3_reg(info,
429 &(instr->third_operand.operand),
430 &(instr->third_operand.size));
432 if (v3_reg_type == -1) {
433 PrintError("Third operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
434 instr->third_operand.type = INVALID_OPERAND;
436 } else if (v3_reg_type == SEGMENT_REGISTER) {
437 struct v3_segment * seg_reg = (struct v3_segment *)(instr->third_operand.operand);
438 instr->third_operand.operand = (addr_t)&(seg_reg->selector);
442 instr->third_operand.type = REG_OPERAND;
446 // PrintError("Unhandled third operand type %s\n", xed_operand_type_enum_t2str(op_type));
459 int v3_encode(struct guest_info * info, struct x86_instr * instr, char * instr_buf) {
468 static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xed_instr, uint_t op_index, struct x86_operand * operand) {
469 struct memory_operand mem_op;
475 ullong_t displacement;
476 // struct v3_segment * seg_reg;
481 memset((void*)&mem_op, '\0', sizeof(struct memory_operand));
483 xed_reg_enum_t xed_seg = xed_decoded_inst_get_seg_reg(xed_instr, op_index);
484 if (xed_seg != XED_REG_INVALID) {
485 struct v3_segment *tmp_segment;
486 if (xed_reg_to_v3_reg(info, xed_seg, (addr_t *)&tmp_segment, &(mem_op.segment_size)) == -1) {
487 PrintError("Unhandled Segment Register\n");
490 mem_op.segment = tmp_segment->base;
493 xed_reg_enum_t xed_base = xed_decoded_inst_get_base_reg(xed_instr, op_index);
494 if (xed_base != XED_REG_INVALID) {
496 if (xed_reg_to_v3_reg(info, xed_base, &base_reg, &(mem_op.base_size)) == -1) {
497 PrintError("Unhandled Base register\n");
500 mem_op.base = *(addr_t *)base_reg;
505 xed_reg_enum_t xed_idx = xed_decoded_inst_get_index_reg(xed_instr, op_index);
506 if ((op_index == 0) && (xed_idx != XED_REG_INVALID)) {
509 if (xed_reg_to_v3_reg(info, xed_idx, &index_reg, &(mem_op.index_size)) == -1) {
510 PrintError("Unhandled Index Register\n");
514 mem_op.index= *(addr_t *)index_reg;
516 xed_uint_t xed_scale = xed_decoded_inst_get_scale(xed_instr, op_index);
517 if (xed_scale != 0) {
518 mem_op.scale = xed_scale;
523 xed_uint_t disp_bits = xed_decoded_inst_get_memory_displacement_width(xed_instr, op_index);
525 xed_int64_t xed_disp = xed_decoded_inst_get_memory_displacement(xed_instr, op_index);
527 mem_op.displacement_size = disp_bits / 8;
528 mem_op.displacement = xed_disp;
532 operand->type = MEM_OPERAND;
533 operand->size = xed_decoded_inst_get_memory_operand_length(xed_instr, op_index);
537 PrintDebug("Struct: Seg=%x, base=%x, index=%x, scale=%x, displacement=%x\n",
538 mem_op.segment, mem_op.base, mem_op.index, mem_op.scale, mem_op.displacement);
541 seg = mem_op.segment;
542 base = MASK(mem_op.base, mem_op.base_size);
543 index = MASK(mem_op.index, mem_op.index_size);
544 scale = mem_op.scale;
545 displacement = MASK(mem_op.displacement, mem_op.displacement_size);
547 PrintDebug("Seg=%x, base=%x, index=%x, scale=%x, displacement=%x\n", seg, base, index, scale, displacement);
549 operand->operand = seg + base + (scale * index) + displacement;
554 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) {
557 case XED_REG_INVALID:
566 *v3_reg = (addr_t)&(info->vm_regs.rax);
570 *v3_reg = (addr_t)&(info->vm_regs.rax);
574 *v3_reg = (addr_t)&(info->vm_regs.rax);
578 *v3_reg = (addr_t)(&(info->vm_regs.rax)) + 1;
582 *v3_reg = (addr_t)&(info->vm_regs.rax);
587 *v3_reg = (addr_t)&(info->vm_regs.rcx);
591 *v3_reg = (addr_t)&(info->vm_regs.rcx);
595 *v3_reg = (addr_t)&(info->vm_regs.rcx);
599 *v3_reg = (addr_t)(&(info->vm_regs.rcx)) + 1;
603 *v3_reg = (addr_t)&(info->vm_regs.rcx);
608 *v3_reg = (addr_t)&(info->vm_regs.rdx);
612 *v3_reg = (addr_t)&(info->vm_regs.rdx);
616 *v3_reg = (addr_t)&(info->vm_regs.rdx);
620 *v3_reg = (addr_t)(&(info->vm_regs.rdx)) + 1;
624 *v3_reg = (addr_t)&(info->vm_regs.rdx);
629 *v3_reg = (addr_t)&(info->vm_regs.rbx);
633 *v3_reg = (addr_t)&(info->vm_regs.rbx);
637 *v3_reg = (addr_t)&(info->vm_regs.rbx);
641 *v3_reg = (addr_t)(&(info->vm_regs.rbx)) + 1;
645 *v3_reg = (addr_t)&(info->vm_regs.rbx);
651 *v3_reg = (addr_t)&(info->vm_regs.rsp);
655 *v3_reg = (addr_t)&(info->vm_regs.rsp);
659 *v3_reg = (addr_t)&(info->vm_regs.rsp);
663 *v3_reg = (addr_t)&(info->vm_regs.rsp);
668 *v3_reg = (addr_t)&(info->vm_regs.rbp);
672 *v3_reg = (addr_t)&(info->vm_regs.rbp);
676 *v3_reg = (addr_t)&(info->vm_regs.rbp);
680 *v3_reg = (addr_t)&(info->vm_regs.rbp);
687 *v3_reg = (addr_t)&(info->vm_regs.rsi);
691 *v3_reg = (addr_t)&(info->vm_regs.rsi);
695 *v3_reg = (addr_t)&(info->vm_regs.rsi);
699 *v3_reg = (addr_t)&(info->vm_regs.rsi);
705 *v3_reg = (addr_t)&(info->vm_regs.rdi);
709 *v3_reg = (addr_t)&(info->vm_regs.rdi);
713 *v3_reg = (addr_t)&(info->vm_regs.rdi);
717 *v3_reg = (addr_t)&(info->vm_regs.rdi);
726 *v3_reg = (addr_t)&(info->rip);
728 return CTRL_REGISTER;
730 *v3_reg = (addr_t)&(info->rip);
732 return CTRL_REGISTER;
734 *v3_reg = (addr_t)&(info->rip);
736 return CTRL_REGISTER;
739 *v3_reg = (addr_t)&(info->ctrl_regs.rflags);
741 return CTRL_REGISTER;
743 *v3_reg = (addr_t)&(info->ctrl_regs.rflags);
745 return CTRL_REGISTER;
747 *v3_reg = (addr_t)&(info->ctrl_regs.rflags);
749 return CTRL_REGISTER;
752 *v3_reg = (addr_t)&(info->ctrl_regs.cr0);
754 return CTRL_REGISTER;
756 *v3_reg = (addr_t)&(info->ctrl_regs.cr2);
758 return CTRL_REGISTER;
760 *v3_reg = (addr_t)&(info->ctrl_regs.cr3);
762 return CTRL_REGISTER;
764 *v3_reg = (addr_t)&(info->ctrl_regs.cr4);
766 return CTRL_REGISTER;
768 *v3_reg = (addr_t)&(info->ctrl_regs.cr8);
770 return CTRL_REGISTER;
792 *v3_reg = (addr_t)&(info->segments.cs);
793 return SEGMENT_REGISTER;
795 *v3_reg = (addr_t)&(info->segments.ds);
796 return SEGMENT_REGISTER;
798 *v3_reg = (addr_t)&(info->segments.es);
799 return SEGMENT_REGISTER;
801 *v3_reg = (addr_t)&(info->segments.ss);
802 return SEGMENT_REGISTER;
804 *v3_reg = (addr_t)&(info->segments.fs);
805 return SEGMENT_REGISTER;
807 *v3_reg = (addr_t)&(info->segments.gs);
808 return SEGMENT_REGISTER;
815 PrintError("Segment selector operand... Don't know how to handle this...\n");
918 case XED_REG_STACKPUSH:
919 case XED_REG_STACKPOP:
925 case XED_REG_X87CONTROL:
926 case XED_REG_X87STATUS:
929 case XED_REG_X87PUSH:
931 case XED_REG_X87POP2:
966 static int get_opcode(xed_iform_enum_t iform, addr_t * opcode) {
969 case XED_IFORM_MOV_CR_GPR64_CR:
970 case XED_IFORM_MOV_CR_GPR32_CR:
971 *opcode = (addr_t)&V3_OPCODE_MOVCR2;
974 case XED_IFORM_MOV_CR_CR_GPR64:
975 case XED_IFORM_MOV_CR_CR_GPR32:
976 *opcode = (addr_t)&V3_OPCODE_MOV2CR;
980 case XED_IFORM_LMSW_GPR16:
981 *opcode = (addr_t)&V3_OPCODE_LMSW;
985 *opcode = (addr_t)&V3_OPCODE_CLTS;