X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_xed.c;h=843cc79f84bf05887f091b81900c5b57313aef7e;hb=3027170914d45604132b62c93a7a99cbe4e35ccf;hp=eaac5bd62f927c876ecee34cf2ba51fc5c91faf2;hpb=30f2ad50ac43558e633fb5f3f40422feacc8338b;p=palacios.git diff --git a/palacios/src/palacios/vmm_xed.c b/palacios/src/palacios/vmm_xed.c index eaac5bd..843cc79 100644 --- a/palacios/src/palacios/vmm_xed.c +++ b/palacios/src/palacios/vmm_xed.c @@ -35,7 +35,7 @@ -#ifndef DEBUG_XED +#ifndef V3_CONFIG_DEBUG_DECODER #undef PrintDebug #define PrintDebug(fmt, args...) #endif @@ -102,7 +102,7 @@ static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, a static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xed_instr, uint_t index, struct x86_operand * operand); static int set_decoder_mode(struct guest_info * info, xed_state_t * state) { - switch (info->cpu_mode) { + switch (v3_get_vm_cpu_mode(info)) { case REAL: if (state->mmode != XED_MACHINE_MODE_LEGACY_16) { xed_state_init(state, @@ -130,7 +130,7 @@ static int set_decoder_mode(struct guest_info * info, xed_state_t * state) { break; case LONG: if (state->mmode != XED_MACHINE_MODE_LONG_64) { - PrintDebug("Setting decoder to long mode\n"); + PrintDebug(info->vm_info, info, "Setting decoder to long mode\n"); // state->mmode = XED_MACHINE_MODE_LONG_64; //xed_state_set_machine_mode(state, XED_MACHINE_MODE_LONG_64); xed_state_init(state, @@ -140,7 +140,7 @@ static int set_decoder_mode(struct guest_info * info, xed_state_t * state) { } break; default: - PrintError("Unsupported CPU mode: %d\n", info->cpu_mode); + PrintError(info->vm_info, info, "Unsupported CPU mode: %d\n", info->cpu_mode); return -1; } return 0; @@ -167,6 +167,12 @@ int v3_init_decoder(struct guest_info * info) { } xed_state_t * decoder_state = (xed_state_t *)V3_Malloc(sizeof(xed_state_t)); + + if (!decoder_state) { + PrintError(info->vm_info, info, "Cannot allocate in initializing decoder\n"); + return -1; + } + xed_state_zero(decoder_state); xed_state_init(decoder_state, XED_MACHINE_MODE_LEGACY_32, @@ -180,76 +186,38 @@ int v3_init_decoder(struct guest_info * info) { -int v3_basic_mem_decode(struct guest_info * info, addr_t instr_ptr, struct basic_instr_info * instr_info) { - xed_decoded_inst_t xed_instr; - xed_error_enum_t xed_error; - - - if (set_decoder_mode(info, info->decoder_state) == -1) { - PrintError("Could not set decoder mode\n"); - return -1; - } - - - xed_decoded_inst_zero_set_mode(&xed_instr, info->decoder_state); - - xed_error = xed_decode(&xed_instr, - REINTERPRET_CAST(const xed_uint8_t *, instr_ptr), - XED_MAX_INSTRUCTION_BYTES); - - if (xed_error != XED_ERROR_NONE) { - PrintError("Xed error: %s\n", xed_error_enum_t2str(xed_error)); - return -1; - } - - instr_info->instr_length = xed_decoded_inst_get_length(&xed_instr); - - - if (xed_decoded_inst_number_of_memory_operands(&xed_instr) == 0) { - PrintError("Tried to decode memory operation with no memory operands\n"); - return -1; - } - - instr_info->op_size = xed_decoded_inst_get_memory_operand_length(&xed_instr, 0); - - - xed_category_enum_t cat = xed_decoded_inst_get_category(&xed_instr); - if (cat == XED_CATEGORY_STRINGOP) { - instr_info->str_op = 1; - } else { - instr_info->str_op = 0; - } - - xed_operand_values_t * operands = xed_decoded_inst_operands(&xed_instr); - if (xed_operand_values_has_real_rep(operands)) { - instr_info->has_rep = 1; - } else { - instr_info->has_rep = 0; - } +int v3_deinit_decoder(struct guest_info * core) { + V3_Free(core->decoder_state); return 0; } + + static int decode_string_op(struct guest_info * info, xed_decoded_inst_t * xed_instr, const xed_inst_t * xi, struct x86_instr * instr) { - PrintDebug("String operation\n"); + PrintDebug(info->vm_info, info, "String operation\n"); if (instr->op_type == V3_OP_MOVS) { instr->num_operands = 2; if (get_memory_operand(info, xed_instr, 0, &(instr->dst_operand)) == -1) { - PrintError("Could not get Destination memory operand\n"); + PrintError(info->vm_info, info, "Could not get Destination memory operand\n"); return -1; } + if (get_memory_operand(info, xed_instr, 1, &(instr->src_operand)) == -1) { - PrintError("Could not get Source memory operand\n"); + PrintError(info->vm_info, info, "Could not get Source memory operand\n"); return -1; } + instr->dst_operand.write = 1; + instr->src_operand.read = 1; + if (instr->prefixes.rep == 1) { addr_t reg_addr = 0; uint_t reg_length = 0; @@ -264,7 +232,7 @@ static int decode_string_op(struct guest_info * info, instr->num_operands = 2; if (get_memory_operand(info, xed_instr, 0, &(instr->dst_operand)) == -1) { - PrintError("Could not get Destination memory operand\n"); + PrintError(info->vm_info, info, "Could not get Destination memory operand\n"); return -1; } @@ -274,21 +242,74 @@ static int decode_string_op(struct guest_info * info, &(instr->src_operand.size)); instr->src_operand.type = REG_OPERAND; + instr->src_operand.read = 1; + instr->dst_operand.write = 1; + if (instr->prefixes.rep == 1) { addr_t reg_addr = 0; uint_t reg_length = 0; - xed_reg_to_v3_reg(info, xed_decoded_inst_get_reg(xed_instr, XED_OPERAND_REG1), ®_addr, ®_length); + xed_reg_to_v3_reg(info, xed_decoded_inst_get_reg(xed_instr, XED_OPERAND_REG1), + ®_addr, ®_length); instr->str_op_length = MASK(*(addr_t *)reg_addr, reg_length); } else { instr->str_op_length = 1; } } else { - PrintError("Unhandled String OP\n"); + PrintError(info->vm_info, info, "Unhandled String OP\n"); + return -1; + } + + return 0; +} + + + +int v3_disasm(struct guest_info * info, void *instr_ptr, addr_t * rip, int mark) { + char buffer[256]; + int i; + unsigned length; + xed_decoded_inst_t xed_instr; + xed_error_enum_t xed_error; + + /* disassemble the specified instruction */ + if (set_decoder_mode(info, info->decoder_state) == -1) { + PrintError(info->vm_info, info, "Could not set decoder mode\n"); + return -1; + } + + xed_decoded_inst_zero_set_mode(&xed_instr, info->decoder_state); + + xed_error = xed_decode(&xed_instr, + REINTERPRET_CAST(const xed_uint8_t *, instr_ptr), + XED_MAX_INSTRUCTION_BYTES); + + if (xed_error != XED_ERROR_NONE) { + PrintError(info->vm_info, info, "Xed error: %s\n", xed_error_enum_t2str(xed_error)); + return -1; + } + + /* obtain string representation in AT&T syntax */ + if (!xed_format_att(&xed_instr, buffer, sizeof(buffer), *rip)) { + PrintError(info->vm_info, info, "Xed error: cannot disaaemble\n"); return -1; } + /* print address, opcode bytes and the disassembled instruction */ + length = xed_decoded_inst_get_length(&xed_instr); + V3_Print(info->vm_info, info, "0x%p %c ", (void *) *rip, mark ? '*' : ' '); + for (i = 0; i < length; i++) { + unsigned char b = ((unsigned char *) instr_ptr)[i]; + V3_Print(info->vm_info, info, "%x%x ", b >> 4, b & 0xf); + } + while (i++ < 8) { + V3_Print(info->vm_info, info, " "); + } + V3_Print(info->vm_info, info, "%s\n", buffer); + + /* move on to next instruction */ + *rip += length; return 0; } @@ -298,11 +319,13 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins xed_decoded_inst_t xed_instr; xed_error_enum_t xed_error; + memset(instr, 0, sizeof(struct x86_instr)); + v3_get_prefixes((uchar_t *)instr_ptr, &(instr->prefixes)); if (set_decoder_mode(info, info->decoder_state) == -1) { - PrintError("Could not set decoder mode\n"); + PrintError(info->vm_info, info, "Could not set decoder mode\n"); return -1; } @@ -314,7 +337,7 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins if (xed_error != XED_ERROR_NONE) { - PrintError("Xed error: %s\n", xed_error_enum_t2str(xed_error)); + PrintError(info->vm_info, info, "Xed error: %s\n", xed_error_enum_t2str(xed_error)); return -1; } @@ -325,15 +348,15 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins xed_iform_enum_t iform = xed_decoded_inst_get_iform_enum(&xed_instr); -#ifdef DEBUG_XED +#ifdef V3_CONFIG_DEBUG_DECODER xed_iclass_enum_t iclass = xed_decoded_inst_get_iclass(&xed_instr); - PrintDebug("iform=%s, iclass=%s\n", xed_iform_enum_t2str(iform), xed_iclass_enum_t2str(iclass)); + PrintDebug(info->vm_info, info, "iform=%s, iclass=%s\n", xed_iform_enum_t2str(iform), xed_iclass_enum_t2str(iclass)); #endif if ((instr->op_type = get_opcode(iform)) == V3_INVALID_OP) { - PrintError("Could not get opcode. (iform=%s)\n", xed_iform_enum_t2str(iform)); + PrintError(info->vm_info, info, "Could not get opcode. (iform=%s)\n", xed_iform_enum_t2str(iform)); return -1; } @@ -351,7 +374,7 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins /* if (instr->num_operands > 3) { - PrintDebug("Special Case Not Handled (more than 3 operands) (iform=%s)\n", xed_iform_enum_t2str(iform) + PrintDebug(info->vm_info, info, "Special Case Not Handled (more than 3 operands) (iform=%s)\n", xed_iform_enum_t2str(iform) return -1; // special case } else if (instr->num_operands == 3) { @@ -361,14 +384,14 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins if ((!xed_operand_is_register(op_enum)) || (!is_flags_reg(xed_decoded_inst_get_reg(&xed_instr, op_enum)))) { // special case - PrintError("Special Case not handled (iform=%s)\n", xed_iform_enum_t2str(iform)); + PrintError(info->vm_info, info, "Special Case not handled (iform=%s)\n", xed_iform_enum_t2str(iform)); return -1; } } */ - //PrintDebug("Number of operands: %d\n", instr->num_operands); - //PrintDebug("INSTR length: %d\n", instr->instr_length); + //PrintDebug(info->vm_info, info, "Number of operands: %d\n", instr->num_operands); + //PrintDebug(info->vm_info, info, "INSTR length: %d\n", instr->instr_length); // set first operand if (instr->num_operands >= 1) { @@ -395,7 +418,7 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins &(v3_op->size)); if (v3_reg_type == -1) { - PrintError("First operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg)); + PrintError(info->vm_info, info, "First operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg)); v3_op->type = INVALID_OPERAND; return -1; } else if (v3_reg_type == SEGMENT_REGISTER) { @@ -410,9 +433,9 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins case XED_OPERAND_MEM0: { - PrintDebug("Memory operand (1)\n"); + PrintDebug(info->vm_info, info, "Memory operand (1)\n"); if (get_memory_operand(info, &xed_instr, 0, v3_op) == -1) { - PrintError("Could not get first memory operand\n"); + PrintError(info->vm_info, info, "Could not get first memory operand\n"); return -1; } } @@ -421,21 +444,44 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins case XED_OPERAND_MEM1: case XED_OPERAND_IMM1: // illegal - PrintError("Illegal Operand Order\n"); + PrintError(info->vm_info, info, "Illegal Operand Order\n"); return -1; case XED_OPERAND_IMM0: + { + v3_op->size = xed_decoded_inst_get_immediate_width(&xed_instr); + + if (v3_op->size > 4) { + PrintError(info->vm_info, info, "Unhandled 64 bit immediates\n"); + return -1; + } + v3_op->operand = xed_decoded_inst_get_unsigned_immediate(&xed_instr); + + v3_op->type = IMM_OPERAND; + + } + break; case XED_OPERAND_AGEN: case XED_OPERAND_PTR: case XED_OPERAND_RELBR: default: - PrintError("Unhandled Operand Type\n"); + PrintError(info->vm_info, info, "Unhandled Operand Type\n"); return -1; + } + } +// V3_Print(info->vm_info, info, "Operand 0 mode: %s\n", xed_operand_action_enum_t2str(xed_operand_rw(op))); - } + + if (xed_operand_read(op)) { + v3_op->read = 1; + } + + if (xed_operand_written(op)) { + v3_op->write = 1; } + } // set second operand @@ -455,6 +501,7 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins */ v3_op = &(instr->src_operand); + if (xed_operand_is_register(op_enum)) { xed_reg_enum_t xed_reg = xed_decoded_inst_get_reg(&xed_instr, op_enum); int v3_reg_type = xed_reg_to_v3_reg(info, @@ -462,7 +509,7 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins &(v3_op->operand), &(v3_op->size)); if (v3_reg_type == -1) { - PrintError("Second operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg)); + PrintError(info->vm_info, info, "Second operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg)); v3_op->type = INVALID_OPERAND; return -1; } else if (v3_reg_type == SEGMENT_REGISTER) { @@ -471,17 +518,14 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins } v3_op->type = REG_OPERAND; - - } else { - switch (op_enum) { case XED_OPERAND_MEM0: { - PrintDebug("Memory operand (2)\n"); + PrintDebug(info->vm_info, info, "Memory operand (2)\n"); if (get_memory_operand(info, &xed_instr, 0, v3_op) == -1) { - PrintError("Could not get first memory operand\n"); + PrintError(info->vm_info, info, "Could not get first memory operand\n"); return -1; } } @@ -492,7 +536,7 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins instr->src_operand.size = xed_decoded_inst_get_immediate_width(&xed_instr); if (instr->src_operand.size > 4) { - PrintError("Unhandled 64 bit immediates\n"); + PrintError(info->vm_info, info, "Unhandled 64 bit immediates\n"); return -1; } instr->src_operand.operand = xed_decoded_inst_get_unsigned_immediate(&xed_instr); @@ -505,18 +549,28 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins case XED_OPERAND_MEM1: case XED_OPERAND_IMM1: // illegal - PrintError("Illegal Operand Order\n"); + PrintError(info->vm_info, info, "Illegal Operand Order\n"); return -1; case XED_OPERAND_AGEN: case XED_OPERAND_PTR: case XED_OPERAND_RELBR: default: - PrintError("Unhandled Operand Type\n"); + PrintError(info->vm_info, info, "Unhandled Operand Type\n"); return -1; } } +// V3_Print(info->vm_info, info, "Operand 1 mode: %s\n", xed_operand_action_enum_t2str(xed_operand_rw(op))); + + if (xed_operand_read(op)) { + v3_op->read = 1; + } + + if (xed_operand_written(op)) { + v3_op->write = 1; + } + } // set third operand @@ -525,6 +579,8 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins xed_operand_type_enum_t op_type = xed_operand_type(op); xed_operand_enum_t op_enum = xed_operand_name(op); + + if (xed_operand_is_register(op_enum)) { xed_reg_enum_t xed_reg = xed_decoded_inst_get_reg(&xed_instr, op_enum); int v3_reg_type = xed_reg_to_v3_reg(info, @@ -533,7 +589,7 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins &(instr->third_operand.size)); if (v3_reg_type == -1) { - PrintError("Third operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg)); + PrintError(info->vm_info, info, "Third operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg)); instr->third_operand.type = INVALID_OPERAND; return -1; } else if (v3_reg_type == SEGMENT_REGISTER) { @@ -544,22 +600,28 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins instr->third_operand.type = REG_OPERAND; + PrintDebug(info->vm_info, info, "Operand 2 mode: %s\n", xed_operand_action_enum_t2str(xed_operand_rw(op))); + + + if (xed_operand_read(op)) { + instr->third_operand.read = 1; + } + + if (xed_operand_written(op)) { + instr->third_operand.write = 1; + } } else { - PrintError("Unhandled third operand type %s\n", xed_operand_type_enum_t2str(op_type)); + PrintError(info->vm_info, info, "Unhandled third operand type %s\n", xed_operand_type_enum_t2str(op_type)); instr->num_operands = 2; } - - } - - return 0; } -int v3_encode(struct guest_info * info, struct x86_instr * instr, char * instr_buf) { +int v3_encode(struct guest_info * info, struct x86_instr * instr, uint8_t * instr_buf) { return -1; } @@ -576,13 +638,14 @@ static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xe addr_t scale; addr_t index; ullong_t displacement; - int addr_width = v3_get_addr_width(info);; + int addr_width = v3_get_addr_width(info); + v3_cpu_mode_t cpu_mode = v3_get_vm_cpu_mode(info); // struct v3_segment * seg_reg; - PrintDebug("Xen mode = %s\n", xed_machine_mode_enum_t2str(xed_state_get_machine_mode(info->decoder_state))); - PrintDebug("Address width: %s\n", + PrintDebug(info->vm_info, info, "Xed mode = %s\n", xed_machine_mode_enum_t2str(xed_state_get_machine_mode(info->decoder_state))); + PrintDebug(info->vm_info, info, "Address width: %s\n", xed_address_width_enum_t2str(xed_state_get_address_width(info->decoder_state))); - PrintDebug("Stack Address width: %s\n", + PrintDebug(info->vm_info, info, "Stack Address width: %s\n", xed_address_width_enum_t2str(xed_state_get_stack_address_width(info->decoder_state))); @@ -593,7 +656,7 @@ static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xe if (xed_seg != XED_REG_INVALID) { struct v3_segment *tmp_segment; if (xed_reg_to_v3_reg(info, xed_seg, (addr_t *)&tmp_segment, &(mem_op.segment_size)) == -1) { - PrintError("Unhandled Segment Register\n"); + PrintError(info->vm_info, info, "Unhandled Segment Register\n"); return -1; } mem_op.segment = tmp_segment->base; @@ -603,7 +666,7 @@ static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xe if (xed_base != XED_REG_INVALID) { addr_t base_reg; if (xed_reg_to_v3_reg(info, xed_base, &base_reg, &(mem_op.base_size)) == -1) { - PrintError("Unhandled Base register\n"); + PrintError(info->vm_info, info, "Unhandled Base register\n"); return -1; } mem_op.base = *(addr_t *)base_reg; @@ -616,7 +679,7 @@ static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xe addr_t index_reg; if (xed_reg_to_v3_reg(info, xed_idx, &index_reg, &(mem_op.index_size)) == -1) { - PrintError("Unhandled Index Register\n"); + PrintError(info->vm_info, info, "Unhandled Index Register\n"); return -1; } @@ -642,38 +705,45 @@ static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xe - PrintDebug("Struct: Seg=%p (size=%d), base=%p, index=%p, scale=%p, displacement=%p (size=%d)\n", + PrintDebug(info->vm_info, info, "Struct: Seg=%p (size=%d), base=%p, index=%p, scale=%p, displacement=%p (size=%d)\n", (void *)mem_op.segment, mem_op.segment_size, (void*)mem_op.base, (void *)mem_op.index, (void *)mem_op.scale, (void *)(addr_t)mem_op.displacement, mem_op.displacement_size); - PrintDebug("operand size: %d\n", operand->size); + PrintDebug(info->vm_info, info, "operand size: %d\n", operand->size); seg = MASK(mem_op.segment, mem_op.segment_size); base = MASK(mem_op.base, mem_op.base_size); index = MASK(mem_op.index, mem_op.index_size); scale = mem_op.scale; - // This is a horrendous hack... - // XED really screwed the pooch in calculating the displacement - if (v3_get_cpu_mode(info) == LONG) { - displacement = mem_op.displacement; - } else { - displacement = MASK(mem_op.displacement, mem_op.displacement_size); - } + // XED returns the displacement as a 2s complement signed number, but it can + // have different sizes, depending on the instruction encoding. + // we put that into a 64 bit unsigned (the unsigned doesn't matter since + // we only ever do 2s complement arithmetic on it. However, this means we + // need to sign-extend what XED provides through 64 bits. + displacement = mem_op.displacement; + displacement <<= 64 - mem_op.displacement_size * 8; + displacement = ((sllong_t)displacement) >> (64 - mem_op.displacement_size * 8); + - PrintDebug("Seg=%p, base=%p, index=%p, scale=%p, displacement=%p\n", + PrintDebug(info->vm_info, info, "Seg=%p, base=%p, index=%p, scale=%p, displacement=%p\n", (void *)seg, (void *)base, (void *)index, (void *)scale, (void *)(addr_t)displacement); - operand->operand = MASK((seg + base + (scale * index) + displacement), addr_width); + if (cpu_mode == REAL) { + operand->operand = seg + MASK((base + (scale * index) + displacement), addr_width); + } else { + operand->operand = MASK((seg + base + (scale * index) + displacement), addr_width); + } return 0; } -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) { +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) { - PrintDebug("Xed Register: %s\n", xed_reg_enum_t2str(xed_reg)); + PrintDebug(info->vm_info, info, "Xed Register: %s\n", xed_reg_enum_t2str(xed_reg)); switch (xed_reg) { case XED_REG_INVALID: @@ -1027,7 +1097,14 @@ static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, a *reg_len = 4; return CTRL_REGISTER; case XED_REG_CR8: - *v3_reg = (addr_t)&(info->ctrl_regs.cr8); + // TODO FIX: Peter says this should actually look like: + // ((info->ctrl_regs.apic_tpr >> 4) & 0xf) + // but this isn't straightforward since it doesn't + // make an lvalue (need to create temporary). + // Committing simple fix below to fix build. We are + // never going to use xed going forward anyway, so + // this doesn't matter. + *v3_reg = (addr_t)&(info->ctrl_regs.apic_tpr); *reg_len = 4; return CTRL_REGISTER; @@ -1080,7 +1157,7 @@ static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, a case XED_REG_LDTR: case XED_REG_IDTR: case XED_REG_TR: - PrintError("Segment selector operand... Don't know how to handle this...\n"); + PrintError(info->vm_info, info, "Segment selector operand... Don't know how to handle this...\n"); return -1; /* @@ -1219,6 +1296,9 @@ static v3_op_type_t get_opcode(xed_iform_enum_t iform) { case XED_IFORM_INVLPG_MEMb: return V3_OP_INVLPG; + case XED_IFORM_INT_IMM: + return V3_OP_INT; + /* Data Instructions */