Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Release 1.0
[palacios.git] / misc / decoder_test / vmm_decoder.h
1 #ifndef __VMM_EMULATE_H
2 #define __VMM_EMULATE_H
3
4 #ifdef __V3VEE__
5
6 #include "test.h"
7 #include "vm_guest.h"
8
9
10 typedef enum {INVALID_OPERAND, REG_OPERAND, MEM_OPERAND, IMM_OPERAND} operand_type_t;
11
12 struct x86_operand {
13   addr_t operand;
14   uint_t size;
15   operand_type_t type;
16 };
17
18 struct x86_prefixes {
19   uint_t lock   : 1;  // 0xF0
20   uint_t repne  : 1;  // 0xF2
21   uint_t repnz  : 1;  // 0xF2
22   uint_t rep    : 1;  // 0xF3
23   uint_t repe   : 1;  // 0xF3
24   uint_t repz   : 1;  // 0xF3
25   uint_t cs_override : 1;  // 0x2E
26   uint_t ss_override : 1;  // 0x36
27   uint_t ds_override : 1;  // 0x3E
28   uint_t es_override : 1;  // 0x26
29   uint_t fs_override : 1;  // 0x64
30   uint_t gs_override : 1;  // 0x65
31   uint_t br_not_taken : 1;  // 0x2E
32   uint_t br_takend   : 1;  // 0x3E
33   uint_t op_size     : 1;  // 0x66
34   uint_t addr_size   : 1;  // 0x67
35 };
36
37
38 struct x86_instr {
39   struct x86_prefixes prefixes;
40   uint_t instr_length;
41   addr_t opcode;    // a pointer to the V3_OPCODE_[*] arrays defined below
42   uint_t num_operands;
43   struct x86_operand src_operand;
44   struct x86_operand dst_operand;
45   struct x86_operand third_operand;
46   void * decoder_data;
47 };
48
49
50   /************************/
51  /* EXTERNAL DECODER API */
52 /************************/
53 /* 
54    This is an External API definition that must be implemented by a decoder
55 */
56
57
58 /* 
59  * Initializes a decoder
60  */
61 int init_decoder();
62
63 /* 
64  * Decodes an instruction 
65  * All addresses in arguments are in the host address space
66  * instr_ptr is the host address of the instruction 
67  * IMPORTANT: make sure the instr_ptr is in contiguous host memory
68  *   ie. Copy it to a buffer before the call
69  */
70 int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * instr);
71
72 /* 
73  * Encodes an instruction
74  * All addresses in arguments are in the host address space
75  * The instruction is encoded from the struct, and copied into a 15 byte host buffer
76  * referenced by instr_buf
77  * any unused bytes at the end of instr_buf will be filled with nops
78  * IMPORTANT: instr_buf must be allocated and 15 bytes long
79  */
80 int v3_encode(struct guest_info * info, struct x86_instr * instr, char * instr_buf);
81
82
83
84
85
86
87
88
89
90 /* 
91  * JRL: Some of this was taken from the Xen sources... 
92  */
93
94 #define PACKED __attribute__((packed))
95
96 #define MODRM_MOD(x) ((x >> 6) & 0x3)
97 #define MODRM_REG(x) ((x >> 3) & 0x7)
98 #define MODRM_RM(x)  (x & 0x7)
99
100 struct modrm_byte {
101   uint_t rm   :   3 PACKED;
102   uint_t reg  :   3 PACKED;
103   uint_t mod  :   2 PACKED;
104 };
105
106
107 #define SIB_BASE(x) ((x >> 6) & 0x3)
108 #define SIB_INDEX(x) ((x >> 3) & 0x7)
109 #define SIB_SCALE(x) (x & 0x7)
110
111 struct sib_byte {
112   uint_t base     :   3 PACKED;
113   uint_t index    :   3 PACKED;
114   uint_t scale    :   2 PACKED;
115 };
116
117
118
119 #define MAKE_INSTR(nm, ...) static  const uchar_t V3_OPCODE_##nm[] = { __VA_ARGS__ }
120
121 /* 
122  * Here's how it works:
123  * First byte: Length. 
124  * Following bytes: Opcode bytes. 
125  * Special case: Last byte, if zero, doesn't need to match. 
126  */
127 MAKE_INSTR(INVD,   2, 0x0f, 0x08);
128 MAKE_INSTR(CPUID,  2, 0x0f, 0xa2);
129 MAKE_INSTR(RDMSR,  2, 0x0f, 0x32);
130 MAKE_INSTR(WRMSR,  2, 0x0f, 0x30);
131 MAKE_INSTR(RDTSC,  2, 0x0f, 0x31);
132 MAKE_INSTR(RDTSCP, 3, 0x0f, 0x01, 0xf9);
133 MAKE_INSTR(CLI,    1, 0xfa);
134 MAKE_INSTR(STI,    1, 0xfb);
135 MAKE_INSTR(RDPMC,  2, 0x0f, 0x33);
136 MAKE_INSTR(CLGI,   3, 0x0f, 0x01, 0xdd);
137 MAKE_INSTR(STGI,   3, 0x0f, 0x01, 0xdc);
138 MAKE_INSTR(VMRUN,  3, 0x0f, 0x01, 0xd8);
139 MAKE_INSTR(VMLOAD, 3, 0x0f, 0x01, 0xda);
140 MAKE_INSTR(VMSAVE, 3, 0x0f, 0x01, 0xdb);
141 MAKE_INSTR(VMCALL, 3, 0x0f, 0x01, 0xd9);
142 MAKE_INSTR(PAUSE,  2, 0xf3, 0x90);
143 MAKE_INSTR(SKINIT, 3, 0x0f, 0x01, 0xde);
144 MAKE_INSTR(MOV2CR, 3, 0x0f, 0x22, 0x00);
145 MAKE_INSTR(MOVCR2, 3, 0x0f, 0x20, 0x00);
146 MAKE_INSTR(MOV2DR, 3, 0x0f, 0x23, 0x00);
147 MAKE_INSTR(MOVDR2, 3, 0x0f, 0x21, 0x00);
148 MAKE_INSTR(PUSHF,  1, 0x9c);
149 MAKE_INSTR(POPF,   1, 0x9d);
150 MAKE_INSTR(RSM,    2, 0x0f, 0xaa);
151 MAKE_INSTR(INVLPG, 3, 0x0f, 0x01, 0x00);
152 MAKE_INSTR(INVLPGA,3, 0x0f, 0x01, 0xdf);
153 MAKE_INSTR(HLT,    1, 0xf4);
154 MAKE_INSTR(CLTS,   2, 0x0f, 0x06);
155 MAKE_INSTR(LMSW,   3, 0x0f, 0x01, 0x00);
156 MAKE_INSTR(SMSW,   3, 0x0f, 0x01, 0x00);
157
158
159 #define PREFIX_LOCK         0xF0
160 #define PREFIX_REPNE        0xF2
161 #define PREFIX_REPNZ        0xF2
162 #define PREFIX_REP          0xF3
163 #define PREFIX_REPE         0xF3
164 #define PREFIX_REPZ         0xF3
165 #define PREFIX_CS_OVERRIDE  0x2E
166 #define PREFIX_SS_OVERRIDE  0x36
167 #define PREFIX_DS_OVERRIDE  0x3E
168 #define PREFIX_ES_OVERRIDE  0x26
169 #define PREFIX_FS_OVERRIDE  0x64
170 #define PREFIX_GS_OVERRIDE  0x65
171 #define PREFIX_BR_NOT_TAKEN 0x2E
172 #define PREFIX_BR_TAKEN     0x3E
173 #define PREFIX_OP_SIZE      0x66
174 #define PREFIX_ADDR_SIZE    0x67
175
176 int opcode_cmp(const uchar_t * op1, const uchar_t * op2);
177
178
179 static inline int is_prefix_byte(char byte) {
180   switch (byte) {
181   case 0xF0:      // lock
182   case 0xF2:      // REPNE/REPNZ
183   case 0xF3:      // REP or REPE/REPZ
184   case 0x2E:      // CS override or Branch hint not taken (with Jcc instrs)
185   case 0x36:      // SS override
186   case 0x3E:      // DS override or Branch hint taken (with Jcc instrs)
187   case 0x26:      // ES override
188   case 0x64:      // FS override
189   case 0x65:      // GS override
190     //case 0x2E:      // branch not taken hint
191     //  case 0x3E:      // branch taken hint
192   case 0x66:      // operand size override
193   case 0x67:      // address size override
194     return 1;
195     break;
196   default:
197     return 0;
198     break;
199   }
200 }
201
202
203 static inline v3_reg_t get_gpr_mask(struct guest_info * info) {
204   switch (info->cpu_mode) {
205   case REAL: 
206     return 0xffff;
207     break;
208   case PROTECTED:
209     return 0xffffffff;
210   default:
211     V3_ASSERT(0);
212     return 0;
213   }
214 }
215
216
217 static inline addr_t get_addr_linear(struct guest_info * info, addr_t addr, struct v3_segment * seg) {
218   switch (info->cpu_mode) {
219   case REAL:
220     // It appears that the segment values are computed and cached in the vmcb structure 
221     // We Need to check this for Intel
222     /*   return addr + (seg->selector << 4);
223          break;*/
224
225   case PROTECTED:
226     return addr + seg->base;
227     break;
228   default:
229     V3_ASSERT(0);
230     return 0;
231   }
232 }
233
234
235 typedef enum {INVALID_ADDR_TYPE, REG, DISP0, DISP8, DISP16, DISP32} modrm_mode_t;
236 typedef enum {INVALID_REG_SIZE, REG64, REG32, REG16, REG8} reg_size_t;
237
238
239
240
241
242
243 struct v3_gprs;
244
245 static inline addr_t decode_register(struct v3_gprs * gprs, char reg_code, reg_size_t reg_size) {
246   addr_t reg_addr;
247
248   switch (reg_code) {
249   case 0:
250     reg_addr = (addr_t)&(gprs->rax);
251     break;
252   case 1:
253     reg_addr = (addr_t)&(gprs->rcx);
254     break;
255   case 2:
256     reg_addr = (addr_t)&(gprs->rdx);
257     break;
258   case 3:
259     reg_addr = (addr_t)&(gprs->rbx);
260     break;
261   case 4:
262     if (reg_size == REG8) {
263       reg_addr = (addr_t)&(gprs->rax) + 1;
264     } else {
265       reg_addr = (addr_t)&(gprs->rsp);
266     }
267     break;
268   case 5:
269     if (reg_size == REG8) {
270       reg_addr = (addr_t)&(gprs->rcx) + 1;
271     } else {
272       reg_addr = (addr_t)&(gprs->rbp);
273     }
274     break;
275   case 6:
276     if (reg_size == REG8) {
277       reg_addr = (addr_t)&(gprs->rdx) + 1;
278     } else {
279       reg_addr = (addr_t)&(gprs->rsi);
280     }
281     break;
282   case 7:
283     if (reg_size == REG8) {
284       reg_addr = (addr_t)&(gprs->rbx) + 1;
285     } else {
286       reg_addr = (addr_t)&(gprs->rdi);
287     }
288     break;
289   default:
290     reg_addr = 0;
291     break;
292   }
293
294   return reg_addr;
295 }
296
297
298
299
300
301 #endif // !__V3VEE__
302
303
304 #endif