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 V3_OP_ADC, V3_OP_ADD, V3_OP_AND, V3_OP_OR, V3_OP_XOR, V3_OP_SUB,
33 V3_OP_INC, V3_OP_DEC, V3_OP_NEG, V3_OP_MOV, V3_OP_NOT, V3_OP_XCHG,
34 V3_OP_SETB, V3_OP_SETBE, V3_OP_SETL, V3_OP_SETLE, V3_OP_SETNB,
35 V3_OP_SETNBE, V3_OP_SETNL, V3_OP_SETNLE, V3_OP_SETNO, V3_OP_SETNP,
36 V3_OP_SETNS, V3_OP_SETNZ, V3_OP_SETO, V3_OP_SETP, V3_OP_SETS,
37 V3_OP_SETZ, V3_OP_MOVS, V3_OP_STOS, V3_OP_MOVZX, V3_OP_MOVSX} v3_op_type_t;
40 typedef enum {INVALID_OPERAND, REG_OPERAND, MEM_OPERAND, IMM_OPERAND} v3_operand_type_t;
45 v3_operand_type_t type;
49 uint_t lock : 1; // 0xF0
50 uint_t repne : 1; // 0xF2
51 uint_t repnz : 1; // 0xF2
52 uint_t rep : 1; // 0xF3
53 uint_t repe : 1; // 0xF3
54 uint_t repz : 1; // 0xF3
55 uint_t cs_override : 1; // 0x2E
56 uint_t ss_override : 1; // 0x36
57 uint_t ds_override : 1; // 0x3E
58 uint_t es_override : 1; // 0x26
59 uint_t fs_override : 1; // 0x64
60 uint_t gs_override : 1; // 0x65
61 uint_t br_not_taken : 1; // 0x2E
62 uint_t br_taken : 1; // 0x3E
63 uint_t op_size : 1; // 0x66
64 uint_t addr_size : 1; // 0x67
69 struct x86_prefixes prefixes;
73 struct x86_operand dst_operand;
74 struct x86_operand src_operand;
75 struct x86_operand third_operand;
82 struct basic_instr_info {
91 /************************/
92 /* EXTERNAL DECODER API */
93 /************************/
95 This is an External API definition that must be implemented by a decoder
100 * Initializes a decoder
102 int v3_init_decoder(struct guest_info * core);
103 int v3_deinit_decoder(struct guest_info * core);
106 * Decodes an instruction
107 * All addresses in arguments are in the host address space
108 * instr_ptr is the host address of the instruction
109 * IMPORTANT: make sure the instr_ptr is in contiguous host memory
110 * ie. Copy it to a buffer before the call
112 int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * instr);
115 * Encodes an instruction
116 * All addresses in arguments are in the host address space
117 * The instruction is encoded from the struct, and copied into a 15 byte host buffer
118 * referenced by instr_buf
119 * any unused bytes at the end of instr_buf will be filled with nops
120 * IMPORTANT: instr_buf must be allocated and 15 bytes long
122 int v3_encode(struct guest_info * info, struct x86_instr * instr, char * instr_buf);
126 * Gets the operand size for a memory operation
129 int v3_basic_mem_decode(struct guest_info * info, addr_t instr_ptr, struct basic_instr_info * instr_info);
133 /* Removes a rep prefix in place */
134 void v3_strip_rep_prefix(uchar_t * instr, int length);
135 void v3_get_prefixes(uchar_t * instr, struct x86_prefixes * prefixes);
139 * JRL: Some of this was taken from the Xen sources...
142 #define PACKED __attribute__((packed))
144 #define MODRM_MOD(x) ((x >> 6) & 0x3)
145 #define MODRM_REG(x) ((x >> 3) & 0x7)
146 #define MODRM_RM(x) (x & 0x7)
149 uint_t rm : 3 PACKED;
150 uint_t reg : 3 PACKED;
151 uint_t mod : 2 PACKED;
155 #define SIB_BASE(x) ((x >> 6) & 0x3)
156 #define SIB_INDEX(x) ((x >> 3) & 0x7)
157 #define SIB_SCALE(x) (x & 0x7)
160 uint_t base : 3 PACKED;
161 uint_t index : 3 PACKED;
162 uint_t scale : 2 PACKED;
167 #define MAKE_INSTR(nm, ...) static const uchar_t V3_OPCODE_##nm[] = { __VA_ARGS__ }
170 * Here's how it works:
171 * First byte: Length.
172 * Following bytes: Opcode bytes.
173 * Special case: Last byte, if zero, doesn't need to match.
175 MAKE_INSTR(INVD, 2, 0x0f, 0x08);
176 MAKE_INSTR(CPUID, 2, 0x0f, 0xa2);
177 MAKE_INSTR(RDMSR, 2, 0x0f, 0x32);
178 MAKE_INSTR(WRMSR, 2, 0x0f, 0x30);
179 MAKE_INSTR(RDTSC, 2, 0x0f, 0x31);
180 MAKE_INSTR(RDTSCP, 3, 0x0f, 0x01, 0xf9);
181 MAKE_INSTR(CLI, 1, 0xfa);
182 MAKE_INSTR(STI, 1, 0xfb);
183 MAKE_INSTR(RDPMC, 2, 0x0f, 0x33);
184 MAKE_INSTR(CLGI, 3, 0x0f, 0x01, 0xdd);
185 MAKE_INSTR(STGI, 3, 0x0f, 0x01, 0xdc);
186 MAKE_INSTR(VMRUN, 3, 0x0f, 0x01, 0xd8);
187 MAKE_INSTR(VMLOAD, 3, 0x0f, 0x01, 0xda);
188 MAKE_INSTR(VMSAVE, 3, 0x0f, 0x01, 0xdb);
189 MAKE_INSTR(VMCALL, 3, 0x0f, 0x01, 0xd9);
190 MAKE_INSTR(PAUSE, 2, 0xf3, 0x90);
191 MAKE_INSTR(SKINIT, 3, 0x0f, 0x01, 0xde);
192 MAKE_INSTR(MOV2CR, 3, 0x0f, 0x22, 0x00);
193 MAKE_INSTR(MOVCR2, 3, 0x0f, 0x20, 0x00);
194 MAKE_INSTR(MOV2DR, 3, 0x0f, 0x23, 0x00);
195 MAKE_INSTR(MOVDR2, 3, 0x0f, 0x21, 0x00);
196 MAKE_INSTR(PUSHF, 1, 0x9c);
197 MAKE_INSTR(POPF, 1, 0x9d);
198 MAKE_INSTR(RSM, 2, 0x0f, 0xaa);
199 MAKE_INSTR(INVLPG, 3, 0x0f, 0x01, 0x00);
200 MAKE_INSTR(INVLPGA,3, 0x0f, 0x01, 0xdf);
201 MAKE_INSTR(HLT, 1, 0xf4);
202 MAKE_INSTR(CLTS, 2, 0x0f, 0x06);
203 MAKE_INSTR(LMSW, 3, 0x0f, 0x01, 0x00);
204 MAKE_INSTR(SMSW, 3, 0x0f, 0x01, 0x00);
207 #define PREFIX_LOCK 0xF0
208 #define PREFIX_REPNE 0xF2
209 #define PREFIX_REPNZ 0xF2
210 #define PREFIX_REP 0xF3
211 #define PREFIX_REPE 0xF3
212 #define PREFIX_REPZ 0xF3
213 #define PREFIX_CS_OVERRIDE 0x2E
214 #define PREFIX_SS_OVERRIDE 0x36
215 #define PREFIX_DS_OVERRIDE 0x3E
216 #define PREFIX_ES_OVERRIDE 0x26
217 #define PREFIX_FS_OVERRIDE 0x64
218 #define PREFIX_GS_OVERRIDE 0x65
219 #define PREFIX_BR_NOT_TAKEN 0x2E
220 #define PREFIX_BR_TAKEN 0x3E
221 #define PREFIX_OP_SIZE 0x66
222 #define PREFIX_ADDR_SIZE 0x67
224 int v3_opcode_cmp(const uchar_t * op1, const uchar_t * op2);
227 static inline int is_prefix_byte(uchar_t byte) {
230 case 0xF2: // REPNE/REPNZ
231 case 0xF3: // REP or REPE/REPZ
232 case 0x2E: // CS override or Branch hint not taken (with Jcc instrs)
233 case 0x36: // SS override
234 case 0x3E: // DS override or Branch hint taken (with Jcc instrs)
235 case 0x26: // ES override
236 case 0x64: // FS override
237 case 0x65: // GS override
238 //case 0x2E: // branch not taken hint
239 // case 0x3E: // branch taken hint
240 case 0x66: // operand size override
241 case 0x67: // address size override
251 static inline v3_reg_t get_gpr_mask(struct guest_info * info) {
252 switch (info->cpu_mode) {
262 return 0xffffffffffffffffLL;
264 PrintError("Unsupported Address Mode\n");
270 static inline addr_t get_addr_linear(struct guest_info * info, addr_t addr, struct v3_segment * seg) {
271 switch (info->cpu_mode) {
273 // It appears that the segment values are computed and cached in the vmcb structure
274 // We Need to check this for Intel
275 /* return addr + (seg->selector << 4);
281 return addr + seg->base;
285 // In long mode the segment bases are disregarded (forced to 0), unless using
286 // FS or GS, then the base addresses are added
287 return addr + seg->base;
291 PrintError("Unsupported CPU Mode: %d\n", info->cpu_mode);
297 typedef enum {INVALID_ADDR_TYPE, REG, DISP0, DISP8, DISP16, DISP32} modrm_mode_t;
298 typedef enum {INVALID_REG_SIZE, REG64, REG32, REG16, REG8} reg_size_t;
307 static inline addr_t decode_register(struct v3_gprs * gprs, char reg_code, reg_size_t reg_size) {
312 reg_addr = (addr_t)&(gprs->rax);
315 reg_addr = (addr_t)&(gprs->rcx);
318 reg_addr = (addr_t)&(gprs->rdx);
321 reg_addr = (addr_t)&(gprs->rbx);
324 if (reg_size == REG8) {
325 reg_addr = (addr_t)&(gprs->rax) + 1;
327 reg_addr = (addr_t)&(gprs->rsp);
331 if (reg_size == REG8) {
332 reg_addr = (addr_t)&(gprs->rcx) + 1;
334 reg_addr = (addr_t)&(gprs->rbp);
338 if (reg_size == REG8) {
339 reg_addr = (addr_t)&(gprs->rdx) + 1;
341 reg_addr = (addr_t)&(gprs->rsi);
345 if (reg_size == REG8) {
346 reg_addr = (addr_t)&(gprs->rbx) + 1;
348 reg_addr = (addr_t)&(gprs->rdi);
361 static inline v3_operand_type_t decode_operands16(struct v3_gprs * gprs, // input/output
362 char * modrm_instr, // input
363 int * offset, // output
364 addr_t * first_operand, // output
365 addr_t * second_operand, // output
366 reg_size_t reg_size) { // input
368 struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
369 addr_t base_addr = 0;
370 modrm_mode_t mod_mode = 0;
371 v3_operand_type_t addr_type = INVALID_OPERAND;
372 char * instr_cursor = modrm_instr;
374 // PrintDebug("ModRM mod=%d\n", modrm->mod);
378 if (modrm->mod == 3) {
380 addr_type = REG_OPERAND;
381 //PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
383 *first_operand = decode_register(gprs, modrm->rm, reg_size);
387 addr_type = MEM_OPERAND;
389 if (modrm->mod == 0) {
391 } else if (modrm->mod == 1) {
393 } else if (modrm->mod == 2) {
399 base_addr = gprs->rbx + gprs->rsi;
402 base_addr = gprs->rbx + gprs->rdi;
405 base_addr = gprs->rbp + gprs->rsi;
408 base_addr = gprs->rbp + gprs->rdi;
411 base_addr = gprs->rsi;
414 base_addr = gprs->rdi;
417 if (modrm->mod == 0) {
421 base_addr = gprs->rbp;
425 base_addr = gprs->rbx;
431 if (mod_mode == DISP8) {
432 base_addr += (uchar_t)*(instr_cursor);
434 } else if (mod_mode == DISP16) {
435 base_addr += (ushort_t)*(instr_cursor);
439 *first_operand = base_addr;
442 *offset += (instr_cursor - modrm_instr);
443 *second_operand = decode_register(gprs, modrm->reg, reg_size);
450 static inline v3_operand_type_t decode_operands32(struct v3_gprs * gprs, // input/output
451 uchar_t * modrm_instr, // input
452 int * offset, // output
453 addr_t * first_operand, // output
454 addr_t * second_operand, // output
455 reg_size_t reg_size) { // input
457 uchar_t * instr_cursor = modrm_instr;
458 struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
459 addr_t base_addr = 0;
460 modrm_mode_t mod_mode = 0;
461 uint_t has_sib_byte = 0;
462 v3_operand_type_t addr_type = INVALID_OPERAND;
468 if (modrm->mod == 3) {
470 addr_type = REG_OPERAND;
472 // PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
474 *first_operand = decode_register(gprs, modrm->rm, reg_size);
478 addr_type = MEM_OPERAND;
480 if (modrm->mod == 0) {
482 } else if (modrm->mod == 1) {
484 } else if (modrm->mod == 2) {
490 base_addr = gprs->rax;
493 base_addr = gprs->rcx;
496 base_addr = gprs->rdx;
499 base_addr = gprs->rbx;
505 if (modrm->mod == 0) {
509 base_addr = gprs->rbp;
513 base_addr = gprs->rsi;
516 base_addr = gprs->rdi;
522 struct sib_byte * sib = (struct sib_byte *)(instr_cursor);
528 if (sib->scale == 1) {
530 } else if (sib->scale == 2) {
532 } else if (sib->scale == 3) {
537 switch (sib->index) {
539 base_addr = gprs->rax;
542 base_addr = gprs->rcx;
545 base_addr = gprs->rdx;
548 base_addr = gprs->rbx;
554 base_addr = gprs->rbp;
557 base_addr = gprs->rsi;
560 base_addr = gprs->rdi;
569 base_addr += gprs->rax;
572 base_addr += gprs->rcx;
575 base_addr += gprs->rdx;
578 base_addr += gprs->rbx;
581 base_addr += gprs->rsp;
584 if (modrm->mod != 0) {
585 base_addr += gprs->rbp;
589 base_addr += gprs->rsi;
592 base_addr += gprs->rdi;
599 if (mod_mode == DISP8) {
600 base_addr += (uchar_t)*(instr_cursor);
602 } else if (mod_mode == DISP32) {
603 base_addr += (uint_t)*(instr_cursor);
608 *first_operand = base_addr;
611 *offset += (instr_cursor - modrm_instr);
613 *second_operand = decode_register(gprs, modrm->reg, reg_size);