3 * This file is part of the Palacios Virtual Machine Monitor developed
4 * by the V3VEE Project with funding from the United States National
5 * Science Foundation and the Department of Energy.
7 * The V3VEE Project is a joint project between Northwestern University
8 * and the University of New Mexico. You can find out more at
11 * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
12 * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
13 * All rights reserved.
15 * Author: Jack Lange <jarusl@cs.northwestern.edu>
17 * This is free software. You are permitted to use,
18 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
21 #ifndef __VMM_DECODER_H
22 #define __VMM_DECODER_H
26 #include <palacios/vm_guest.h>
27 #include <palacios/vmm.h>
30 typedef enum {INVALID_OPERAND, REG_OPERAND, MEM_OPERAND, IMM_OPERAND} operand_type_t;
39 uint_t lock : 1; // 0xF0
40 uint_t repne : 1; // 0xF2
41 uint_t repnz : 1; // 0xF2
42 uint_t rep : 1; // 0xF3
43 uint_t repe : 1; // 0xF3
44 uint_t repz : 1; // 0xF3
45 uint_t cs_override : 1; // 0x2E
46 uint_t ss_override : 1; // 0x36
47 uint_t ds_override : 1; // 0x3E
48 uint_t es_override : 1; // 0x26
49 uint_t fs_override : 1; // 0x64
50 uint_t gs_override : 1; // 0x65
51 uint_t br_not_taken : 1; // 0x2E
52 uint_t br_takend : 1; // 0x3E
53 uint_t op_size : 1; // 0x66
54 uint_t addr_size : 1; // 0x67
59 struct x86_prefixes prefixes;
61 addr_t opcode; // a pointer to the V3_OPCODE_[*] arrays defined below
63 struct x86_operand dst_operand;
64 struct x86_operand src_operand;
65 struct x86_operand third_operand;
70 struct basic_instr_info {
79 /************************/
80 /* EXTERNAL DECODER API */
81 /************************/
83 This is an External API definition that must be implemented by a decoder
88 * Initializes a decoder
93 * Decodes an instruction
94 * All addresses in arguments are in the host address space
95 * instr_ptr is the host address of the instruction
96 * IMPORTANT: make sure the instr_ptr is in contiguous host memory
97 * ie. Copy it to a buffer before the call
99 int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * instr);
102 * Encodes an instruction
103 * All addresses in arguments are in the host address space
104 * The instruction is encoded from the struct, and copied into a 15 byte host buffer
105 * referenced by instr_buf
106 * any unused bytes at the end of instr_buf will be filled with nops
107 * IMPORTANT: instr_buf must be allocated and 15 bytes long
109 int v3_encode(struct guest_info * info, struct x86_instr * instr, char * instr_buf);
113 * Gets the operand size for a memory operation
116 int v3_basic_mem_decode(struct guest_info * info, addr_t instr_ptr, struct basic_instr_info * instr_info);
120 /* Removes a rep prefix in place */
121 void strip_rep_prefix(uchar_t * instr, int length);
126 * JRL: Some of this was taken from the Xen sources...
129 #define PACKED __attribute__((packed))
131 #define MODRM_MOD(x) ((x >> 6) & 0x3)
132 #define MODRM_REG(x) ((x >> 3) & 0x7)
133 #define MODRM_RM(x) (x & 0x7)
136 uint_t rm : 3 PACKED;
137 uint_t reg : 3 PACKED;
138 uint_t mod : 2 PACKED;
142 #define SIB_BASE(x) ((x >> 6) & 0x3)
143 #define SIB_INDEX(x) ((x >> 3) & 0x7)
144 #define SIB_SCALE(x) (x & 0x7)
147 uint_t base : 3 PACKED;
148 uint_t index : 3 PACKED;
149 uint_t scale : 2 PACKED;
154 #define MAKE_INSTR(nm, ...) static const uchar_t V3_OPCODE_##nm[] = { __VA_ARGS__ }
157 * Here's how it works:
158 * First byte: Length.
159 * Following bytes: Opcode bytes.
160 * Special case: Last byte, if zero, doesn't need to match.
162 MAKE_INSTR(INVD, 2, 0x0f, 0x08);
163 MAKE_INSTR(CPUID, 2, 0x0f, 0xa2);
164 MAKE_INSTR(RDMSR, 2, 0x0f, 0x32);
165 MAKE_INSTR(WRMSR, 2, 0x0f, 0x30);
166 MAKE_INSTR(RDTSC, 2, 0x0f, 0x31);
167 MAKE_INSTR(RDTSCP, 3, 0x0f, 0x01, 0xf9);
168 MAKE_INSTR(CLI, 1, 0xfa);
169 MAKE_INSTR(STI, 1, 0xfb);
170 MAKE_INSTR(RDPMC, 2, 0x0f, 0x33);
171 MAKE_INSTR(CLGI, 3, 0x0f, 0x01, 0xdd);
172 MAKE_INSTR(STGI, 3, 0x0f, 0x01, 0xdc);
173 MAKE_INSTR(VMRUN, 3, 0x0f, 0x01, 0xd8);
174 MAKE_INSTR(VMLOAD, 3, 0x0f, 0x01, 0xda);
175 MAKE_INSTR(VMSAVE, 3, 0x0f, 0x01, 0xdb);
176 MAKE_INSTR(VMCALL, 3, 0x0f, 0x01, 0xd9);
177 MAKE_INSTR(PAUSE, 2, 0xf3, 0x90);
178 MAKE_INSTR(SKINIT, 3, 0x0f, 0x01, 0xde);
179 MAKE_INSTR(MOV2CR, 3, 0x0f, 0x22, 0x00);
180 MAKE_INSTR(MOVCR2, 3, 0x0f, 0x20, 0x00);
181 MAKE_INSTR(MOV2DR, 3, 0x0f, 0x23, 0x00);
182 MAKE_INSTR(MOVDR2, 3, 0x0f, 0x21, 0x00);
183 MAKE_INSTR(PUSHF, 1, 0x9c);
184 MAKE_INSTR(POPF, 1, 0x9d);
185 MAKE_INSTR(RSM, 2, 0x0f, 0xaa);
186 MAKE_INSTR(INVLPG, 3, 0x0f, 0x01, 0x00);
187 MAKE_INSTR(INVLPGA,3, 0x0f, 0x01, 0xdf);
188 MAKE_INSTR(HLT, 1, 0xf4);
189 MAKE_INSTR(CLTS, 2, 0x0f, 0x06);
190 MAKE_INSTR(LMSW, 3, 0x0f, 0x01, 0x00);
191 MAKE_INSTR(SMSW, 3, 0x0f, 0x01, 0x00);
194 #define PREFIX_LOCK 0xF0
195 #define PREFIX_REPNE 0xF2
196 #define PREFIX_REPNZ 0xF2
197 #define PREFIX_REP 0xF3
198 #define PREFIX_REPE 0xF3
199 #define PREFIX_REPZ 0xF3
200 #define PREFIX_CS_OVERRIDE 0x2E
201 #define PREFIX_SS_OVERRIDE 0x36
202 #define PREFIX_DS_OVERRIDE 0x3E
203 #define PREFIX_ES_OVERRIDE 0x26
204 #define PREFIX_FS_OVERRIDE 0x64
205 #define PREFIX_GS_OVERRIDE 0x65
206 #define PREFIX_BR_NOT_TAKEN 0x2E
207 #define PREFIX_BR_TAKEN 0x3E
208 #define PREFIX_OP_SIZE 0x66
209 #define PREFIX_ADDR_SIZE 0x67
211 int opcode_cmp(const uchar_t * op1, const uchar_t * op2);
214 static inline int is_prefix_byte(char byte) {
217 case 0xF2: // REPNE/REPNZ
218 case 0xF3: // REP or REPE/REPZ
219 case 0x2E: // CS override or Branch hint not taken (with Jcc instrs)
220 case 0x36: // SS override
221 case 0x3E: // DS override or Branch hint taken (with Jcc instrs)
222 case 0x26: // ES override
223 case 0x64: // FS override
224 case 0x65: // GS override
225 //case 0x2E: // branch not taken hint
226 // case 0x3E: // branch taken hint
227 case 0x66: // operand size override
228 case 0x67: // address size override
238 static inline v3_reg_t get_gpr_mask(struct guest_info * info) {
239 switch (info->cpu_mode) {
252 static inline addr_t get_addr_linear(struct guest_info * info, addr_t addr, struct v3_segment * seg) {
253 switch (info->cpu_mode) {
255 // It appears that the segment values are computed and cached in the vmcb structure
256 // We Need to check this for Intel
257 /* return addr + (seg->selector << 4);
261 return addr + seg->base;
270 typedef enum {INVALID_ADDR_TYPE, REG, DISP0, DISP8, DISP16, DISP32} modrm_mode_t;
271 typedef enum {INVALID_REG_SIZE, REG64, REG32, REG16, REG8} reg_size_t;
280 static inline addr_t decode_register(struct v3_gprs * gprs, char reg_code, reg_size_t reg_size) {
285 reg_addr = (addr_t)&(gprs->rax);
288 reg_addr = (addr_t)&(gprs->rcx);
291 reg_addr = (addr_t)&(gprs->rdx);
294 reg_addr = (addr_t)&(gprs->rbx);
297 if (reg_size == REG8) {
298 reg_addr = (addr_t)&(gprs->rax) + 1;
300 reg_addr = (addr_t)&(gprs->rsp);
304 if (reg_size == REG8) {
305 reg_addr = (addr_t)&(gprs->rcx) + 1;
307 reg_addr = (addr_t)&(gprs->rbp);
311 if (reg_size == REG8) {
312 reg_addr = (addr_t)&(gprs->rdx) + 1;
314 reg_addr = (addr_t)&(gprs->rsi);
318 if (reg_size == REG8) {
319 reg_addr = (addr_t)&(gprs->rbx) + 1;
321 reg_addr = (addr_t)&(gprs->rdi);
334 static inline operand_type_t decode_operands16(struct v3_gprs * gprs, // input/output
335 char * modrm_instr, // input
336 int * offset, // output
337 addr_t * first_operand, // output
338 addr_t * second_operand, // output
339 reg_size_t reg_size) { // input
341 struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
342 addr_t base_addr = 0;
343 modrm_mode_t mod_mode = 0;
344 operand_type_t addr_type = INVALID_OPERAND;
345 char * instr_cursor = modrm_instr;
347 // PrintDebug("ModRM mod=%d\n", modrm->mod);
351 if (modrm->mod == 3) {
353 addr_type = REG_OPERAND;
354 //PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
356 *first_operand = decode_register(gprs, modrm->rm, reg_size);
360 addr_type = MEM_OPERAND;
362 if (modrm->mod == 0) {
364 } else if (modrm->mod == 1) {
366 } else if (modrm->mod == 2) {
372 base_addr = gprs->rbx + gprs->rsi;
375 base_addr = gprs->rbx + gprs->rdi;
378 base_addr = gprs->rbp + gprs->rsi;
381 base_addr = gprs->rbp + gprs->rdi;
384 base_addr = gprs->rsi;
387 base_addr = gprs->rdi;
390 if (modrm->mod == 0) {
394 base_addr = gprs->rbp;
398 base_addr = gprs->rbx;
404 if (mod_mode == DISP8) {
405 base_addr += (uchar_t)*(instr_cursor);
407 } else if (mod_mode == DISP16) {
408 base_addr += (ushort_t)*(instr_cursor);
412 *first_operand = base_addr;
415 *offset += (instr_cursor - modrm_instr);
416 *second_operand = decode_register(gprs, modrm->reg, reg_size);
423 static inline operand_type_t decode_operands32(struct v3_gprs * gprs, // input/output
424 char * modrm_instr, // input
425 int * offset, // output
426 addr_t * first_operand, // output
427 addr_t * second_operand, // output
428 reg_size_t reg_size) { // input
430 char * instr_cursor = modrm_instr;
431 struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
432 addr_t base_addr = 0;
433 modrm_mode_t mod_mode = 0;
434 uint_t has_sib_byte = 0;
435 operand_type_t addr_type = INVALID_OPERAND;
441 if (modrm->mod == 3) {
443 addr_type = REG_OPERAND;
445 // PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
447 *first_operand = decode_register(gprs, modrm->rm, reg_size);
451 addr_type = MEM_OPERAND;
453 if (modrm->mod == 0) {
455 } else if (modrm->mod == 1) {
457 } else if (modrm->mod == 2) {
463 base_addr = gprs->rax;
466 base_addr = gprs->rcx;
469 base_addr = gprs->rdx;
472 base_addr = gprs->rbx;
478 if (modrm->mod == 0) {
482 base_addr = gprs->rbp;
486 base_addr = gprs->rsi;
489 base_addr = gprs->rdi;
495 struct sib_byte * sib = (struct sib_byte *)(instr_cursor);
501 if (sib->scale == 1) {
503 } else if (sib->scale == 2) {
505 } else if (sib->scale == 3) {
510 switch (sib->index) {
512 base_addr = gprs->rax;
515 base_addr = gprs->rcx;
518 base_addr = gprs->rdx;
521 base_addr = gprs->rbx;
527 base_addr = gprs->rbp;
530 base_addr = gprs->rsi;
533 base_addr = gprs->rdi;
542 base_addr += gprs->rax;
545 base_addr += gprs->rcx;
548 base_addr += gprs->rdx;
551 base_addr += gprs->rbx;
554 base_addr += gprs->rsp;
557 if (modrm->mod != 0) {
558 base_addr += gprs->rbp;
562 base_addr += gprs->rsi;
565 base_addr += gprs->rdi;
572 if (mod_mode == DISP8) {
573 base_addr += (uchar_t)*(instr_cursor);
575 } else if (mod_mode == DISP32) {
576 base_addr += (uint_t)*(instr_cursor);
581 *first_operand = base_addr;
584 *offset += (instr_cursor - modrm_instr);
586 *second_operand = decode_register(gprs, modrm->reg, reg_size);