X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Finclude%2Fpalacios%2Fvmm_decoder.h;h=009fc588f7c06fd25f6762a05d25672e5cb6140c;hb=0733f93d0fc8a20528a9ab2f21704bee5562b302;hp=ef08031875a4d7ec0fe62e8e0e77c2949fa77ebd;hpb=9dd0a80f28ca47a1fb69992dcd96e7526bf5175c;p=palacios.git diff --git a/palacios/include/palacios/vmm_decoder.h b/palacios/include/palacios/vmm_decoder.h index ef08031..009fc58 100644 --- a/palacios/include/palacios/vmm_decoder.h +++ b/palacios/include/palacios/vmm_decoder.h @@ -1,41 +1,137 @@ -#ifndef __VMM_EMULATE_H -#define __VMM_EMULATE_H +/* + * 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". + */ + +#ifndef __VMM_DECODER_H +#define __VMM_DECODER_H + +#ifdef __V3VEE__ + #include #include -/* - * This is where we do the hideous X86 instruction parsing among other things - * We can parse out the instruction prefixes, as well as decode the operands - */ -typedef enum {INVALID_OPERAND, REG_OPERAND, MEM_OPERAND} operand_type_t; +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_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_type_t; -int parse(); +typedef enum {INVALID_OPERAND, REG_OPERAND, MEM_OPERAND, IMM_OPERAND} v3_operand_type_t; struct x86_operand { addr_t operand; uint_t size; - operand_type_t type; + v3_operand_type_t type; +}; + +struct x86_prefixes { + uint_t lock : 1; // 0xF0 + uint_t repne : 1; // 0xF2 + uint_t repnz : 1; // 0xF2 + uint_t rep : 1; // 0xF3 + uint_t repe : 1; // 0xF3 + uint_t repz : 1; // 0xF3 + uint_t cs_override : 1; // 0x2E + uint_t ss_override : 1; // 0x36 + uint_t ds_override : 1; // 0x3E + uint_t es_override : 1; // 0x26 + uint_t fs_override : 1; // 0x64 + uint_t gs_override : 1; // 0x65 + uint_t br_not_taken : 1; // 0x2E + uint_t br_taken : 1; // 0x3E + uint_t op_size : 1; // 0x66 + uint_t addr_size : 1; // 0x67 +}; + + +struct x86_instr { + struct x86_prefixes prefixes; + uint_t instr_length; + v3_op_type_t op_type; + uint_t num_operands; + struct x86_operand dst_operand; + struct x86_operand src_operand; + struct x86_operand third_operand; + addr_t str_op_length; + addr_t is_str_op; + void * decoder_data; }; -struct x86_prefix_list { - uint_t lock : 1; + +struct basic_instr_info { + uint_t instr_length; + uint_t op_size; + uint_t str_op : 1; + uint_t has_rep : 1; }; -/* This parses an instruction + + + /************************/ + /* EXTERNAL DECODER API */ +/************************/ +/* + This is an External API definition that must be implemented by a decoder +*/ + + +/* + * Initializes a decoder + */ +int v3_init_decoder(); + +/* + * Decodes an instruction * All addresses in arguments are in the host address space + * instr_ptr is the host address of the instruction + * IMPORTANT: make sure the instr_ptr is in contiguous host memory + * ie. Copy it to a buffer before the call */ -int v3_parse_instr(struct guest_info * info, // input - char * instr_ptr, // input - uint_t * instr_length, // output - addr_t * opcode, // output - uint_t * opcode_length, // output - struct x86_prefix_list * prefixes, // output - struct x86_operand * src_operand, // output - struct x86_operand * dst_operand, // output - struct x86_operand * extra_operand); // output - +int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * instr); + +/* + * Encodes an instruction + * All addresses in arguments are in the host address space + * The instruction is encoded from the struct, and copied into a 15 byte host buffer + * referenced by instr_buf + * any unused bytes at the end of instr_buf will be filled with nops + * IMPORTANT: instr_buf must be allocated and 15 bytes long + */ +int v3_encode(struct guest_info * info, struct x86_instr * instr, char * instr_buf); + + +/* + * Gets the operand size for a memory operation + * + */ +int v3_basic_mem_decode(struct guest_info * info, addr_t instr_ptr, struct basic_instr_info * instr_info); + + + +/* Removes a rep prefix in place */ +void v3_strip_rep_prefix(uchar_t * instr, int length); +void v3_get_prefixes(uchar_t * instr, struct x86_prefixes * prefixes); /* @@ -67,7 +163,7 @@ struct sib_byte { -#define MAKE_INSTR(nm, ...) static const uchar_t OPCODE_##nm[] = { __VA_ARGS__ } +#define MAKE_INSTR(nm, ...) static const uchar_t V3_OPCODE_##nm[] = { __VA_ARGS__ } /* * Here's how it works: @@ -124,7 +220,10 @@ MAKE_INSTR(SMSW, 3, 0x0f, 0x01, 0x00); #define PREFIX_OP_SIZE 0x66 #define PREFIX_ADDR_SIZE 0x67 -static inline int is_prefix_byte(char byte) { +int v3_opcode_cmp(const uchar_t * op1, const uchar_t * op2); + + +static inline int is_prefix_byte(uchar_t byte) { switch (byte) { case 0xF0: // lock case 0xF2: // REPNE/REPNZ @@ -154,10 +253,14 @@ static inline v3_reg_t get_gpr_mask(struct guest_info * info) { return 0xffff; break; case PROTECTED: + case PROTECTED_PAE: return 0xffffffff; + case LONG: + case LONG_32_COMPAT: + case LONG_16_COMPAT: default: - V3_ASSERT(0); - return 0; + PrintError("Unsupported Address Mode\n"); + return -1; } } @@ -171,11 +274,20 @@ static inline addr_t get_addr_linear(struct guest_info * info, addr_t addr, stru break;*/ case PROTECTED: + case PROTECTED_PAE: + case LONG_32_COMPAT: return addr + seg->base; break; + + case LONG: + // In long mode the segment bases are disregarded (forced to 0), unless using + // FS or GS, then the base addresses are added + return addr + seg->base; + + case LONG_16_COMPAT: default: - V3_ASSERT(0); - return 0; + PrintError("Unsupported CPU Mode: %d\n", info->cpu_mode); + return -1; } } @@ -244,7 +356,7 @@ static inline addr_t decode_register(struct v3_gprs * gprs, char reg_code, reg_s -static inline operand_type_t decode_operands16(struct v3_gprs * gprs, // input/output +static inline v3_operand_type_t decode_operands16(struct v3_gprs * gprs, // input/output char * modrm_instr, // input int * offset, // output addr_t * first_operand, // output @@ -254,7 +366,7 @@ static inline operand_type_t decode_operands16(struct v3_gprs * gprs, // input/o struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr; addr_t base_addr = 0; modrm_mode_t mod_mode = 0; - operand_type_t addr_type = INVALID_OPERAND; + v3_operand_type_t addr_type = INVALID_OPERAND; char * instr_cursor = modrm_instr; // PrintDebug("ModRM mod=%d\n", modrm->mod); @@ -333,19 +445,19 @@ static inline operand_type_t decode_operands16(struct v3_gprs * gprs, // input/o -static inline operand_type_t decode_operands32(struct v3_gprs * gprs, // input/output - char * modrm_instr, // input +static inline v3_operand_type_t decode_operands32(struct v3_gprs * gprs, // input/output + uchar_t * modrm_instr, // input int * offset, // output addr_t * first_operand, // output addr_t * second_operand, // output reg_size_t reg_size) { // input - char * instr_cursor = modrm_instr; + uchar_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; uint_t has_sib_byte = 0; - operand_type_t addr_type = INVALID_OPERAND; + v3_operand_type_t addr_type = INVALID_OPERAND; @@ -376,7 +488,7 @@ static inline operand_type_t decode_operands32(struct v3_gprs * gprs, // input/o base_addr = gprs->rax; break; case 1: - base_addr = gprs->rcx; + base_addr = gprs->rcx; break; case 2: base_addr = gprs->rdx; @@ -503,5 +615,7 @@ static inline operand_type_t decode_operands32(struct v3_gprs * gprs, // input/o +#endif // !__V3VEE__ + #endif