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>
40 #define PrintDebug(fmt, args...)
45 static xed_state_t decoder_state;
47 #define GPR_REGISTER 0
48 #define SEGMENT_REGISTER 1
49 #define CTRL_REGISTER 2
50 #define DEBUG_REGISTER 3
54 /* Disgusting mask hack...
55 I can't think right now, so we'll do it this way...
57 static const ullong_t mask_1 = 0x00000000000000ffLL;
58 static const ullong_t mask_2 = 0x000000000000ffffLL;
59 static const ullong_t mask_4 = 0x00000000ffffffffLL;
60 static const ullong_t mask_8 = 0xffffffffffffffffLL;
63 #define MASK(val, length) ({ \
64 ullong_t mask = 0x0LL; \
77 struct memory_operand {
85 uint_t displacement_size;
86 ullong_t displacement;
91 // This returns a pointer to a V3_OPCODE_[*] array defined in vmm_decoder.h
92 static int get_opcode(xed_iform_enum_t iform, addr_t * opcode);
94 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);
95 static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xed_instr, uint_t index, struct x86_operand * operand);
97 static int set_decoder_mode(struct guest_info * info, xed_state_t * state) {
98 switch (info->cpu_mode) {
100 if (state->mmode != XED_MACHINE_MODE_LEGACY_16) {
101 xed_state_init(state,
102 XED_MACHINE_MODE_LEGACY_16,
103 XED_ADDRESS_WIDTH_16b,
104 XED_ADDRESS_WIDTH_16b);
110 if (state->mmode != XED_MACHINE_MODE_LEGACY_32) {
111 xed_state_init(state,
112 XED_MACHINE_MODE_LEGACY_32,
113 XED_ADDRESS_WIDTH_32b,
114 XED_ADDRESS_WIDTH_32b);
118 if (state->mmode != XED_MACHINE_MODE_LONG_64) {
119 state->mmode = XED_MACHINE_MODE_LONG_64;
123 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
129 static int is_flags_reg(xed_reg_enum_t xed_reg) {
142 int v3_init_decoder() {
144 xed_state_zero(&decoder_state);
150 int v3_basic_mem_decode(struct guest_info * info, addr_t instr_ptr, struct basic_instr_info * instr_info) {
151 xed_decoded_inst_t xed_instr;
152 xed_error_enum_t xed_error;
155 if (set_decoder_mode(info, &decoder_state) == -1) {
156 PrintError("Could not set decoder mode\n");
161 xed_decoded_inst_zero_set_mode(&xed_instr, &decoder_state);
163 xed_error = xed_decode(&xed_instr,
164 REINTERPRET_CAST(const xed_uint8_t *, instr_ptr),
165 XED_MAX_INSTRUCTION_BYTES);
167 if (xed_error != XED_ERROR_NONE) {
168 PrintError("Xed error: %s\n", xed_error_enum_t2str(xed_error));
172 instr_info->instr_length = xed_decoded_inst_get_length(&xed_instr);
175 if (xed_decoded_inst_number_of_memory_operands(&xed_instr) == 0) {
176 PrintError("Tried to decode memory operation with no memory operands\n");
180 instr_info->op_size = xed_decoded_inst_get_memory_operand_length(&xed_instr, 0);
183 xed_category_enum_t cat = xed_decoded_inst_get_category(&xed_instr);
184 if (cat == XED_CATEGORY_STRINGOP) {
185 instr_info->str_op = 1;
187 instr_info->str_op = 0;
190 xed_operand_values_t * operands = xed_decoded_inst_operands(&xed_instr);
191 if (xed_operand_values_has_real_rep(operands)) {
192 instr_info->has_rep = 1;
194 instr_info->has_rep = 0;
202 int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * instr) {
203 xed_decoded_inst_t xed_instr;
204 xed_error_enum_t xed_error;
208 if (set_decoder_mode(info, &decoder_state) == -1) {
209 PrintError("Could not set decoder mode\n");
215 xed_decoded_inst_zero_set_mode(&xed_instr, &decoder_state);
217 xed_error = xed_decode(&xed_instr,
218 REINTERPRET_CAST(const xed_uint8_t *, instr_ptr),
219 XED_MAX_INSTRUCTION_BYTES);
222 if (xed_error != XED_ERROR_NONE) {
223 PrintError("Xed error: %s\n", xed_error_enum_t2str(xed_error));
227 const xed_inst_t * xi = xed_decoded_inst_inst(&xed_instr);
229 instr->instr_length = xed_decoded_inst_get_length(&xed_instr);
230 instr->num_operands = xed_decoded_inst_noperands(&xed_instr);
232 xed_iform_enum_t iform = xed_decoded_inst_get_iform_enum(&xed_instr);
235 PrintDebug("iform=%s\n", xed_iform_enum_t2str(iform));
238 if (instr->num_operands > 3) {
239 PrintDebug("Special Case Not Handled\n");
242 } else if (instr->num_operands == 3) {
243 const xed_operand_t * op = xed_inst_operand(xi, 2);
244 xed_operand_enum_t op_enum = xed_operand_name(op);
246 if ((!xed_operand_is_register(op_enum)) ||
247 (!is_flags_reg(xed_decoded_inst_get_reg(&xed_instr, op_enum)))) {
249 PrintDebug("Special Case not handled\n");
258 if (get_opcode(iform, &(instr->opcode)) == -1) {
259 PrintDebug("Could not get opcode. (iform=%s)\n", xed_iform_enum_t2str(iform));
266 //PrintDebug("Number of operands: %d\n", instr->num_operands);
267 //PrintDebug("INSTR length: %d\n", instr->instr_length);
270 if (instr->num_operands >= 1) {
271 const xed_operand_t * op = xed_inst_operand(xi, 0);
272 xed_operand_enum_t op_enum = xed_operand_name(op);
274 struct x86_operand * v3_op = NULL;
276 if (xed_operand_written(op)) {
277 v3_op = &(instr->dst_operand);
279 v3_op = &(instr->src_operand);
283 if (xed_operand_is_register(op_enum)) {
284 xed_reg_enum_t xed_reg = xed_decoded_inst_get_reg(&xed_instr, op_enum);
285 int v3_reg_type = xed_reg_to_v3_reg(info,
290 if (v3_reg_type == -1) {
291 PrintError("First operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
292 v3_op->type = INVALID_OPERAND;
294 } else if (v3_reg_type == SEGMENT_REGISTER) {
295 struct v3_segment * seg_reg = (struct v3_segment *)(v3_op->operand);
296 v3_op->operand = (addr_t)&(seg_reg->selector);
299 v3_op->type = REG_OPERAND;
304 case XED_OPERAND_MEM0:
307 struct x86_operand * operand = &(instr->dst_operand);
309 if (xed_decoded_inst_mem_read(&xed_instr, 0)) {
310 operand = &(instr->src_operand);
311 } else if (xed_decoded_inst_mem_written(&xed_instr, 0)) {
312 operand = &(instr->dst_operand);
316 if (get_memory_operand(info, &xed_instr, 0, v3_op) == -1) {
317 PrintError("Could not get first memory operand\n");
323 case XED_OPERAND_MEM1:
324 case XED_OPERAND_IMM1:
326 PrintError("Illegal Operand Order\n");
330 case XED_OPERAND_IMM0:
331 case XED_OPERAND_AGEN:
332 case XED_OPERAND_PTR:
333 case XED_OPERAND_RELBR:
335 PrintError("Unhandled Operand Type\n");
343 // set second operand
344 if (instr->num_operands >= 2) {
345 const xed_operand_t * op = xed_inst_operand(xi, 1);
346 // xed_operand_type_enum_t op_type = xed_operand_type(op);
347 xed_operand_enum_t op_enum = xed_operand_name(op);
349 struct x86_operand * v3_op;
351 if (xed_operand_written(op)) {
352 v3_op = &(instr->dst_operand);
354 v3_op = &(instr->src_operand);
358 if (xed_operand_is_register(op_enum)) {
359 xed_reg_enum_t xed_reg = xed_decoded_inst_get_reg(&xed_instr, op_enum);
360 int v3_reg_type = xed_reg_to_v3_reg(info,
364 if (v3_reg_type == -1) {
365 PrintError("Second operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
366 v3_op->type = INVALID_OPERAND;
368 } else if (v3_reg_type == SEGMENT_REGISTER) {
369 struct v3_segment * seg_reg = (struct v3_segment *)(v3_op->operand);
370 v3_op->operand = (addr_t)&(seg_reg->selector);
373 v3_op->type = REG_OPERAND;
380 case XED_OPERAND_MEM0:
384 if (xed_decoded_inst_mem_read(&xed_instr, 0)) {
385 v3_op = &(instr->src_operand);
386 } else if (xed_decoded_inst_mem_written(&xed_instr, 0)) {
387 v3_op = &(instr->dst_operand);
391 if (get_memory_operand(info, &xed_instr, 0, v3_op) == -1) {
392 PrintError("Could not get first memory operand\n");
398 case XED_OPERAND_IMM0:
400 instr->src_operand.size = xed_decoded_inst_get_immediate_width(&xed_instr);
402 if (instr->src_operand.size > 4) {
403 PrintError("Unhandled 64 bit immediates\n");
406 instr->src_operand.operand = xed_decoded_inst_get_unsigned_immediate(&xed_instr);
408 instr->src_operand.type = IMM_OPERAND;
413 case XED_OPERAND_MEM1:
414 case XED_OPERAND_IMM1:
416 PrintError("Illegal Operand Order\n");
419 case XED_OPERAND_AGEN:
420 case XED_OPERAND_PTR:
421 case XED_OPERAND_RELBR:
423 PrintError("Unhandled Operand Type\n");
431 if (instr->num_operands >= 3) {
432 const xed_operand_t * op = xed_inst_operand(xi, 2);
433 // xed_operand_type_enum_t op_type = xed_operand_type(op);
434 xed_operand_enum_t op_enum = xed_operand_name(op);
436 if (xed_operand_is_register(op_enum)) {
437 xed_reg_enum_t xed_reg = xed_decoded_inst_get_reg(&xed_instr, op_enum);
438 int v3_reg_type = xed_reg_to_v3_reg(info,
440 &(instr->third_operand.operand),
441 &(instr->third_operand.size));
443 if (v3_reg_type == -1) {
444 PrintError("Third operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
445 instr->third_operand.type = INVALID_OPERAND;
447 } else if (v3_reg_type == SEGMENT_REGISTER) {
448 struct v3_segment * seg_reg = (struct v3_segment *)(instr->third_operand.operand);
449 instr->third_operand.operand = (addr_t)&(seg_reg->selector);
453 instr->third_operand.type = REG_OPERAND;
457 // PrintError("Unhandled third operand type %s\n", xed_operand_type_enum_t2str(op_type));
470 int v3_encode(struct guest_info * info, struct x86_instr * instr, char * instr_buf) {
479 static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xed_instr, uint_t op_index, struct x86_operand * operand) {
480 struct memory_operand mem_op;
486 ullong_t displacement;
487 // struct v3_segment * seg_reg;
492 memset((void*)&mem_op, '\0', sizeof(struct memory_operand));
494 xed_reg_enum_t xed_seg = xed_decoded_inst_get_seg_reg(xed_instr, op_index);
495 if (xed_seg != XED_REG_INVALID) {
496 struct v3_segment *tmp_segment;
497 if (xed_reg_to_v3_reg(info, xed_seg, (addr_t *)&tmp_segment, &(mem_op.segment_size)) == -1) {
498 PrintError("Unhandled Segment Register\n");
501 mem_op.segment = tmp_segment->base;
504 xed_reg_enum_t xed_base = xed_decoded_inst_get_base_reg(xed_instr, op_index);
505 if (xed_base != XED_REG_INVALID) {
507 if (xed_reg_to_v3_reg(info, xed_base, &base_reg, &(mem_op.base_size)) == -1) {
508 PrintError("Unhandled Base register\n");
511 mem_op.base = *(addr_t *)base_reg;
516 xed_reg_enum_t xed_idx = xed_decoded_inst_get_index_reg(xed_instr, op_index);
517 if ((op_index == 0) && (xed_idx != XED_REG_INVALID)) {
520 if (xed_reg_to_v3_reg(info, xed_idx, &index_reg, &(mem_op.index_size)) == -1) {
521 PrintError("Unhandled Index Register\n");
525 mem_op.index= *(addr_t *)index_reg;
527 xed_uint_t xed_scale = xed_decoded_inst_get_scale(xed_instr, op_index);
528 if (xed_scale != 0) {
529 mem_op.scale = xed_scale;
534 xed_uint_t disp_bits = xed_decoded_inst_get_memory_displacement_width(xed_instr, op_index);
536 xed_int64_t xed_disp = xed_decoded_inst_get_memory_displacement(xed_instr, op_index);
538 mem_op.displacement_size = disp_bits / 8;
539 mem_op.displacement = xed_disp;
543 operand->type = MEM_OPERAND;
544 operand->size = xed_decoded_inst_get_memory_operand_length(xed_instr, op_index);
548 PrintDebug("Struct: Seg=%x, base=%x, index=%x, scale=%x, displacement=%x\n",
549 mem_op.segment, mem_op.base, mem_op.index, mem_op.scale, mem_op.displacement);
552 seg = mem_op.segment;
553 base = MASK(mem_op.base, mem_op.base_size);
554 index = MASK(mem_op.index, mem_op.index_size);
555 scale = mem_op.scale;
556 displacement = MASK(mem_op.displacement, mem_op.displacement_size);
558 PrintDebug("Seg=%x, base=%x, index=%x, scale=%x, displacement=%x\n", seg, base, index, scale, displacement);
560 operand->operand = seg + base + (scale * index) + displacement;
565 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) {
568 case XED_REG_INVALID:
577 *v3_reg = (addr_t)&(info->vm_regs.rax);
581 *v3_reg = (addr_t)&(info->vm_regs.rax);
585 *v3_reg = (addr_t)&(info->vm_regs.rax);
589 *v3_reg = (addr_t)(&(info->vm_regs.rax)) + 1;
593 *v3_reg = (addr_t)&(info->vm_regs.rax);
598 *v3_reg = (addr_t)&(info->vm_regs.rcx);
602 *v3_reg = (addr_t)&(info->vm_regs.rcx);
606 *v3_reg = (addr_t)&(info->vm_regs.rcx);
610 *v3_reg = (addr_t)(&(info->vm_regs.rcx)) + 1;
614 *v3_reg = (addr_t)&(info->vm_regs.rcx);
619 *v3_reg = (addr_t)&(info->vm_regs.rdx);
623 *v3_reg = (addr_t)&(info->vm_regs.rdx);
627 *v3_reg = (addr_t)&(info->vm_regs.rdx);
631 *v3_reg = (addr_t)(&(info->vm_regs.rdx)) + 1;
635 *v3_reg = (addr_t)&(info->vm_regs.rdx);
640 *v3_reg = (addr_t)&(info->vm_regs.rbx);
644 *v3_reg = (addr_t)&(info->vm_regs.rbx);
648 *v3_reg = (addr_t)&(info->vm_regs.rbx);
652 *v3_reg = (addr_t)(&(info->vm_regs.rbx)) + 1;
656 *v3_reg = (addr_t)&(info->vm_regs.rbx);
662 *v3_reg = (addr_t)&(info->vm_regs.rsp);
666 *v3_reg = (addr_t)&(info->vm_regs.rsp);
670 *v3_reg = (addr_t)&(info->vm_regs.rsp);
674 *v3_reg = (addr_t)&(info->vm_regs.rsp);
679 *v3_reg = (addr_t)&(info->vm_regs.rbp);
683 *v3_reg = (addr_t)&(info->vm_regs.rbp);
687 *v3_reg = (addr_t)&(info->vm_regs.rbp);
691 *v3_reg = (addr_t)&(info->vm_regs.rbp);
698 *v3_reg = (addr_t)&(info->vm_regs.rsi);
702 *v3_reg = (addr_t)&(info->vm_regs.rsi);
706 *v3_reg = (addr_t)&(info->vm_regs.rsi);
710 *v3_reg = (addr_t)&(info->vm_regs.rsi);
716 *v3_reg = (addr_t)&(info->vm_regs.rdi);
720 *v3_reg = (addr_t)&(info->vm_regs.rdi);
724 *v3_reg = (addr_t)&(info->vm_regs.rdi);
728 *v3_reg = (addr_t)&(info->vm_regs.rdi);
737 *v3_reg = (addr_t)&(info->rip);
739 return CTRL_REGISTER;
741 *v3_reg = (addr_t)&(info->rip);
743 return CTRL_REGISTER;
745 *v3_reg = (addr_t)&(info->rip);
747 return CTRL_REGISTER;
750 *v3_reg = (addr_t)&(info->ctrl_regs.rflags);
752 return CTRL_REGISTER;
754 *v3_reg = (addr_t)&(info->ctrl_regs.rflags);
756 return CTRL_REGISTER;
758 *v3_reg = (addr_t)&(info->ctrl_regs.rflags);
760 return CTRL_REGISTER;
763 *v3_reg = (addr_t)&(info->ctrl_regs.cr0);
765 return CTRL_REGISTER;
767 *v3_reg = (addr_t)&(info->ctrl_regs.cr2);
769 return CTRL_REGISTER;
771 *v3_reg = (addr_t)&(info->ctrl_regs.cr3);
773 return CTRL_REGISTER;
775 *v3_reg = (addr_t)&(info->ctrl_regs.cr4);
777 return CTRL_REGISTER;
779 *v3_reg = (addr_t)&(info->ctrl_regs.cr8);
781 return CTRL_REGISTER;
803 *v3_reg = (addr_t)&(info->segments.cs);
804 return SEGMENT_REGISTER;
806 *v3_reg = (addr_t)&(info->segments.ds);
807 return SEGMENT_REGISTER;
809 *v3_reg = (addr_t)&(info->segments.es);
810 return SEGMENT_REGISTER;
812 *v3_reg = (addr_t)&(info->segments.ss);
813 return SEGMENT_REGISTER;
815 *v3_reg = (addr_t)&(info->segments.fs);
816 return SEGMENT_REGISTER;
818 *v3_reg = (addr_t)&(info->segments.gs);
819 return SEGMENT_REGISTER;
826 PrintError("Segment selector operand... Don't know how to handle this...\n");
929 case XED_REG_STACKPUSH:
930 case XED_REG_STACKPOP:
936 case XED_REG_X87CONTROL:
937 case XED_REG_X87STATUS:
940 case XED_REG_X87PUSH:
942 case XED_REG_X87POP2:
977 static int get_opcode(xed_iform_enum_t iform, addr_t * opcode) {
980 case XED_IFORM_MOV_CR_GPR64_CR:
981 case XED_IFORM_MOV_CR_GPR32_CR:
982 *opcode = (addr_t)&V3_OPCODE_MOVCR2;
985 case XED_IFORM_MOV_CR_CR_GPR64:
986 case XED_IFORM_MOV_CR_CR_GPR32:
987 *opcode = (addr_t)&V3_OPCODE_MOV2CR;
991 case XED_IFORM_LMSW_GPR16:
992 *opcode = (addr_t)&V3_OPCODE_LMSW;
996 *opcode = (addr_t)&V3_OPCODE_CLTS;