2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
11 * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Jack Lange <jarusl@cs.northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20 #ifndef __VMM_DECODER_H
21 #define __VMM_DECODER_H
25 #include <palacios/vm_guest.h>
26 #include <palacios/vmm.h>
29 typedef enum { V3_INVALID_OP,
30 V3_OP_MOVCR2, V3_OP_MOV2CR, V3_OP_SMSW, V3_OP_LMSW, V3_OP_CLTS,
32 /* 441-tm: adding CMP, POP, JLE, CALL, TEST*/
33 V3_OP_CMP, V3_OP_POP, V3_OP_JLE, V3_OP_CALL, V3_OP_TEST, V3_OP_PUSH,
34 V3_OP_JAE, V3_OP_JMP, V3_OP_JNZ, V3_OP_JZ, V3_OP_LEA, V3_OP_IMUL,
35 V3_OP_RET, V3_OP_JL, V3_OP_CMOVZ, V3_OP_MOVSXD, V3_OP_JNS,
36 V3_OP_CMOVS, V3_OP_SHL,
38 V3_OP_ADC, V3_OP_ADD, V3_OP_AND, V3_OP_OR, V3_OP_XOR, V3_OP_SUB,
39 V3_OP_INC, V3_OP_DEC, V3_OP_NEG, V3_OP_MOV, V3_OP_NOT, V3_OP_XCHG,
40 V3_OP_SETB, V3_OP_SETBE, V3_OP_SETL, V3_OP_SETLE, V3_OP_SETNB,
41 V3_OP_SETNBE, V3_OP_SETNL, V3_OP_SETNLE, V3_OP_SETNO, V3_OP_SETNP,
42 V3_OP_SETNS, V3_OP_SETNZ, V3_OP_SETO, V3_OP_SETP, V3_OP_SETS,
43 V3_OP_SETZ, V3_OP_MOVS, V3_OP_STOS, V3_OP_MOVZX, V3_OP_MOVSX, V3_OP_INT } v3_op_type_t;
46 typedef enum {INVALID_OPERAND, REG_OPERAND, MEM_OPERAND, IMM_OPERAND} v3_operand_type_t;
51 v3_operand_type_t type;
52 uint8_t read : 1; // This operand value will be read by the instruction
53 uint8_t write : 1; // This operand value will be written to by the instruction
54 } __attribute__((packed));
61 uint32_t lock : 1; // 0xF0
62 uint32_t repne : 1; // 0xF2
63 uint32_t repnz : 1; // 0xF2
64 uint32_t rep : 1; // 0xF3
65 uint32_t repe : 1; // 0xF3
66 uint32_t repz : 1; // 0xF3
67 uint32_t cs_override : 1; // 0x2E
68 uint32_t ss_override : 1; // 0x36
69 uint32_t ds_override : 1; // 0x3E
70 uint32_t es_override : 1; // 0x26
71 uint32_t fs_override : 1; // 0x64
72 uint32_t gs_override : 1; // 0x65
73 uint32_t br_not_taken : 1; // 0x2E
74 uint32_t br_taken : 1; // 0x3E
75 uint32_t op_size : 1; // 0x66
76 uint32_t addr_size : 1; // 0x67
80 uint32_t rex_rm : 1; // REX.B
81 uint32_t rex_sib_idx : 1; // REX.X
82 uint32_t rex_reg : 1; // REX.R
83 uint32_t rex_op_size : 1; // REX.W
86 } __attribute__((packed));
87 } __attribute__((packed));
88 } __attribute__((packed));
92 struct x86_prefixes prefixes;
96 struct x86_operand dst_operand;
97 struct x86_operand src_operand;
98 struct x86_operand third_operand;
104 /************************/
105 /* EXTERNAL DECODER API */
106 /************************/
108 This is an External API definition that must be implemented by a decoder
113 * Initializes a decoder
115 int v3_init_decoder(struct guest_info * core);
116 int v3_deinit_decoder(struct guest_info * core);
119 * Decodes an instruction
120 * All addresses in arguments are in the host address space
121 * instr_ptr is the host address of the instruction
122 * IMPORTANT: make sure the instr_ptr is in contiguous host memory
123 * ie. Copy it to a buffer before the call
125 int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * instr);
128 * Encodes an instruction
129 * All addresses in arguments are in the host address space
130 * The instruction is encoded from the struct, and copied into a 15 byte host buffer
131 * referenced by instr_buf
132 * any unused bytes at the end of instr_buf will be filled with nops
133 * IMPORTANT: instr_buf must be allocated and 15 bytes long
135 int v3_encode(struct guest_info * info, struct x86_instr * instr, uint8_t * instr_buf);
139 /* Removes a rep prefix in place */
140 void v3_strip_rep_prefix(uint8_t * instr, int length);
141 uint8_t v3_get_prefixes(uint8_t * instr, struct x86_prefixes * prefixes);
144 void v3_print_instr(struct x86_instr * instr);
147 #define PREFIX_LOCK 0xF0
148 #define PREFIX_REPNE 0xF2
149 #define PREFIX_REPNZ 0xF2
150 #define PREFIX_REP 0xF3
151 #define PREFIX_REPE 0xF3
152 #define PREFIX_REPZ 0xF3
153 #define PREFIX_CS_OVERRIDE 0x2E
154 #define PREFIX_SS_OVERRIDE 0x36
155 #define PREFIX_DS_OVERRIDE 0x3E
156 #define PREFIX_ES_OVERRIDE 0x26
157 #define PREFIX_FS_OVERRIDE 0x64
158 #define PREFIX_GS_OVERRIDE 0x65
159 #define PREFIX_BR_NOT_TAKEN 0x2E
160 #define PREFIX_BR_TAKEN 0x3E
161 #define PREFIX_OP_SIZE 0x66
162 #define PREFIX_ADDR_SIZE 0x67
167 static inline int is_prefix_byte(uchar_t byte) {
170 case 0xF2: // REPNE/REPNZ
171 case 0xF3: // REP or REPE/REPZ
172 case 0x2E: // CS override or Branch hint not taken (with Jcc instrs)
173 case 0x36: // SS override
174 case 0x3E: // DS override or Branch hint taken (with Jcc instrs)
175 case 0x26: // ES override
176 case 0x64: // FS override
177 case 0x65: // GS override
178 //case 0x2E: // branch not taken hint
179 // case 0x3E: // branch taken hint
180 case 0x66: // operand size override
181 case 0x67: // address size override
191 static inline v3_reg_t get_gpr_mask(struct guest_info * info) {
192 switch (info->cpu_mode) {
202 return 0xffffffffffffffffLL;
204 PrintError(info->vm_info, info, "Unsupported Address Mode\n");
211 static inline addr_t get_addr_linear(struct guest_info * info, addr_t addr, struct v3_segment * seg) {
212 switch (info->cpu_mode) {
214 return ((seg->selector & 0xffff) << 4) + (addr & 0xffff);
220 return addr + seg->base;
224 uint64_t seg_base = 0;
226 // In long mode the segment bases are disregarded (forced to 0), unless using
227 // FS or GS, then the base addresses are added
230 seg_base = seg->base;
233 return addr + seg_base;
237 PrintError(info->vm_info, info,"Unsupported CPU Mode: %d\n", info->cpu_mode);