From: Jack Lange Date: Mon, 16 Feb 2009 21:35:12 +0000 (-0600) Subject: added movzx/movsx instructions to the emulator X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=7569a7e7b33dc1c26b68d66e4bcd3aebf3beaf7f;p=palacios-OLD.git added movzx/movsx instructions to the emulator --- diff --git a/palacios/include/palacios/vmm_decoder.h b/palacios/include/palacios/vmm_decoder.h index 6aa0833..4c3df0b 100644 --- a/palacios/include/palacios/vmm_decoder.h +++ b/palacios/include/palacios/vmm_decoder.h @@ -34,7 +34,7 @@ typedef enum { V3_INVALID_OP, V3_OP_SETB, V3_OP_SETBE, V3_OP_SETL, V3_OP_SETLE, V3_OP_SETNB, V3_OP_SETNBE, V3_OP_SETNL, V3_OP_SETNLE, V3_OP_SETNO, V3_OP_SETNP, V3_OP_SETNS, V3_OP_SETNZ, V3_OP_SETO, V3_OP_SETP, V3_OP_SETS, - V3_OP_SETZ, V3_OP_MOVS} v3_op_type_t; + V3_OP_SETZ, V3_OP_MOVS, V3_OP_MOVZX, V3_OP_MOVSX} v3_op_type_t; typedef enum {INVALID_OPERAND, REG_OPERAND, MEM_OPERAND, IMM_OPERAND} v3_operand_type_t; diff --git a/palacios/include/palacios/vmm_instr_emulator.h b/palacios/include/palacios/vmm_instr_emulator.h index 3e9e613..aef325a 100644 --- a/palacios/include/palacios/vmm_instr_emulator.h +++ b/palacios/include/palacios/vmm_instr_emulator.h @@ -397,6 +397,49 @@ +#define MAKE_2OP_8EXT_INST(iname) static inline void iname##8(addr_t * dst, addr_t * src, uint_t dst_len) { \ + if (dst_len == 2) { \ + asm volatile ( \ + #iname" %1, %0; " \ + : "=q"(*(uint16_t *)dst) \ + : "q"(*(uint8_t *)src), "0"(*(uint16_t *)dst) \ + ); \ + } else if (dst_len == 4) { \ + asm volatile ( \ + #iname" %1, %0; " \ + : "=q"(*(uint32_t *)dst) \ + : "q"(*(uint8_t *)src), "0"(*(uint32_t *)dst) \ + ); \ + } else if (dst_len == 8) { \ + asm volatile ( \ + #iname" %1, %0; " \ + : "=q"(*(uint64_t *)dst) \ + : "q"(*(uint8_t *)src), "0"(*(uint64_t *)dst) \ + ); \ + } \ + } + +#define MAKE_2OP_16EXT_INST(iname) static inline void iname##16(addr_t * dst, addr_t * src, uint_t dst_len) { \ + if (dst_len == 4) { \ + asm volatile ( \ + #iname" %1, %0; " \ + : "=q"(*(uint32_t *)dst) \ + : "q"(*(uint16_t *)src), "0"(*(uint32_t *)dst) \ + ); \ + } else if (dst_len == 8) { \ + asm volatile ( \ + #iname" %1, %0; " \ + : "=q"(*(uint64_t *)dst) \ + : "q"(*(uint16_t *)src), "0"(*(uint64_t *)dst) \ + ); \ + } \ + } + + + + + + /****************************/ /* 8 Bit instruction forms */ /****************************/ @@ -433,6 +476,9 @@ MAKE_1OP_8FLAGS_INST(setz); MAKE_1OP_8_INST(not); MAKE_2OP_8_INST(mov); +MAKE_2OP_8EXT_INST(movzx); +MAKE_2OP_8EXT_INST(movsx); + MAKE_2OP_8_INST(xchg); MAKE_2OP_8STR_INST(movs); @@ -456,6 +502,8 @@ MAKE_1OP_16FLAGS_INST(neg); MAKE_1OP_16_INST(not); MAKE_2OP_16_INST(mov); +MAKE_2OP_16EXT_INST(movzx); +MAKE_2OP_16EXT_INST(movsx); MAKE_2OP_16_INST(xchg); MAKE_2OP_16STR_INST(movs); @@ -478,6 +526,7 @@ MAKE_1OP_32FLAGS_INST(neg); MAKE_1OP_32_INST(not); MAKE_2OP_32_INST(mov); + MAKE_2OP_32_INST(xchg); @@ -505,6 +554,7 @@ MAKE_1OP_64_INST(not); MAKE_2OP_64_INST(mov); + MAKE_2OP_64_INST(xchg); diff --git a/palacios/src/palacios/vmm_emulator.c b/palacios/src/palacios/vmm_emulator.c index 859d6b2..a040c3c 100644 --- a/palacios/src/palacios/vmm_emulator.c +++ b/palacios/src/palacios/vmm_emulator.c @@ -32,7 +32,7 @@ -static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_addr, addr_t dst_addr, int op_size); +static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_addr, addr_t dst_addr, int src_op_size, int dst_op_size); // We emulate up to the next 4KB page boundry static int emulate_string_write_op(struct guest_info * info, struct x86_instr * dec_instr, @@ -149,7 +149,8 @@ int v3_emulate_write_op(struct guest_info * info, addr_t write_gva, addr_t write uchar_t instr[15]; int ret = 0; addr_t src_addr = 0; - int op_len = 0; + int src_op_len = 0; + int dst_op_len = 0; PrintDebug("Emulating Write for instruction at %p\n", (void *)(addr_t)(info->rip)); PrintDebug("GVA=%p\n", (void *)write_gva); @@ -201,25 +202,26 @@ int v3_emulate_write_op(struct guest_info * info, addr_t write_gva, addr_t write src_addr = (addr_t)&(dec_instr.src_operand.operand); } - op_len = dec_instr.dst_operand.size; + dst_op_len = dec_instr.dst_operand.size; + src_op_len = dec_instr.src_operand.size; PrintDebug("Dst_Addr = %p, SRC operand = %p\n", (void *)dst_addr, (void *)src_addr); - if (run_op(info, dec_instr.op_type, src_addr, dst_addr, op_len) == -1) { + if (run_op(info, dec_instr.op_type, src_addr, dst_addr, src_op_len, dst_op_len) == -1) { PrintError("Instruction Emulation Failed\n"); return -1; } - if (write_fn(write_gpa, (void *)dst_addr, op_len, priv_data) != op_len) { + if (write_fn(write_gpa, (void *)dst_addr, dst_op_len, priv_data) != dst_op_len) { PrintError("Did not fully write hooked data\n"); return -1; } info->rip += dec_instr.instr_length; - return op_len; + return dst_op_len; } @@ -230,7 +232,8 @@ int v3_emulate_read_op(struct guest_info * info, addr_t read_gva, addr_t read_gp uchar_t instr[15]; int ret = 0; addr_t dst_addr = 0; - int op_len = 0; + int src_op_len = 0; + int dst_op_len = 0; PrintDebug("Emulating Read for instruction at %p\n", (void *)(addr_t)(info->rip)); PrintDebug("GVA=%p\n", (void *)read_gva); @@ -283,24 +286,25 @@ int v3_emulate_read_op(struct guest_info * info, addr_t read_gva, addr_t read_gp dst_addr = (addr_t)&(dec_instr.dst_operand.operand); } - op_len = dec_instr.src_operand.size; + src_op_len = dec_instr.src_operand.size; + dst_op_len = dec_instr.dst_operand.size; PrintDebug("Dst_Addr = %p, SRC Addr = %p\n", (void *)dst_addr, (void *)src_addr); - if (read_fn(read_gpa, (void *)src_addr,op_len, priv_data) != op_len) { + if (read_fn(read_gpa, (void *)src_addr, src_op_len, priv_data) != src_op_len) { PrintError("Did not fully read hooked data\n"); return -1; } - if (run_op(info, dec_instr.op_type, src_addr, dst_addr, op_len) == -1) { + if (run_op(info, dec_instr.op_type, src_addr, dst_addr, src_op_len, dst_op_len) == -1) { PrintError("Instruction Emulation Failed\n"); return -1; } info->rip += dec_instr.instr_length; - return op_len; + return src_op_len; } @@ -308,9 +312,9 @@ int v3_emulate_read_op(struct guest_info * info, addr_t read_gva, addr_t read_gp -static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_addr, addr_t dst_addr, int op_size) { +static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_addr, addr_t dst_addr, int src_op_size, int dst_op_size) { - if (op_size == 1) { + if (src_op_size == 1) { switch (op_type) { case V3_OP_ADC: @@ -335,6 +339,14 @@ static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_add case V3_OP_MOV: mov8((addr_t *)dst_addr, (addr_t *)src_addr); break; + + case V3_OP_MOVZX: + movzx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size); + break; + case V3_OP_MOVSX: + movsx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size); + break; + case V3_OP_NOT: not8((addr_t *)dst_addr); break; @@ -406,7 +418,7 @@ static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_add return -1; } - } else if (op_size == 2) { + } else if (src_op_size == 2) { switch (op_type) { case V3_OP_ADC: @@ -442,6 +454,12 @@ static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_add case V3_OP_MOV: mov16((addr_t *)dst_addr, (addr_t *)src_addr); break; + case V3_OP_MOVZX: + movzx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size); + break; + case V3_OP_MOVSX: + movsx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size); + break; case V3_OP_NOT: not16((addr_t *)dst_addr); break; @@ -454,7 +472,7 @@ static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_add return -1; } - } else if (op_size == 4) { + } else if (src_op_size == 4) { switch (op_type) { case V3_OP_ADC: @@ -489,6 +507,7 @@ static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_add case V3_OP_MOV: mov32((addr_t *)dst_addr, (addr_t *)src_addr); break; + case V3_OP_NOT: not32((addr_t *)dst_addr); break; @@ -502,7 +521,7 @@ static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_add } #ifdef __V3_64BIT__ - } else if (op_size == 8) { + } else if (src_op_size == 8) { switch (op_type) { @@ -538,6 +557,7 @@ static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_add case V3_OP_MOV: mov64((addr_t *)dst_addr, (addr_t *)src_addr); break; + case V3_OP_NOT: not64((addr_t *)dst_addr); break; diff --git a/palacios/src/palacios/vmm_xed.c b/palacios/src/palacios/vmm_xed.c index cc0d1d2..68e39b0 100644 --- a/palacios/src/palacios/vmm_xed.c +++ b/palacios/src/palacios/vmm_xed.c @@ -1225,6 +1225,17 @@ static v3_op_type_t get_opcode(xed_iform_enum_t iform) { 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;