X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_decoder.c;h=874e8cf3d824bd949cadb79a492cd7cc3cf2eab2;hb=9a32111c4074aafd55cd9590a24bd5c751a6fe61;hp=a67887e4f3460a91ab059eab3b13a3720a88f597;hpb=f7cc83b3bae64c853f5b7b63e2830b1ea92dfed9;p=palacios.git diff --git a/palacios/src/palacios/vmm_decoder.c b/palacios/src/palacios/vmm_decoder.c index a67887e..874e8cf 100644 --- a/palacios/src/palacios/vmm_decoder.c +++ b/palacios/src/palacios/vmm_decoder.c @@ -1,86 +1,232 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2008, Jack Lange + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Jack Lange + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + + #include -#if VMM_XED -#include -#endif - - -int parse() { -#if !VMM_XED - PrintDebug("XED is not included in this kernel\n"); -#else - xed_state_t dstate; - xed_decoded_inst_t xedd; - xed_uint_t i, length; - xed_uint8_t itext[100] = {0x01,0x00,0x00,0x00,0x12,0x00,0x55,0x48,0x89,0xe5,0x48,0x89,0x7d,0xf8,0x89,0x75,0xf4,0x89,0x55,0xf0,0x89,0x4d,0xec,0x48,0x8b,0x55,0xf8,0x8b,0x45,0xf4,0x89,0x02,0x48,0x8b,0x55,0xf8,0x8b,0x45,0xf0,0x89,0x42,0x04,0x48,0x8b,0x55,0xf8,0x8b,0x45,0xec,0x89,0x42,0x08,0xc9,0xc3,0x55,0x48,0x89,0xe5,0x48,0x89,0x7d,0xf8,0x48,0x8b,0x45,0xf8,0x8b,0x40,0x08,0xc9,0xc3,0x90,0x0}; - xed_bool_t long_mode = true; - unsigned int first_argv; - int num; - - - for (i=0, num=1; i<100; i += length, num++){ - xed_tables_init(); - xed_state_zero(&dstate); - //if (argc > 2 && strcmp(argv[1], "-64") == 0) - long_mode = true; - - if (long_mode) { - first_argv = 2; - dstate.mmode=XED_MACHINE_MODE_LONG_64; - } - else { - first_argv=1; - xed_state_init(&dstate, - XED_MACHINE_MODE_LEGACY_32, - XED_ADDRESS_WIDTH_32b, - XED_ADDRESS_WIDTH_32b); - } - - xed_decoded_inst_zero_set_mode(&xedd, &dstate); - xed_error_enum_t xed_error = xed_decode(&xedd, - REINTERPRET_CAST(const xed_uint8_t*,&itext[i]), - XED_MAX_INSTRUCTION_BYTES); - switch(xed_error) { - case XED_ERROR_NONE: - break; - case XED_ERROR_BUFFER_TOO_SHORT: - PrintDebug("Not enough bytes provided\n"); - return 1; - case XED_ERROR_GENERAL_ERROR: - PrintDebug("Could not decode given input.\n"); - return 1; - default: - PrintDebug("Unhandled error code \n"); - return 1;; - } - - length = xed_decoded_inst_get_length (&xedd); - - PrintDebug("\nThe %dth instruction:", num); - - PrintDebug("\ncategory: "); - PrintDebug(" %s\n", xed_category_enum_t2str(xed_decoded_inst_get_category(&xedd)));; - PrintDebug("ISA-extension:%s\n ",xed_extension_enum_t2str(xed_decoded_inst_get_extension(&xedd))); - PrintDebug(" instruction-length: %d\n ", xed_decoded_inst_get_length(&xedd)); - PrintDebug(" operand-size:%d\n ", xed_operand_values_get_effective_operand_width(xed_decoded_inst_operands_const(&xedd))); - PrintDebug("address-size:%d\n ", xed_operand_values_get_effective_address_width(xed_decoded_inst_operands_const(&xedd))); - PrintDebug("iform-enum-name:%s\n ",xed_iform_enum_t2str(xed_decoded_inst_get_iform_enum(&xedd))); - PrintDebug("iform-enum-name-dispatch (zero based):%d\n ", xed_decoded_inst_get_iform_enum_dispatch(&xedd)); - PrintDebug("iclass-max-iform-dispatch: %d\n ", xed_iform_max_per_iclass(xed_decoded_inst_get_iclass(&xedd))); - - // operands - // print_operands(&xedd); - - // memops - // print_memops(&xedd); - - // flags - //print_flags(&xedd); - - // attributes - //print_attributes(&xedd);*/ + + + + + +uint8_t v3_get_prefixes(uint8_t * instr, struct x86_prefixes * prefixes) { + uint8_t * instr_cursor = instr; + + while (1) { + switch (*instr_cursor) { + case 0xF0: // lock + prefixes->lock = 1; + break; + + case 0xF2: // REPNE/REPNZ + prefixes->repnz = 1; + prefixes->repne = 1; + break; + + case 0xF3: // REP or REPE/REPZ + prefixes->rep = 1; + prefixes->repe = 1; + prefixes->repz = 1; + break; + + case 0x2E: // CS override or Branch hint not taken (with Jcc instr_cursors) + prefixes->cs_override = 1; + prefixes->br_not_taken = 1; + break; + + case 0x36: // SS override + prefixes->ss_override = 1; + break; + + case 0x3E: // DS override or Branch hint taken (with Jcc instr_cursors) + prefixes->ds_override = 1; + prefixes->br_taken = 1; + break; + + case 0x26: // ES override + prefixes->es_override = 1; + break; + + case 0x64: // FS override + prefixes->fs_override = 1; + break; + + case 0x65: // GS override + prefixes->gs_override = 1; + break; + + case 0x66: // operand size override + prefixes->op_size = 1; + break; + + case 0x67: // address size override + prefixes->addr_size = 1; + break; + + default: + return (instr_cursor - instr); + } + + instr_cursor++; } +} -#endif +void v3_strip_rep_prefix(uchar_t * instr, int length) { + int read_ctr = 0; + int write_ctr = 0; + int found = 0; - return 0; + while (read_ctr < length) { + if ((!found) && + ( (instr[read_ctr] == 0xF2) || + (instr[read_ctr] == 0xF3))) { + read_ctr++; + found = 1; + } else { + instr[write_ctr] = instr[read_ctr]; + write_ctr++; + read_ctr++; + } + } } + + +static char * op_type_to_str(v3_op_type_t type) { + switch (type) { + case V3_OP_MOVCR2: return "V3_OP_MOVCR2"; + case V3_OP_MOV2CR: return "V3_OP_MOV2CR"; + case V3_OP_SMSW: return "V3_OP_SMSW"; + 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_ADC: return "V3_OP_ADC"; + case V3_OP_ADD: return "V3_OP_ADD"; + case V3_OP_AND: return "V3_OP_AND"; + case V3_OP_OR: return "V3_OP_OR"; + case V3_OP_XOR: return "V3_OP_XOR"; + case V3_OP_SUB: return "V3_OP_SUB"; + case V3_OP_INC: return "V3_OP_INC"; + case V3_OP_DEC: return "V3_OP_DEC"; + case V3_OP_NEG: return "V3_OP_NEG"; + case V3_OP_MOV: return "V3_OP_MOV"; + case V3_OP_NOT: return "V3_OP_NOT"; + case V3_OP_XCHG: return "V3_OP_XCHG"; + case V3_OP_SETB: return "V3_OP_SETB"; + case V3_OP_SETBE: return "V3_OP_SETBE"; + case V3_OP_SETL: return "V3_OP_SETL"; + case V3_OP_SETLE: return "V3_OP_SETLE"; + case V3_OP_SETNB: return "V3_OP_SETNB"; + case V3_OP_SETNBE: return "V3_OP_SETNBE"; + case V3_OP_SETNL: return "V3_OP_SETNL"; + case V3_OP_SETNLE: return "V3_OP_SETNLE"; + case V3_OP_SETNO: return "V3_OP_SETNO"; + case V3_OP_SETNP: return "V3_OP_SETNP"; + case V3_OP_SETNS: return "V3_OP_SETNS"; + case V3_OP_SETNZ: return "V3_OP_SETNZ"; + case V3_OP_SETO: return "V3_OP_SETO"; + case V3_OP_SETP: return "V3_OP_SETP"; + case V3_OP_SETS: return "V3_OP_SETS"; + case V3_OP_SETZ: return "V3_OP_SETZ"; + case V3_OP_MOVS: return "V3_OP_MOVS"; + case V3_OP_STOS: return "V3_OP_STOS"; + case V3_OP_MOVZX: return "V3_OP_MOVZX"; + case V3_OP_MOVSX: return "V3_OP_MOVSX"; + case V3_OP_INT: return "V3_OP_INT"; + case V3_INVALID_OP: + default: + return "V3_INVALID_OP"; + } +} + + +static char * operand_type_to_str(v3_operand_type_t op) { + switch (op) { + case REG_OPERAND: return "REG_OPERAND"; + case MEM_OPERAND: return "MEM_OPERAND"; + case IMM_OPERAND: return "IMM_OPERAND"; + default: + return "INVALID_OPERAND"; + } +} + + +static const ullong_t mask_1 = 0x00000000000000ffLL; +static const ullong_t mask_2 = 0x000000000000ffffLL; +static const ullong_t mask_4 = 0x00000000ffffffffLL; +static const ullong_t mask_8 = 0xffffffffffffffffLL; + + +#define MASK(val, length) ({ \ + ullong_t mask = 0x0LL; \ + switch (length) { \ + case 1: \ + mask = mask_1; \ + break; \ + case 2: \ + mask = mask_2; \ + break; \ + case 4: \ + mask = mask_4; \ + break; \ + case 8: \ + mask = mask_8; \ + break; \ + } \ + val & mask; \ + }) + +void v3_print_instr(struct x86_instr * instr) { + V3_Print("Instr: %s (Len: %d)\n", op_type_to_str(instr->op_type), instr->instr_length); + + V3_Print("Prefixes= %x\n", instr->prefixes.val); + + if (instr->is_str_op) { + V3_Print("String OP (len=%d)\n", (uint32_t)instr->str_op_length); + } + + V3_Print("Number of operands: %d\n", instr->num_operands); + + if (instr->num_operands > 0) { + V3_Print("Src Operand (%s)\n", operand_type_to_str(instr->src_operand.type)); + V3_Print("\tLen=%d (Addr: %p)\n", instr->src_operand.size, + (void *)instr->src_operand.operand); + if (instr->src_operand.type == REG_OPERAND) { + V3_Print("\tVal: 0x%llx\n", MASK(*(uint64_t *)(instr->src_operand.operand), instr->src_operand.size)); + } + } + + if (instr->num_operands > 1) { + V3_Print("Dst Operand (%s)\n", operand_type_to_str(instr->dst_operand.type)); + V3_Print("\tLen=%d (Addr: %p)\n", instr->dst_operand.size, + (void *)instr->dst_operand.operand); + if (instr->dst_operand.type == REG_OPERAND) { + V3_Print("\tVal: 0x%llx\n", MASK(*(uint64_t *)(instr->dst_operand.operand), instr->dst_operand.size)); + } + } + + if (instr->num_operands > 2) { + V3_Print("Third Operand (%s)\n", operand_type_to_str(instr->third_operand.type)); + V3_Print("\tLen=%d (Addr: %p)\n", instr->third_operand.size, + (void *)instr->third_operand.operand); + if (instr->third_operand.type == REG_OPERAND) { + V3_Print("\tVal: 0x%llx\n", MASK(*(uint64_t *)(instr->third_operand.operand), instr->third_operand.size)); + } + } +} + +