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.


working on x86 instruction decoding support
[palacios.git] / palacios / include / geekos / vmm_emulate.h
1 #ifndef __VMM_EMULATE_H
2 #define __VMM_EMULATE_H
3 #include <geekos/vm_guest.h>
4
5
6 /*
7  * This is where we do the hideous X86 instruction parsing among other things
8  * We can parse out the instruction prefixes, as well as decode the operands 
9  *
10  * Before we begin I'd just like to say a few words to those that made this possible...
11  *
12  *
13  *                                   _____
14  *                                  ||   ||
15  *                                  |\___/|
16  *                                  |     |
17  *                                  |     |
18  *                                  |     |
19  *                                  |     |
20  *                                  |     |
21  *                                  |     |
22  *                             _____|<--->|_____
23  *                         ___/     |     |      \
24  *                       /    |     |     |     | \
25  *                       |    |     |     |     |  |
26  *                       |    |     |     |     |  |
27  *                       |                      |  |
28  *                       |                      |  |
29  *                       |    Fuck You Intel!     /
30  *                       |                       /
31  *                        \                    /
32  *                         \                  /
33  *                          |                 |
34  *                          |                 |
35  *
36  * That is all.
37  *
38  */
39
40
41 /* JRL: Some of this was taken from the Xen sources... 
42  *
43  */
44
45 #define PACKED __attribute__((packed))
46
47 #define MODRM_MOD(x) ((x >> 6) & 0x3)
48 #define MODRM_REG(x) ((x >> 3) & 0x7)
49 #define MODRM_RM(x)  (x & 0x07)
50
51 struct modrm_byte {
52   uint_t rm   :   3 PACKED;
53   uint_t reg  :   3 PACKED;
54   uint_t mod  :   2 PACKED;
55 };
56
57
58 struct sib_byte {
59   uint_t base     :   3 PACKED;
60   uint_t index    :   3 PACKED;
61   uint_t scale    :   2 PACKED;
62 };
63
64
65
66 #define MAKE_INSTR(nm, ...) static const uchar_t OPCODE_##nm[] = { __VA_ARGS__ }
67
68 /* 
69  * Here's how it works:
70  * First byte: Length. 
71  * Following bytes: Opcode bytes. 
72  * Special case: Last byte, if zero, doesn't need to match. 
73  */
74 MAKE_INSTR(INVD,   2, 0x0f, 0x08);
75 MAKE_INSTR(CPUID,  2, 0x0f, 0xa2);
76 MAKE_INSTR(RDMSR,  2, 0x0f, 0x32);
77 MAKE_INSTR(WRMSR,  2, 0x0f, 0x30);
78 MAKE_INSTR(RDTSC,  2, 0x0f, 0x31);
79 MAKE_INSTR(RDTSCP, 3, 0x0f, 0x01, 0xf9);
80 MAKE_INSTR(CLI,    1, 0xfa);
81 MAKE_INSTR(STI,    1, 0xfb);
82 MAKE_INSTR(RDPMC,  2, 0x0f, 0x33);
83 MAKE_INSTR(CLGI,   3, 0x0f, 0x01, 0xdd);
84 MAKE_INSTR(STGI,   3, 0x0f, 0x01, 0xdc);
85 MAKE_INSTR(VMRUN,  3, 0x0f, 0x01, 0xd8);
86 MAKE_INSTR(VMLOAD, 3, 0x0f, 0x01, 0xda);
87 MAKE_INSTR(VMSAVE, 3, 0x0f, 0x01, 0xdb);
88 MAKE_INSTR(VMCALL, 3, 0x0f, 0x01, 0xd9);
89 MAKE_INSTR(PAUSE,  2, 0xf3, 0x90);
90 MAKE_INSTR(SKINIT, 3, 0x0f, 0x01, 0xde);
91 MAKE_INSTR(MOV2CR, 3, 0x0f, 0x22, 0x00);
92 MAKE_INSTR(MOVCR2, 3, 0x0f, 0x20, 0x00);
93 MAKE_INSTR(MOV2DR, 3, 0x0f, 0x23, 0x00);
94 MAKE_INSTR(MOVDR2, 3, 0x0f, 0x21, 0x00);
95 MAKE_INSTR(PUSHF,  1, 0x9c);
96 MAKE_INSTR(POPF,   1, 0x9d);
97 MAKE_INSTR(RSM,    2, 0x0f, 0xaa);
98 MAKE_INSTR(INVLPG, 3, 0x0f, 0x01, 0x00);
99 MAKE_INSTR(INVLPGA,3, 0x0f, 0x01, 0xdf);
100 MAKE_INSTR(HLT,    1, 0xf4);
101 MAKE_INSTR(CLTS,   2, 0x0f, 0x06);
102 MAKE_INSTR(LMSW,   3, 0x0f, 0x01, 0x00);
103 MAKE_INSTR(SMSW,   3, 0x0f, 0x01, 0x00);
104
105
106
107 static inline int is_prefix_byte(char byte) {
108   switch (byte) {
109   case 0xF0:      // lock
110   case 0xF2:      // REPNE/REPNZ
111   case 0xF3:      // REP or REPE/REPZ
112   case 0x2E:      // CS override or Branch hint not taken (with Jcc instrs)
113   case 0x36:      // SS override
114   case 0x3E:      // DS override or Branch hint taken (with Jcc instrs)
115   case 0x26:      // ES override
116   case 0x64:      // FS override
117   case 0x65:      // GS override
118     //case 0x2E:      // branch not taken hint
119     //  case 0x3E:      // branch taken hint
120   case 0x66:      // operand size override
121   case 0x67:      // address size override
122     return 1;
123     break;
124   default:
125     return 0;
126     break;
127   }
128 }
129
130 typedef enum {INVALID_ADDR_TYPE, REG, DISP0, DISP8, DISP16, DISP32} modrm_addr_type_t;
131 typedef enum {INVALID_REG_SIZE, REG64, REG32, REG16, REG8} reg_size_t;
132 typedef enum {INVALID_OPERAND_TYPE, REG_TO_REG, REG_TO_MEM, MEM_TO_REG} operand_type_t;
133
134 struct guest_gprs;
135
136
137 static inline int decode_operands16(struct guest_gprs * gprs, 
138                                     char * modrm_instr, 
139                                     addr_t * first_operand,
140                                     addr_t * second_operand, 
141                                     reg_size_t reg_size) {
142   
143   struct modrm_byte * modrm = (struct modrm_byte*)modrm_instr;
144   addr_t base_addr = 0;
145   modrm_addr_type_t mod_type = 0;
146
147   PrintDebug("ModRM mod=%d\n", modrm->mod);
148
149   if (modrm->mod == 3) {
150     mod_type = REG;
151
152     PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
153
154     switch (modrm->rm) {
155     case 0:
156       PrintDebug("EAX Operand\n");
157       *first_operand = (addr_t)&(gprs->rax);
158       break;
159     case 1:
160       *first_operand = (addr_t)&(gprs->rcx);
161       break;
162     case 2:
163       *first_operand = (addr_t)&(gprs->rdx);
164       break;
165     case 3:
166       *first_operand = (addr_t)&(gprs->rbx);
167       break;
168     case 4:
169       if (reg_size == REG8) {
170         *first_operand = (addr_t)(&(gprs->rax) + 1);
171       } else {
172         *first_operand = (addr_t)&(gprs->rsp);
173       }
174       break;
175     case 5:
176       if (reg_size == REG8) {
177         *first_operand = (addr_t)(&(gprs->rcx) + 1);
178       } else {
179         *first_operand = (addr_t)&(gprs->rbp);
180       }
181       break;
182     case 6:
183       if (reg_size == REG8) {
184         *first_operand = (addr_t)(&(gprs->rdx) + 1);
185       } else {
186         *first_operand = (addr_t)&(gprs->rsi);
187       }
188       break;
189     case 7:
190       if (reg_size == REG8) {
191         *first_operand = (addr_t)(&(gprs->rbx) + 1);
192       } else {
193         *first_operand = (addr_t)&(gprs->rdi);
194       }
195       break;
196     }
197
198   } else {
199     if (modrm->mod == 0) {
200       mod_type = DISP0;
201     } else if (modrm->mod == 1) {
202       mod_type = DISP8;
203     } else if (modrm->mod == 2) {
204       mod_type = DISP16;
205     }
206
207     switch (modrm->rm) {
208     case 0:
209       base_addr = gprs->rbx + gprs->rsi;
210     case 1:
211       base_addr = gprs->rbx + gprs->rdi;
212     case 2:
213       base_addr = gprs->rbp + gprs->rsi;
214     case 3:
215       base_addr = gprs->rbp + gprs->rdi;
216     case 4:
217       base_addr = gprs->rsi;
218     case 5:
219       base_addr = gprs->rdi;
220     case 6:
221       if (modrm->mod == 0) {
222         base_addr = 0;
223         mod_type = DISP16;
224       } else {
225         base_addr = gprs->rbp;
226       }
227     case 7:
228       base_addr = gprs->rbx;
229     }
230
231     if (mod_type == DISP8) {
232       base_addr += (uchar_t)*(modrm_instr + 1);
233     } else if (mod_type == DISP16) {
234       base_addr += (ushort_t)*(modrm_instr + 1);
235     }
236     
237     
238     *first_operand = base_addr;
239   }
240
241
242
243   switch (modrm->reg) {
244     case 0:
245       *second_operand = (addr_t)&(gprs->rax);
246       break;
247     case 1:
248       *second_operand = (addr_t)&(gprs->rcx);
249       break;
250     case 2:
251       *second_operand = (addr_t)&(gprs->rdx);
252       break;
253     case 3:
254       *second_operand = (addr_t)&(gprs->rbx);
255       break;
256     case 4:
257       if (reg_size == REG8) {
258         *second_operand = (addr_t)&(gprs->rax) + 1;
259       } else {
260         *second_operand = (addr_t)&(gprs->rsp);
261       }
262       break;
263     case 5:
264       if (reg_size == REG8) {
265         *second_operand = (addr_t)&(gprs->rcx) + 1;
266       } else {
267         *second_operand = (addr_t)&(gprs->rbp);
268       }
269       break;
270     case 6:
271       if (reg_size == REG8) {
272         *second_operand = (addr_t)&(gprs->rdx) + 1;
273       } else {
274         *second_operand = (addr_t)&(gprs->rsi);
275       }
276       break;
277     case 7:
278       if (reg_size == REG8) {
279         *second_operand = (addr_t)&(gprs->rbx) + 1;
280       } else {
281         *second_operand = (addr_t)&(gprs->rdi);
282       }
283       break;
284   }
285
286   return 0;
287
288 }
289
290
291
292
293
294 #endif