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.


Basic HRT startup for HVM, plus assorted cleanup
[palacios.git] / palacios / include / palacios / vmm_decoder.h
1 /*
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.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
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.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #ifndef __VMM_DECODER_H
21 #define __VMM_DECODER_H
22
23 #ifdef __V3VEE__
24
25 #include <palacios/vm_guest.h>
26 #include <palacios/vmm.h>
27
28
29 typedef enum { V3_INVALID_OP,
30                V3_OP_MOVCR2, V3_OP_MOV2CR, V3_OP_SMSW, V3_OP_LMSW, V3_OP_CLTS,
31                V3_OP_INVLPG,
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,
37
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;
44
45
46 typedef enum {INVALID_OPERAND, REG_OPERAND, MEM_OPERAND, IMM_OPERAND} v3_operand_type_t;
47
48 struct x86_operand {
49     addr_t operand;
50     uint_t size;
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));
55
56 struct x86_prefixes {
57     union {
58         uint32_t val;
59         
60         struct {
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
77
78             uint32_t rex   : 1;
79     
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
84
85             uint32_t rsvd          : 11;
86         } __attribute__((packed));
87     } __attribute__((packed));
88 } __attribute__((packed));
89
90
91 struct x86_instr {
92     struct x86_prefixes prefixes;
93     uint8_t instr_length;
94     v3_op_type_t op_type;
95     uint_t num_operands;
96     struct x86_operand dst_operand;
97     struct x86_operand src_operand;
98     struct x86_operand third_operand;
99     addr_t str_op_length;
100     addr_t is_str_op;
101 };
102
103
104 /************************/
105 /* EXTERNAL DECODER API */
106 /************************/
107 /* 
108    This is an External API definition that must be implemented by a decoder
109 */
110
111
112 /* 
113  * Initializes a decoder
114  */
115 int v3_init_decoder(struct guest_info * core);
116 int v3_deinit_decoder(struct guest_info * core);
117
118 /* 
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
124  */
125 int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * instr);
126
127 /* 
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
134  */
135 int v3_encode(struct guest_info * info, struct x86_instr * instr, uint8_t * instr_buf);
136
137
138
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);
142
143
144 void v3_print_instr(struct x86_instr * instr);
145
146
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
163
164
165
166
167 static inline int is_prefix_byte(uchar_t byte) {
168     switch (byte) {
169         case 0xF0:      // lock
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
182             return 1;
183             break;
184         default:
185             return 0;
186             break;
187     }
188 }
189
190
191 static inline v3_reg_t get_gpr_mask(struct guest_info * info) {
192     switch (info->cpu_mode) {
193         case REAL: 
194         case LONG_16_COMPAT:
195             return 0xffff;
196             break;
197         case PROTECTED:
198         case LONG_32_COMPAT:
199         case PROTECTED_PAE:
200             return 0xffffffff;
201         case LONG:
202             return 0xffffffffffffffffLL;
203         default:
204             PrintError(info->vm_info, info, "Unsupported Address Mode\n");
205             return -1;
206     }
207 }
208
209
210
211 static inline addr_t get_addr_linear(struct guest_info * info, addr_t addr, struct v3_segment * seg) {
212     switch (info->cpu_mode) {
213         case REAL: {
214             return ((seg->selector & 0xffff) << 4) + (addr & 0xffff);
215             break;
216         }
217         case PROTECTED:
218         case PROTECTED_PAE:
219         case LONG_32_COMPAT:
220             return addr + seg->base;
221             break;
222
223         case LONG: {
224             uint64_t seg_base = 0;
225
226             // In long mode the segment bases are disregarded (forced to 0), unless using 
227             // FS or GS, then the base addresses are added
228
229             if (seg) {
230                 seg_base = seg->base;
231             }
232
233             return addr + seg_base;
234         }
235         case LONG_16_COMPAT:
236         default:
237           PrintError(info->vm_info, info,"Unsupported CPU Mode: %d\n", info->cpu_mode);
238             return -1;
239     }
240 }
241
242
243
244 #endif // !__V3VEE__
245
246
247 #endif