X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_xed.c;h=a3b39d5164c7fa9537c48018b1503c95569ae5a5;hb=d3a58bbcc5cc9105e894771b1b2c39f76c86a70e;hp=c82f107bb04b35bd6aba2bd586cd0514c82149c5;hpb=191b42c70d34a064b6600784508e3a06040ec044;p=palacios.git diff --git a/palacios/src/palacios/vmm_xed.c b/palacios/src/palacios/vmm_xed.c index c82f107..a3b39d5 100644 --- a/palacios/src/palacios/vmm_xed.c +++ b/palacios/src/palacios/vmm_xed.c @@ -35,7 +35,7 @@ -#ifndef DEBUG_XED +#ifndef CONFIG_DEBUG_XED #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, @@ -146,18 +146,18 @@ static int set_decoder_mode(struct guest_info * info, xed_state_t * state) { return 0; } -static int is_flags_reg(xed_reg_enum_t xed_reg) { - switch (xed_reg) { - case XED_REG_FLAGS: - case XED_REG_EFLAGS: - case XED_REG_RFLAGS: - return 1; - default: - return 0; - } -} - - +/* + static int is_flags_reg(xed_reg_enum_t xed_reg) { + switch (xed_reg) { + case XED_REG_FLAGS: + case XED_REG_EFLAGS: + case XED_REG_RFLAGS: + return 1; + default: + return 0; + } + } +*/ int v3_init_decoder(struct guest_info * info) { // Global library initialization, only do it once @@ -180,57 +180,15 @@ 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) { @@ -278,7 +236,8 @@ static int decode_string_op(struct guest_info * info, 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; @@ -294,6 +253,55 @@ static int decode_string_op(struct guest_info * info, +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("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; + } + + /* obtain string representation in AT&T syntax */ + if (!xed_format_att(&xed_instr, buffer, sizeof(buffer), *rip)) { + PrintError("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("0x%p %c ", (void *) *rip, mark ? '*' : ' '); + for (i = 0; i < length; i++) { + unsigned char b = ((unsigned char *) instr_ptr)[i]; + V3_Print("%x%x ", b >> 4, b & 0xf); + } + while (i++ < 8) { + V3_Print(" "); + } + V3_Print("%s\n", buffer); + + /* move on to next instruction */ + *rip += length; + return 0; +} + + + int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * instr) { xed_decoded_inst_t xed_instr; xed_error_enum_t xed_error; @@ -325,7 +333,7 @@ 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 CONFIG_DEBUG_XED 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)); @@ -349,21 +357,23 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins instr->num_operands = xed_decoded_inst_noperands(&xed_instr); - if (instr->num_operands > 3) { - PrintDebug("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) { - const xed_operand_t * op = xed_inst_operand(xi, 2); - xed_operand_enum_t op_enum = xed_operand_name(op); - - 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)); - return -1; - } - } + /* + if (instr->num_operands > 3) { + PrintDebug("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) { + const xed_operand_t * op = xed_inst_operand(xi, 2); + xed_operand_enum_t op_enum = xed_operand_name(op); + + 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)); + return -1; + } + } + */ //PrintDebug("Number of operands: %d\n", instr->num_operands); //PrintDebug("INSTR length: %d\n", instr->instr_length); @@ -430,8 +440,6 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins default: PrintError("Unhandled Operand Type\n"); return -1; - - } } } @@ -469,10 +477,7 @@ 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: @@ -514,7 +519,6 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins return -1; } } - } // set third operand @@ -542,17 +546,12 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins instr->third_operand.type = REG_OPERAND; - } else { PrintError("Unhandled third operand type %s\n", xed_operand_type_enum_t2str(op_type)); - return -1; + instr->num_operands = 2; } - - } - - return 0; } @@ -574,10 +573,11 @@ 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("Xed mode = %s\n", xed_machine_mode_enum_t2str(xed_state_get_machine_mode(info->decoder_state))); PrintDebug("Address width: %s\n", xed_address_width_enum_t2str(xed_state_get_address_width(info->decoder_state))); PrintDebug("Stack Address width: %s\n", @@ -652,24 +652,31 @@ static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xe 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", (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));