X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Finclude%2Fpalacios%2Fvmm_decoder.h;h=b6e65e6ad2be7e0c590eba630cc2032bae0dd272;hb=7617d3cee4bd93b90558206b1bb1681c07f0396a;hp=aeb758d553b0e71a4e378ddc56c67215f4174d89;hpb=f7cc83b3bae64c853f5b7b63e2830b1ea92dfed9;p=palacios.git diff --git a/palacios/include/palacios/vmm_decoder.h b/palacios/include/palacios/vmm_decoder.h index aeb758d..b6e65e6 100644 --- a/palacios/include/palacios/vmm_decoder.h +++ b/palacios/include/palacios/vmm_decoder.h @@ -1,17 +1,16 @@ +/* (c) 2008, Jack Lange */ +/* (c) 2008, The V3VEE Project */ + #ifndef __VMM_EMULATE_H #define __VMM_EMULATE_H -#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 - */ +#ifdef __V3VEE__ -typedef enum {INVALID_OPERAND, REG_OPERAND, MEM_OPERAND} operand_type_t; +#include +#include -int parse(); +typedef enum {INVALID_OPERAND, REG_OPERAND, MEM_OPERAND, IMM_OPERAND} operand_type_t; struct x86_operand { addr_t operand; @@ -19,23 +18,91 @@ struct x86_operand { operand_type_t type; }; -struct x86_prefix_list { - uint_t lock : 1; +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_takend : 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; + addr_t opcode; // a pointer to the V3_OPCODE_[*] arrays defined below + uint_t num_operands; + struct x86_operand dst_operand; + struct x86_operand src_operand; + struct x86_operand third_operand; + void * decoder_data; }; -/* This parses an instruction + +struct basic_instr_info { + uint_t instr_length; + uint_t op_size; + uint_t str_op : 1; + uint_t has_rep : 1; +}; + + + + /************************/ + /* EXTERNAL DECODER API */ +/************************/ +/* + This is an External API definition that must be implemented by a decoder +*/ + + +/* + * Initializes a decoder + */ +int 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_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_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_basic_mem_decode(struct guest_info * info, addr_t instr_ptr, struct basic_instr_info * instr_info); + + + +/* Removes a rep prefix in place */ +void strip_rep_prefix(uchar_t * instr, int length); + /* @@ -67,7 +134,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,6 +191,9 @@ MAKE_INSTR(SMSW, 3, 0x0f, 0x01, 0x00); #define PREFIX_OP_SIZE 0x66 #define PREFIX_ADDR_SIZE 0x67 +int opcode_cmp(const uchar_t * op1, const uchar_t * op2); + + static inline int is_prefix_byte(char byte) { switch (byte) { case 0xF0: // lock @@ -257,14 +327,14 @@ static inline operand_type_t decode_operands16(struct v3_gprs * gprs, // input/o operand_type_t addr_type = INVALID_OPERAND; char * instr_cursor = modrm_instr; - PrintDebug("ModRM mod=%d\n", modrm->mod); + // PrintDebug("ModRM mod=%d\n", modrm->mod); instr_cursor += 1; if (modrm->mod == 3) { mod_mode = REG; addr_type = REG_OPERAND; - PrintDebug("first operand = Register (RM=%d)\n",modrm->rm); + //PrintDebug("first operand = Register (RM=%d)\n",modrm->rm); *first_operand = decode_register(gprs, modrm->rm, reg_size); @@ -355,7 +425,7 @@ static inline operand_type_t decode_operands32(struct v3_gprs * gprs, // input/o mod_mode = REG; addr_type = REG_OPERAND; - PrintDebug("first operand = Register (RM=%d)\n",modrm->rm); + // PrintDebug("first operand = Register (RM=%d)\n",modrm->rm); *first_operand = decode_register(gprs, modrm->rm, reg_size); @@ -503,5 +573,7 @@ static inline operand_type_t decode_operands32(struct v3_gprs * gprs, // input/o +#endif // !__V3VEE__ + #endif