X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Finclude%2Fpalacios%2Fvmm_instr_decoder.h;h=207da43654fe513a75283a936bd993b5a3edb3f3;hb=fe9b69407ae9ac7aeb6a9d1500c89d48953864ac;hp=b9dc7fdad3f0b068eef6000d0706ae9c96eaf914;hpb=847838d7621455a02df5d657914d7da163718234;p=palacios.git diff --git a/palacios/include/palacios/vmm_instr_decoder.h b/palacios/include/palacios/vmm_instr_decoder.h index b9dc7fd..207da43 100644 --- a/palacios/include/palacios/vmm_instr_decoder.h +++ b/palacios/include/palacios/vmm_instr_decoder.h @@ -23,11 +23,6 @@ /* .... Giant fucking switch tables */ - - - - - typedef enum { INVALID_INSTR, LMSW, @@ -140,16 +135,31 @@ typedef enum { } op_form_t; +static int get_addr_width(struct guest_info * info, struct x86_instr * instr, + op_form_t form) { + switch (v3_get_vm_cpu_mode(info)) { + case REAL: + return (instr->prefixes.addr_size) ? 4 : 2; + case PROTECTED: + case PROTECTED_PAE: + return (instr->prefixes.addr_size) ? 2 : 4; + case LONG_32_COMPAT: + case LONG: + default: + PrintError("Unsupported CPU mode: %d\n", info->cpu_mode); + return -1; + } +} -static int get_operand_width(struct guest_info * info, struct x86_instr * instr, op_form_t form) { +static int get_operand_width(struct guest_info * info, struct x86_instr * instr, + op_form_t form) { switch (form) { case CLTS: case HLT: return 0; - case MOV_MEM2_8: case MOV_2MEM_8: case MOV_MEM2AL_8: @@ -200,7 +210,6 @@ static int get_operand_width(struct guest_info * info, struct x86_instr * instr, case SETO: return 1; - case LMSW: case SMSW: return 2; @@ -256,7 +265,6 @@ static int get_operand_width(struct guest_info * info, struct x86_instr * instr, return -1; } - case INVLPG: switch (v3_get_vm_cpu_mode(info)) { case REAL: @@ -272,7 +280,6 @@ static int get_operand_width(struct guest_info * info, struct x86_instr * instr, return -1; } - case PUSHF: case POPF: switch (v3_get_vm_cpu_mode(info)) { @@ -304,7 +311,6 @@ static int get_operand_width(struct guest_info * info, struct x86_instr * instr, return -1; } - case MOV_SR2: case MOV_2SR: default: @@ -412,16 +418,17 @@ static inline int decode_gpr(struct v3_gprs * gprs, val; \ }) -static int decode_rm_operand16(struct v3_gprs * gprs, - char * modrm_instr, - struct x86_operand * operand, - uint8_t * reg_code) { +static int decode_rm_operand16(struct guest_info * core, + uint8_t * modrm_instr, + struct x86_instr * instr, + struct x86_operand * operand, + uint8_t * reg_code) { - + struct v3_gprs * gprs = &(core->vm_regs); struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr; addr_t base_addr = 0; modrm_mode_t mod_mode = 0; - char * instr_cursor = modrm_instr; + uint8_t * instr_cursor = modrm_instr; // PrintDebug("ModRM mod=%d\n", modrm->mod); @@ -436,6 +443,7 @@ static int decode_rm_operand16(struct v3_gprs * gprs, decode_gpr(gprs, modrm->rm, operand); } else { + struct v3_segment * seg = NULL; operand->type = MEM_OPERAND; @@ -489,7 +497,23 @@ static int decode_rm_operand16(struct v3_gprs * gprs, instr_cursor += 2; } - operand->operand = base_addr; + + // get appropriate segment + if (instr->prefixes.cs_override) { + seg = &(core->segments.cs); + } else if (instr->prefixes.es_override) { + seg = &(core->segments.es); + } else if (instr->prefixes.ss_override) { + seg = &(core->segments.ss); + } else if (instr->prefixes.fs_override) { + seg = &(core->segments.fs); + } else if (instr->prefixes.gs_override) { + seg = &(core->segments.gs); + } else { + seg = &(core->segments.ds); + } + + operand->operand = get_addr_linear(core, base_addr, seg); } @@ -498,12 +522,14 @@ static int decode_rm_operand16(struct v3_gprs * gprs, // returns num_bytes parsed -static int decode_rm_operand32(struct v3_gprs * gprs, // input/output - uint8_t * modrm_instr, // input +static int decode_rm_operand32(struct guest_info * core, + uint8_t * modrm_instr, + struct x86_instr * instr, struct x86_operand * operand, uint8_t * reg_code) { - - uchar_t * instr_cursor = modrm_instr; + + struct v3_gprs * gprs = &(core->vm_regs); + uint8_t * instr_cursor = modrm_instr; struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr; addr_t base_addr = 0; modrm_mode_t mod_mode = 0; @@ -521,6 +547,7 @@ static int decode_rm_operand32(struct v3_gprs * gprs, // input/output decode_gpr(gprs, modrm->rm, operand); } else { + struct v3_segment * seg = NULL; operand->type = MEM_OPERAND; @@ -641,8 +668,22 @@ static int decode_rm_operand32(struct v3_gprs * gprs, // input/output instr_cursor += 4; } - - operand->operand = base_addr; + // get appropriate segment + if (instr->prefixes.cs_override) { + seg = &(core->segments.cs); + } else if (instr->prefixes.es_override) { + seg = &(core->segments.es); + } else if (instr->prefixes.ss_override) { + seg = &(core->segments.ss); + } else if (instr->prefixes.fs_override) { + seg = &(core->segments.fs); + } else if (instr->prefixes.gs_override) { + seg = &(core->segments.gs); + } else { + seg = &(core->segments.ds); + } + + operand->operand = get_addr_linear(core, base_addr, seg); } @@ -655,15 +696,16 @@ static int decode_rm_operand32(struct v3_gprs * gprs, // input/output static int decode_rm_operand(struct guest_info * core, uint8_t * instr_ptr, // input + struct x86_instr * instr, struct x86_operand * operand, uint8_t * reg_code) { v3_cpu_mode_t mode = v3_get_vm_cpu_mode(core); if (mode == REAL) { - return decode_rm_operand16(&(core->vm_regs), instr_ptr, operand, reg_code); + return decode_rm_operand16(core, instr_ptr, instr, operand, reg_code); } else if ((mode == PROTECTED) || (mode == PROTECTED_PAE)) { - return decode_rm_operand32(&(core->vm_regs), instr_ptr, operand, reg_code); + return decode_rm_operand32(core, instr_ptr, instr, operand, reg_code); } else { PrintError("Invalid CPU_MODE (%d)\n", mode); return -1; @@ -672,7 +714,9 @@ static int decode_rm_operand(struct guest_info * core, -static inline op_form_t op_code_to_form_0f(uint8_t * instr) { +static inline op_form_t op_code_to_form_0f(uint8_t * instr, int * length) { + *length += 1; + switch (instr[1]) { case 0x01: { struct modrm_byte * modrm = (struct modrm_byte *)&(instr[2]); @@ -751,7 +795,9 @@ static inline op_form_t op_code_to_form_0f(uint8_t * instr) { } -static op_form_t op_code_to_form(uint8_t * instr) { +static op_form_t op_code_to_form(uint8_t * instr, int * length) { + *length += 1; + switch (instr[0]) { case 0x00: return ADD_2MEM_8; @@ -773,7 +819,7 @@ static op_form_t op_code_to_form(uint8_t * instr) { case 0x0f: - return op_code_to_form_0f(instr); + return op_code_to_form_0f(instr, length); case 0x10: return ADC_2MEM_8;