From 5ffa4325fda49e889e935c5db400ff00652d27db Mon Sep 17 00:00:00 2001 From: Vladimir Koshelev Date: Mon, 26 Sep 2011 13:51:28 +0400 Subject: [PATCH 16/32] VMM Emulator +SCAS +CMP --- palacios/include/palacios/vmm_decoder.h | 3 +- palacios/include/palacios/vmm_instr_emulator.h | 5 ++- palacios/src/palacios/vmm_decoder.c | 1 + palacios/src/palacios/vmm_emulator.c | 44 +++++++++++++++++++++++- 4 files changed, 50 insertions(+), 3 deletions(-) diff --git a/palacios/include/palacios/vmm_decoder.h b/palacios/include/palacios/vmm_decoder.h index 767fe25..41568cf 100644 --- a/palacios/include/palacios/vmm_decoder.h +++ b/palacios/include/palacios/vmm_decoder.h @@ -29,12 +29,13 @@ typedef enum { V3_INVALID_OP, V3_OP_MOVCR2, V3_OP_MOV2CR, V3_OP_SMSW, V3_OP_LMSW, V3_OP_CLTS, V3_OP_INVLPG, + V3_OP_CMP, V3_OP_ADC, V3_OP_ADD, V3_OP_AND, V3_OP_OR, V3_OP_XOR, V3_OP_SUB, V3_OP_INC, V3_OP_DEC, V3_OP_NEG, V3_OP_MOV, V3_OP_NOT, V3_OP_XCHG, 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_STOS, V3_OP_MOVZX, V3_OP_MOVSX, V3_OP_INT } v3_op_type_t; + V3_OP_SCAS, V3_OP_SETZ, V3_OP_MOVS, V3_OP_STOS, V3_OP_MOVZX, V3_OP_MOVSX, V3_OP_INT } 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 cbccaf1..050a0eb 100644 --- a/palacios/include/palacios/vmm_instr_emulator.h +++ b/palacios/include/palacios/vmm_instr_emulator.h @@ -616,7 +616,7 @@ /****************************/ /* 8 Bit instruction forms */ /****************************/ - +MAKE_2OP_8FLAGS_INST(cmp); MAKE_2OP_8FLAGS_INST(adc); MAKE_2OP_8FLAGS_INST(add); MAKE_2OP_8FLAGS_INST(and); @@ -662,6 +662,7 @@ MAKE_1OP_8STR_INST(scas); /****************************/ /* 16 Bit instruction forms */ /****************************/ +MAKE_2OP_16FLAGS_INST(cmp); MAKE_2OP_16FLAGS_INST(adc); MAKE_2OP_16FLAGS_INST(add); MAKE_2OP_16FLAGS_INST(and); @@ -689,6 +690,7 @@ MAKE_1OP_16STR_INST(scas); /****************************/ /* 32 Bit instruction forms */ /****************************/ +MAKE_2OP_32FLAGS_INST(cmp); MAKE_2OP_32FLAGS_INST(adc); MAKE_2OP_32FLAGS_INST(add); MAKE_2OP_32FLAGS_INST(and); @@ -720,6 +722,7 @@ MAKE_1OP_32STR_INST(scas); /****************************/ /* 64 Bit instruction forms */ /****************************/ +MAKE_2OP_64FLAGS_INST(cmp); MAKE_2OP_64FLAGS_INST(adc); MAKE_2OP_64FLAGS_INST(add); MAKE_2OP_64FLAGS_INST(and); diff --git a/palacios/src/palacios/vmm_decoder.c b/palacios/src/palacios/vmm_decoder.c index 874e8cf..2231d82 100644 --- a/palacios/src/palacios/vmm_decoder.c +++ b/palacios/src/palacios/vmm_decoder.c @@ -114,6 +114,7 @@ static char * op_type_to_str(v3_op_type_t type) { case V3_OP_LMSW: return "V3_OP_LMSW"; case V3_OP_CLTS: return "V3_OP_CLTS"; case V3_OP_INVLPG: return "V3_OP_INVLPG"; + case V3_OP_CMP: return "V3_OP_CMP"; case V3_OP_ADC: return "V3_OP_ADC"; case V3_OP_ADD: return "V3_OP_ADD"; case V3_OP_AND: return "V3_OP_AND"; diff --git a/palacios/src/palacios/vmm_emulator.c b/palacios/src/palacios/vmm_emulator.c index 20c6ecb..f1f174b 100644 --- a/palacios/src/palacios/vmm_emulator.c +++ b/palacios/src/palacios/vmm_emulator.c @@ -38,6 +38,9 @@ static int run_op(struct guest_info * info, v3_op_type_t op_type, PrintDebug("Executing 8 bit instruction\n"); switch (op_type) { + case V3_OP_CMP : + cmp8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags)); + break; case V3_OP_ADC: adc8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags)); break; @@ -143,6 +146,9 @@ static int run_op(struct guest_info * info, v3_op_type_t op_type, PrintDebug("Executing 16 bit instruction\n"); switch (op_type) { + case V3_OP_CMP : + cmp16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags)); + break; case V3_OP_ADC: adc16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags)); break; @@ -198,6 +204,9 @@ static int run_op(struct guest_info * info, v3_op_type_t op_type, PrintDebug("Executing 32 bit instruction\n"); switch (op_type) { + case V3_OP_CMP : + cmp32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags)); + break; case V3_OP_ADC: adc32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags)); break; @@ -248,6 +257,9 @@ static int run_op(struct guest_info * info, v3_op_type_t op_type, PrintDebug("Executing 64 bit instruction\n"); switch (op_type) { + case V3_OP_CMP : + cmp64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags)); + break; case V3_OP_ADC: adc64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags)); break; @@ -374,7 +386,37 @@ static int run_str_op(struct guest_info * core, struct x86_instr * instr, if (instr->prefixes.rep == 1) { core->vm_regs.rcx -= rep_cnt; } - } else { + } else if (instr->op_type == V3_OP_SCAS) { + if (op_size == 1) { + scas8((addr_t *)&dst_addr, (addr_t *)&(core->vm_regs.rax), &tmp_rcx, (addr_t *)&(core->ctrl_regs.rflags)); + } else if (op_size == 2) { + scas16((addr_t *)&dst_addr, (addr_t *)&(core->vm_regs.rax), &tmp_rcx, (addr_t *)&(core->ctrl_regs.rflags)); + } else if (op_size == 4) { + scas32((addr_t *)&dst_addr, (addr_t *)&(core->vm_regs.rax), &tmp_rcx, (addr_t *)&(core->ctrl_regs.rflags)); + #ifdef __V3_64BIT__ + } else if (op_size == 8) { + scas64((addr_t *)&dst_addr, (addr_t *)&(core->vm_regs.rax), &tmp_rcx, (addr_t *)&(core->ctrl_regs.rflags)); + #endif + } else { + PrintError("Invalid operand length\n"); + return -1; + } + + + + if (flags_reg->df == 0) { + core->vm_regs.rdi += emulation_length; + } else { + core->vm_regs.rdi -= emulation_length; + } + + // RCX is only modified if the rep prefix is present + if (instr->prefixes.rep == 1) { + core->vm_regs.rcx -= rep_cnt; + } + } + + { PrintError("Unimplemented String operation\n"); return -1; } -- 1.7.5.4