X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_quix86.c;h=befc9d1d43c4234483b7fd152d27129585318048;hb=d775bbfa668ce9968bacc0e4257cf86e5ab88e90;hp=fd64626d8fa6f2b870464ac6b2eb94f3a7b95105;hpb=3d68a569e5122ebb366d426d1e69f657a4201408;p=palacios.git diff --git a/palacios/src/palacios/vmm_quix86.c b/palacios/src/palacios/vmm_quix86.c index fd64626..befc9d1 100644 --- a/palacios/src/palacios/vmm_quix86.c +++ b/palacios/src/palacios/vmm_quix86.c @@ -7,8 +7,8 @@ * and the University of New Mexico. You can find out more at * http://www.v3vee.org * - * Copyright (c) 2011, Jack Lange - * Copyright (c) 2008, The V3VEE Project + * Copyright (c) 2012, Alexander Kudryavtsev + * Copyright (c) 2012, The V3VEE Project * All rights reserved. * * Author: Alexander Kudryavtsev @@ -27,6 +27,16 @@ #include +#ifdef V3_CONFIG_TM_FUNC +#include +#endif + +#ifdef V3_CONFIG_DEBUG_TM_FUNC +#define PrintTMDebug(...) V3_Print(__VA_ARGS__) +#else +#define PrintTMDebug(...) +#endif + #ifndef V3_CONFIG_DEBUG_DECODER #undef PrintDebug #define PrintDebug(fmt, args...) @@ -45,73 +55,10 @@ int v3_deinit_decoder(struct guest_info * core) { return 0; } -static int get_opcode(qx86_insn *inst); +static int get_opcode(qx86_insn *inst, struct guest_info *core); static int qx86_register_to_v3_reg(struct guest_info * info, int qx86_reg, addr_t * v3_reg, uint_t * reg_len); -static int decode_string_op(struct guest_info * info, - const qx86_insn * qx86_inst, struct x86_instr * instr) -{ - int status = 0; - PrintDebug("String operation\n"); - - if (instr->prefixes.rep == 1) { - uint64_t a_mask = ~(~0ULL << - (QX86_SIZE_OCTETS(qx86_inst->attributes.addressSize) * 8)); - - instr->str_op_length = info->vm_regs.rcx & a_mask; - } else { - instr->str_op_length = 1; - } - - - if (instr->op_type == V3_OP_MOVS) { - instr->num_operands = 2; - - if((status = qx86_calculate_linear_address(qx86_inst, 0, - (qx86_uint64*)&instr->dst_operand.operand)) != QX86_SUCCESS) { - PrintError("Could not get destination memory operand: " - "qx86_calculate_linear_address: %d\n", status); - return -1; - } - - if((status = qx86_calculate_linear_address(qx86_inst, 1, - (qx86_uint64*)&instr->src_operand.operand)) != QX86_SUCCESS) { - PrintError("Could not get source memory operand: " - "qx86_calculate_linear_address: %d\n", status); - return -1; - } - - instr->dst_operand.write = 1; - instr->src_operand.read = 1; - - } else if (instr->op_type == V3_OP_STOS) { - instr->num_operands = 2; - - if((status = qx86_calculate_linear_address(qx86_inst, 0, - (qx86_uint64*)&instr->dst_operand.operand)) != QX86_SUCCESS) { - PrintError("Could not get destination memory operand: " - "qx86_calculate_linear_address: %d\n", status); - return -1; - } - - // STOS reads from rax - qx86_register_to_v3_reg(info, - qx86_inst->operands[1].u.r.rindex, - &(instr->src_operand.operand), &(instr->src_operand.size)); - instr->src_operand.type = REG_OPERAND; - - instr->src_operand.read = 1; - instr->dst_operand.write = 1; - - } else { - PrintError("Unhandled String OP\n"); - return -1; - } - - return 0; -} - static int callback(void *data, int rindex, int subreg, unsigned char *value) { void* reg_addr = 0; uint_t reg_size; @@ -122,7 +69,7 @@ static int callback(void *data, int rindex, int subreg, unsigned char *value) { (addr_t*)®_addr, ®_size); if(v3_reg_type == -1) { - PrintError("Callback failed to get register index %d\n", rindex); + PrintError(info->vm_info, info, "Callback failed to get register index %d\n", rindex); return 0; } @@ -135,10 +82,10 @@ static int callback(void *data, int rindex, int subreg, unsigned char *value) { *(uint32_t*)value = ((struct v3_segment*)reg_addr)->limit; break; case QX86_SUBREG_FLAGS: - PrintError("Callback doesn't know how to give flags.\n"); + PrintError(info->vm_info, info, "Callback doesn't know how to give flags.\n"); return 0; case QX86_SUBREG_NONE: { - switch(qx86_rtab[rindex].size) { + switch(qx86_rinfo(rindex)->size) { case 1: *(uint8_t* )value = *(uint8_t* )reg_addr; break; case 2: *(uint16_t*)value = *(uint16_t*)reg_addr; break; case 4: *(uint32_t*)value = *(uint32_t*)reg_addr; break; @@ -161,8 +108,8 @@ static inline int qx86_op_to_v3_op(struct guest_info *info, qx86_insn *qx86_insn &(v3_op->operand), &(v3_op->size)); if (v3_reg_type == -1) { - PrintError("Operand %d is an Unhandled Operand: %s\n", op_num, - qx86_rtab[qx86_op->u.r.rindex].name); + PrintError(info->vm_info, info, "Operand %d is an Unhandled Operand: %s\n", op_num, + qx86_rinfo(qx86_op->u.r.rindex)->name); v3_op->type = INVALID_OPERAND; return -1; } else if (v3_reg_type == SEGMENT_REGISTER) { @@ -172,10 +119,10 @@ static inline int qx86_op_to_v3_op(struct guest_info *info, qx86_insn *qx86_insn v3_op->type = REG_OPERAND; } else if(qx86_op->ot == QX86_OPERAND_TYPE_MEMORY) { - PrintDebug("Memory operand (%d)\n", op_num); + PrintDebug(info->vm_info, info, "Memory operand (%d)\n", op_num); if((status = qx86_calculate_linear_address(qx86_insn, op_num, (qx86_uint64*)&v3_op->operand)) != QX86_SUCCESS) { - PrintError("Could not get memory operand %d: " + PrintError(info->vm_info, info, "Could not get memory operand %d: " "qx86_calculate_linear_address() returns %d\n", op_num, status); return -1; } @@ -186,14 +133,14 @@ static inline int qx86_op_to_v3_op(struct guest_info *info, qx86_insn *qx86_insn v3_op->size = qx86_op->u.i.valueSize; if (v3_op->size > 4) { - PrintError("Unhandled 64 bit immediates\n"); + PrintError(info->vm_info, info, "Unhandled 64 bit immediates\n"); return -1; } v3_op->operand = (addr_t)*(uint64_t*)qx86_op->u.i.value; v3_op->type = IMM_OPERAND; } else { - PrintError("Unhandled Operand %d Type %d\n", op_num, qx86_op->ot); + PrintError(info->vm_info, info, "Unhandled Operand %d Type %d\n", op_num, qx86_op->ot); return -1; } @@ -214,6 +161,13 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins memset(instr, 0, sizeof(struct x86_instr)); memset(&qx86_inst, 0, sizeof(qx86_inst)); +#ifdef V3_CONFIG_TM_FUNC + if (v3_tm_decode_rtm_instrs(info, instr_ptr, instr) == -1) { + return -1; + } +#endif + + v3_get_prefixes((uchar_t *)instr_ptr, &(instr->prefixes)); switch(v3_get_vm_cpu_mode(info)) { @@ -224,7 +178,7 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins case LONG: proc_mode = QX86_SIZE_64; 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; } @@ -241,13 +195,13 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins (info->rip & ~0xfffULL) + 0x1000, &(info->segments.cs)), &instr_ptr2); } if (status == -1) { - PrintError("Could not translate Instruction Address at second stage " + PrintError(info->vm_info, info, "Could not translate Instruction Address at second stage " "translation (%p)\n", (void *)(addr_t)info->rip); return -1; } if(((instr_ptr & ~0xfffUL) + 0x1000) != instr_ptr2) { - PrintError("Note: physical page non-contiguous\n"); + PrintError(info->vm_info, info, "Note: physical page non-contiguous\n"); memcpy(inst_buf, (const void*)instr_ptr, left_in_page); memcpy(inst_buf + left_in_page, (const void*)instr_ptr2, QX86_INSN_SIZE_MAX - left_in_page); @@ -261,21 +215,36 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins int status = qx86_decode(&qx86_inst, proc_mode, (const void*)instr_ptr, QX86_INSN_SIZE_MAX); if(status != QX86_SUCCESS) { - PrintError("qx86_decode() returned %d\n", status); + PrintError(info->vm_info, info, "qx86_decode() returned %d\n", status); return -1; } instr->instr_length = qx86_inst.rawSize; - if ((instr->op_type = get_opcode(&qx86_inst)) == V3_INVALID_OP) { - PrintError("Could not get opcode. (mnemonic=%s)\n", - qx86_mtab[qx86_inst.mnemonic].name); + // 441 - dump memory for quix86 debugging + if ((instr->op_type = get_opcode(&qx86_inst,info)) == V3_INVALID_OP) { + PrintError(info->vm_info, info, "++==++ QX86 DECODE ++==++, guest RIP: %llx\n", info->rip); + v3_dump_mem((void *)instr_ptr, 15); + PrintError(info->vm_info, info, "Could not get opcode. (mnemonic=%s)\n", + qx86_minfo(qx86_inst.mnemonic)->name); + return -1; + } + if ((instr->op_type = get_opcode(&qx86_inst, info)) == V3_INVALID_OP) { + PrintError(info->vm_info, info, "Could not get opcode. (mnemonic=%s)\n", + qx86_minfo(qx86_inst.mnemonic)->name); return -1; } if(instr->op_type == V3_OP_MOVS || instr->op_type == V3_OP_STOS) { instr->is_str_op = 1; - return decode_string_op(info, &qx86_inst, instr); + if (instr->prefixes.rep == 1) { + uint64_t a_mask = (~0ULL >> + (64 - QX86_SIZE_OCTETS(qx86_inst.attributes.addressSize) * 8)); + + instr->str_op_length = info->vm_regs.rcx & a_mask; + } else { + instr->str_op_length = 1; + } } else { instr->is_str_op = 0; instr->str_op_length = 0; @@ -306,20 +275,20 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins char buf[128]; int buf_sz = 128; if(qx86_print_intel(&qx86_inst, &opt, buf, &buf_sz) != QX86_SUCCESS) { - PrintDebug("Print failed!\n"); + PrintDebug(info->vm_info, info, "Print failed!\n"); } else { - PrintDebug("Instruction (%p): %s\n", (void*)info->rip, buf); + PrintDebug(info->vm_info, info, "Instruction (%p): %s\n", (void*)info->rip, buf); } - PrintDebug("Operands: dst %p src %p 3rd %p\n", (void*)instr->dst_operand.operand, + PrintDebug(info->vm_info, info, "Operands: dst %p src %p 3rd %p\n", (void*)instr->dst_operand.operand, (void*)instr->src_operand.operand, (void*)instr->third_operand.operand); #endif return 0; } -static int get_opcode(qx86_insn *inst) { +static int get_opcode(qx86_insn *inst, struct guest_info *core) { switch (inst->mnemonic) { #define IS_CR(op) inst->operands[op].ot == QX86_OPERAND_TYPE_REGISTER && \ - qx86_rtab[inst->operands[op].u.r.rindex].rclass == QX86_RCLASS_CREG + qx86_rinfo(inst->operands[op].u.r.rindex)->rclass == QX86_RCLASS_CREG /* MOV cases */ case QX86_MNEMONIC_MOV: { @@ -330,8 +299,12 @@ static int get_opcode(qx86_insn *inst) { return V3_OP_MOV2CR; if(IS_CR(1)) return V3_OP_MOVCR2; + // 441 - mov reg reg is also ok + if(inst->operands[0].ot == QX86_OPERAND_TYPE_REGISTER + || inst->operands[1].ot == QX86_OPERAND_TYPE_REGISTER) + return V3_OP_MOV; - PrintError("Bad operand types for MOV: %d %d\n", inst->operands[0].ot, + PrintError(core->vm_info, core, "Bad operand types for MOV: %d %d\n", inst->operands[0].ot, inst->operands[1].ot); return V3_INVALID_OP; } @@ -451,6 +424,66 @@ static int get_opcode(qx86_insn *inst) { case QX86_MNEMONIC_STOSQ: return V3_OP_STOS; + /* 441-tm: add in CMP, POP, JLE, CALL cases */ + case QX86_MNEMONIC_CMP: + return V3_OP_CMP; + + case QX86_MNEMONIC_POP: + return V3_OP_POP; + + case QX86_MNEMONIC_JLE: + return V3_OP_JLE; + + case QX86_MNEMONIC_CALL: + return V3_OP_CALL; + + case QX86_MNEMONIC_TEST: + return V3_OP_TEST; + + case QX86_MNEMONIC_PUSH: + return V3_OP_PUSH; + + case QX86_MNEMONIC_JAE: + return V3_OP_JAE; + + case QX86_MNEMONIC_JMP: + return V3_OP_JMP; + + case QX86_MNEMONIC_JNZ: + return V3_OP_JNZ; + + case QX86_MNEMONIC_JZ: + return V3_OP_JZ; + + case QX86_MNEMONIC_RET: + return V3_OP_RET; + + case QX86_MNEMONIC_IMUL: + return V3_OP_IMUL; + + case QX86_MNEMONIC_LEA: + return V3_OP_LEA; + + case QX86_MNEMONIC_JL: + return V3_OP_JL; + + case QX86_MNEMONIC_CMOVZ: + return V3_OP_CMOVZ; + + case QX86_MNEMONIC_MOVSXD: + return V3_OP_MOVSXD; + + case QX86_MNEMONIC_JNS: + return V3_OP_JNS; + + case QX86_MNEMONIC_CMOVS: + return V3_OP_CMOVS; + + case QX86_MNEMONIC_SHL: + return V3_OP_SHL; + + case QX86_MNEMONIC_INT: + return V3_OP_INT; default: return V3_INVALID_OP; @@ -459,7 +492,7 @@ static int get_opcode(qx86_insn *inst) { static int qx86_register_to_v3_reg(struct guest_info * info, int qx86_reg, addr_t * v3_reg, uint_t * reg_len) { - PrintDebug("qx86 Register: %s\n", qx86_rtab[qx86_reg].name); + PrintDebug(info->vm_info, info, "qx86 Register: %s\n", qx86_rinfo(qx86_reg)->name); switch (qx86_reg) { case QX86_REGISTER_INVALID: @@ -807,7 +840,7 @@ static int qx86_register_to_v3_reg(struct guest_info * info, int qx86_reg, *reg_len = 4; return CTRL_REGISTER; case QX86_REGISTER_CR8: - *v3_reg = (addr_t)&(info->ctrl_regs.cr8); + *v3_reg = (addr_t)&(info->ctrl_regs.apic_tpr); *reg_len = 4; return CTRL_REGISTER;