X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_xed.c;h=1aef74aa9b8e421d8638b9847b3544dc685c2de8;hb=ad81fe7841677f9c74046495369ef0240c5a3b61;hp=e6de1e1bb6e8ba6a3cb608de8893de470df32cf6;hpb=87bd3921fe6a17138bdba3a41b501a8d620cb48a;p=palacios-OLD.git diff --git a/palacios/src/palacios/vmm_xed.c b/palacios/src/palacios/vmm_xed.c index e6de1e1..1aef74a 100644 --- a/palacios/src/palacios/vmm_xed.c +++ b/palacios/src/palacios/vmm_xed.c @@ -112,7 +112,6 @@ static int set_decoder_mode(struct guest_info * info, xed_state_t * state) { break; case PROTECTED: case PROTECTED_PAE: - case LONG_32_COMPAT: if (state->mmode != XED_MACHINE_MODE_LEGACY_32) { xed_state_init(state, XED_MACHINE_MODE_LEGACY_32, @@ -120,9 +119,23 @@ static int set_decoder_mode(struct guest_info * info, xed_state_t * state) { XED_ADDRESS_WIDTH_32b); } break; + case LONG_32_COMPAT: + if (state->mmode != XED_MACHINE_MODE_LONG_COMPAT_32) { + xed_state_init(state, + XED_MACHINE_MODE_LONG_COMPAT_32, + XED_ADDRESS_WIDTH_32b, + XED_ADDRESS_WIDTH_32b); + } + break; case LONG: - if (state->mmode != XED_MACHINE_MODE_LONG_64) { - state->mmode = XED_MACHINE_MODE_LONG_64; + if (state->mmode != XED_MACHINE_MODE_LONG_64) { + PrintDebug("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, + XED_MACHINE_MODE_LONG_64, + XED_ADDRESS_WIDTH_64b, + XED_ADDRESS_WIDTH_64b); } break; default: @@ -154,6 +167,10 @@ int v3_init_decoder(struct guest_info * info) { xed_state_t * decoder_state = (xed_state_t *)V3_Malloc(sizeof(xed_state_t)); xed_state_zero(decoder_state); + xed_state_init(decoder_state, + XED_MACHINE_MODE_LEGACY_32, + XED_ADDRESS_WIDTH_32b, + XED_ADDRESS_WIDTH_32b); info->decoder_state = decoder_state; @@ -242,6 +259,33 @@ static int decode_string_op(struct guest_info * info, instr->str_op_length = 1; } + } else if (instr->op_type == V3_OP_STOS) { + instr->num_operands = 2; + + if (get_memory_operand(info, xed_instr, 0, &(instr->dst_operand)) == -1) { + PrintError("Could not get Destination memory operand\n"); + return -1; + } + + // STOS reads from rax + xed_reg_to_v3_reg(info, xed_decoded_inst_get_reg(xed_instr, XED_OPERAND_REG0), + &(instr->src_operand.operand), + &(instr->src_operand.size)); + instr->src_operand.type = REG_OPERAND; + + 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); + instr->str_op_length = MASK(*(addr_t *)reg_addr, reg_length); + } else { + instr->str_op_length = 1; + } + + } else { + PrintError("Unhandled String OP\n"); + return -1; } return 0; @@ -333,12 +377,15 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins struct x86_operand * v3_op = NULL; - if (xed_operand_written(op)) { + /* + if (xed_operand_written(op)) { v3_op = &(instr->dst_operand); - } else { + } else { v3_op = &(instr->src_operand); - } + } + */ + v3_op = &(instr->dst_operand); if (xed_operand_is_register(op_enum)) { xed_reg_enum_t xed_reg = xed_decoded_inst_get_reg(&xed_instr, op_enum); @@ -363,6 +410,7 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins case XED_OPERAND_MEM0: { + PrintDebug("Memory operand (1)\n"); if (get_memory_operand(info, &xed_instr, 0, v3_op) == -1) { PrintError("Could not get first memory operand\n"); return -1; @@ -398,12 +446,14 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins struct x86_operand * v3_op; - if (xed_operand_written(op)) { + /* + if (xed_operand_written(op)) { v3_op = &(instr->dst_operand); - } else { + } else { v3_op = &(instr->src_operand); - } - + } + */ + 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); @@ -429,6 +479,7 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins case XED_OPERAND_MEM0: { + PrintDebug("Memory operand (2)\n"); if (get_memory_operand(info, &xed_instr, 0, v3_op) == -1) { PrintError("Could not get first memory operand\n"); return -1; @@ -525,10 +576,16 @@ 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);; // 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", + xed_address_width_enum_t2str(xed_state_get_address_width(info->decoder_state))); + PrintDebug("Stack Address width: %s\n", + xed_address_width_enum_t2str(xed_state_get_stack_address_width(info->decoder_state))); - + memset((void*)&mem_op, '\0', sizeof(struct memory_operand)); @@ -585,8 +642,8 @@ static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xe - PrintDebug("Struct: Seg=%p, base=%p, index=%p, scale=%p, displacement=%p (size=%d)\n", - (void *)mem_op.segment, (void*)mem_op.base, (void *)mem_op.index, + PrintDebug("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); @@ -596,19 +653,27 @@ static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xe base = MASK(mem_op.base, mem_op.base_size); index = MASK(mem_op.index, mem_op.index_size); scale = mem_op.scale; - displacement = MASK(mem_op.displacement, mem_op.displacement_size); + + // 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); + } 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 = seg + base + (scale * index) + displacement; + 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) { - // PrintError("Xed Register: %s\n", xed_reg_enum_t2str(xed_reg)); + PrintDebug("Xed Register: %s\n", xed_reg_enum_t2str(xed_reg)); switch (xed_reg) { case XED_REG_INVALID: @@ -987,21 +1052,27 @@ static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, a */ case XED_REG_CS: *v3_reg = (addr_t)&(info->segments.cs); + *reg_len = 8; return SEGMENT_REGISTER; case XED_REG_DS: *v3_reg = (addr_t)&(info->segments.ds); + *reg_len = 8; return SEGMENT_REGISTER; case XED_REG_ES: *v3_reg = (addr_t)&(info->segments.es); + *reg_len = 8; return SEGMENT_REGISTER; case XED_REG_SS: *v3_reg = (addr_t)&(info->segments.ss); + *reg_len = 8; return SEGMENT_REGISTER; case XED_REG_FS: *v3_reg = (addr_t)&(info->segments.fs); + *reg_len = 8; return SEGMENT_REGISTER; case XED_REG_GS: *v3_reg = (addr_t)&(info->segments.gs); + *reg_len = 8; return SEGMENT_REGISTER; @@ -1151,37 +1222,71 @@ static v3_op_type_t get_opcode(xed_iform_enum_t iform) { /* Data Instructions */ + // Write case XED_IFORM_ADC_MEMv_GPRv: case XED_IFORM_ADC_MEMv_IMM: case XED_IFORM_ADC_MEMb_GPR8: case XED_IFORM_ADC_MEMb_IMM: + // Read + case XED_IFORM_ADC_GPRv_MEMv: + case XED_IFORM_ADC_GPR8_MEMb: return V3_OP_ADC; + // Write case XED_IFORM_ADD_MEMv_GPRv: case XED_IFORM_ADD_MEMb_IMM: case XED_IFORM_ADD_MEMb_GPR8: case XED_IFORM_ADD_MEMv_IMM: + // Read + case XED_IFORM_ADD_GPRv_MEMv: + case XED_IFORM_ADD_GPR8_MEMb: return V3_OP_ADD; + // Write case XED_IFORM_AND_MEMv_IMM: case XED_IFORM_AND_MEMb_GPR8: case XED_IFORM_AND_MEMv_GPRv: case XED_IFORM_AND_MEMb_IMM: + // Read + case XED_IFORM_AND_GPR8_MEMb: + case XED_IFORM_AND_GPRv_MEMv: return V3_OP_AND; + // Write case XED_IFORM_SUB_MEMv_IMM: case XED_IFORM_SUB_MEMb_GPR8: case XED_IFORM_SUB_MEMb_IMM: case XED_IFORM_SUB_MEMv_GPRv: + // Read + case XED_IFORM_SUB_GPR8_MEMb: + case XED_IFORM_SUB_GPRv_MEMv: return V3_OP_SUB; + // Write case XED_IFORM_MOV_MEMv_GPRv: case XED_IFORM_MOV_MEMb_GPR8: case XED_IFORM_MOV_MEMb_AL: case XED_IFORM_MOV_MEMv_IMM: case XED_IFORM_MOV_MEMb_IMM: + // Read + case XED_IFORM_MOV_GPRv_MEMv: + case XED_IFORM_MOV_GPR8_MEMb: + case XED_IFORM_MOV_AL_MEMb: return V3_OP_MOV; + + // Read + case XED_IFORM_MOVZX_GPRv_MEMb: + case XED_IFORM_MOVZX_GPRv_MEMw: + return V3_OP_MOVZX; + + // Read + case XED_IFORM_MOVSX_GPRv_MEMb: + case XED_IFORM_MOVSX_GPRv_MEMw: + return V3_OP_MOVSX; + + + case XED_IFORM_DEC_MEMv: case XED_IFORM_DEC_MEMb: return V3_OP_DEC; @@ -1190,16 +1295,24 @@ static v3_op_type_t get_opcode(xed_iform_enum_t iform) { case XED_IFORM_INC_MEMv: return V3_OP_INC; + // Write case XED_IFORM_OR_MEMv_IMM: case XED_IFORM_OR_MEMb_IMM: case XED_IFORM_OR_MEMv_GPRv: case XED_IFORM_OR_MEMb_GPR8: + // Read + case XED_IFORM_OR_GPRv_MEMv: + case XED_IFORM_OR_GPR8_MEMb: return V3_OP_OR; + // Write case XED_IFORM_XOR_MEMv_GPRv: case XED_IFORM_XOR_MEMb_IMM: case XED_IFORM_XOR_MEMb_GPR8: case XED_IFORM_XOR_MEMv_IMM: + // Read + case XED_IFORM_XOR_GPRv_MEMv: + case XED_IFORM_XOR_GPR8_MEMb: return V3_OP_XOR; case XED_IFORM_NEG_MEMb: @@ -1262,13 +1375,19 @@ static v3_op_type_t get_opcode(xed_iform_enum_t iform) { case XED_IFORM_SETZ_MEMb: return V3_OP_SETZ; - case XED_IFORM_MOVSB: case XED_IFORM_MOVSW: case XED_IFORM_MOVSD: case XED_IFORM_MOVSQ: return V3_OP_MOVS; + case XED_IFORM_STOSB: + case XED_IFORM_STOSW: + case XED_IFORM_STOSD: + case XED_IFORM_STOSQ: + return V3_OP_STOS; + + default: return V3_INVALID_OP; }