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.


aef325ace0b450bf8b7a25b3a0213c8c552c688a
[palacios.git] / palacios / include / palacios / vmm_instr_emulator.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 #include <palacios/vmm_types.h>
21
22
23
24 #define MAKE_1OP_8FLAGS_INST(iname) static inline void iname##8(addr_t * dst,  addr_t * flags) { \
25     uchar_t tmp_dst = *dst;                                             \
26                                                                         \
27     /* Some of the flags values are not copied out in a pushf, we save them here */ \
28     addr_t flags_rsvd = *flags & ~0xfffe7fff;                           \
29                                                                         \
30     asm volatile (                                                              \
31          "pushf; "                                                      \
32          "push %2; "                                                    \
33          "popf; "                                                       \
34          #iname"b %0; "                                                 \
35          "pushf; "                                                      \
36          "pop %1; "                                                     \
37          "popf; "                                                       \
38          : "=q"(tmp_dst),"=q"(*flags)                                   \
39          : "q"(*flags), "0"(tmp_dst)                                    \
40          );                                                             \
41     *dst = tmp_dst;                                                     \
42     *flags |= flags_rsvd;                                               \
43                                                                         \
44   }
45
46 #define MAKE_1OP_16FLAGS_INST(iname) static inline void iname##16(addr_t * dst,  addr_t * flags) { \
47     ushort_t tmp_dst = *dst;                                            \
48                                                                         \
49     /* Some of the flags values are not copied out in a pushf, we save them here */ \
50     addr_t flags_rsvd = *flags & ~0xfffe7fff;                           \
51                                                                         \
52     asm volatile (                                                              \
53          "pushf; "                                                      \
54          "push %2; "                                                    \
55          "popf; "                                                       \
56          #iname"w %0; "                                                 \
57          "pushf; "                                                      \
58          "pop %1; "                                                     \
59          "popf; "                                                       \
60          : "=q"(tmp_dst),"=q"(*flags)                                   \
61          : "q"(*flags), "0"(tmp_dst)                                    \
62          );                                                             \
63     *dst = tmp_dst;                                                     \
64     *flags |= flags_rsvd;                                               \
65                                                                         \
66   }
67
68 #define MAKE_1OP_32FLAGS_INST(iname) static inline void iname##32(addr_t * dst,  addr_t * flags) { \
69     uint_t tmp_dst = *dst;                                              \
70                                                                         \
71     /* Some of the flags values are not copied out in a pushf, we save them here */ \
72     addr_t flags_rsvd = *flags & ~0xfffe7fff;                           \
73                                                                         \
74     asm volatile (                                                              \
75          "pushf; "                                                      \
76          "push %2; "                                                    \
77          "popf; "                                                       \
78          #iname"l %0; "                                                 \
79          "pushf; "                                                      \
80          "pop %1; "                                                     \
81          "popf; "                                                       \
82          : "=q"(tmp_dst),"=q"(*flags)                                   \
83          : "q"(*flags), "0"(tmp_dst)                                    \
84          );                                                             \
85     *dst = tmp_dst;                                                     \
86     *flags |= flags_rsvd;                                               \
87                                                                         \
88   }
89
90 #define MAKE_1OP_64FLAGS_INST(iname) static inline void iname##64(addr_t * dst,  addr_t * flags) { \
91     ullong_t tmp_dst = *dst;                                            \
92                                                                         \
93     /* Some of the flags values are not copied out in a pushf, we save them here */ \
94     addr_t flags_rsvd = *flags & ~0xfffe7fff;                           \
95                                                                         \
96     asm volatile (                                                              \
97          "pushfq; "                                                     \
98          "push %2; "                                                    \
99          "popfq; "                                                      \
100          #iname"q %0; "                                                 \
101          "pushfq; "                                                     \
102          "pop %1; "                                                     \
103          "popfq; "                                                      \
104          : "=q"(tmp_dst),"=q"(*flags)                                   \
105          : "q"(*flags), "0"(tmp_dst)                                    \
106          );                                                             \
107     *dst = tmp_dst;                                                     \
108     *flags |= flags_rsvd;                                               \
109                                                                         \
110   }
111
112
113
114 #define MAKE_1OP_8_INST(iname) static inline void iname##8(addr_t * dst) { \
115     uchar_t tmp_dst = *dst;                                             \
116                                                                         \
117     asm volatile (                                                      \
118                   #iname"b %0; "                                        \
119                   : "=q"(tmp_dst)                                       \
120                   : "0"(tmp_dst)                                        \
121                   );                                                    \
122     *dst = tmp_dst;                                                     \
123   }
124
125 #define MAKE_1OP_16_INST(iname) static inline void iname##16(addr_t * dst) { \
126     ushort_t tmp_dst = *dst;                                            \
127                                                                         \
128     asm volatile (                                                      \
129          #iname"w %0; "                                                 \
130          : "=q"(tmp_dst)                                                \
131          :  "0"(tmp_dst)                                                \
132          );                                                             \
133     *dst = tmp_dst;                                                     \
134   }
135
136 #define MAKE_1OP_32_INST(iname) static inline void iname##32(addr_t * dst) { \
137     uint_t tmp_dst = *dst;                                              \
138                                                                         \
139     asm volatile (                                                      \
140          #iname"l %0; "                                                 \
141          : "=q"(tmp_dst)                                                \
142          : "0"(tmp_dst)                                                 \
143          );                                                             \
144     *dst = tmp_dst;                                                     \
145   }
146
147 #define MAKE_1OP_64_INST(iname) static inline void iname##64(addr_t * dst) { \
148     ullong_t tmp_dst = *dst;                                            \
149                                                                         \
150     asm volatile (                                                      \
151                   #iname"q %0; "                                        \
152                   : "=q"(tmp_dst)                                       \
153                   : "0"(tmp_dst)                                        \
154                   );                                                    \
155     *dst = tmp_dst;                                                     \
156   }
157
158
159 #define MAKE_2OP_64FLAGS_INST(iname) static inline void iname##64(addr_t * dst, addr_t * src, addr_t * flags) { \
160     uint64_t tmp_dst = *dst, tmp_src = *src;                                    \
161     addr_t tmp_flags = *flags;                                          \
162                                                                         \
163     /* Some of the flags values are not copied out in a pushf, we save them here */ \
164     addr_t flags_rsvd = *flags & ~0xfffe7fff;                           \
165                                                                         \
166     asm volatile (                                                              \
167          "pushfq\r\n"                                                   \
168          "push %3\r\n"                                                  \
169          "popfq\r\n"                                                    \
170          #iname"q %2, %0\r\n"                                           \
171          "pushfq\r\n"                                                   \
172          "pop %1\r\n"                                                   \
173          "popfq\r\n"                                                    \
174          : "=q"(tmp_dst),"=q"(tmp_flags)                                \
175          : "q"(tmp_src),"q"(tmp_flags), "0"(tmp_dst)                    \
176          );                                                             \
177                                                                         \
178     *dst = tmp_dst;                                                     \
179     *flags = tmp_flags;                                                 \
180     *flags |= flags_rsvd;                                               \
181                                                                         \
182   }
183
184
185
186
187 #define MAKE_2OP_32FLAGS_INST(iname) static inline void iname##32(addr_t * dst, addr_t * src, addr_t * flags) { \
188     uint32_t tmp_dst = *dst, tmp_src = *src;                            \
189                                                                         \
190     /* Some of the flags values are not copied out in a pushf, we save them here */ \
191     addr_t flags_rsvd = *flags & ~0xfffe7fff;                           \
192                                                                         \
193     asm volatile (                                                      \
194          "pushf; "                                                      \
195          "push %3; "                                                    \
196          "popf; "                                                       \
197          #iname"l %2, %0; "                                             \
198          "pushf; "                                                      \
199          "pop %1; "                                                     \
200          "popf; "                                                       \
201          : "=q"(tmp_dst),"=q"(*flags)                                   \
202          : "q"(tmp_src),"q"(*flags), "0"(tmp_dst)                       \
203          );                                                             \
204     *dst = tmp_dst;                                                     \
205     *flags |= flags_rsvd;                                               \
206                                                                         \
207   }
208
209
210 #define MAKE_2OP_16FLAGS_INST(iname) static inline void iname##16(addr_t * dst, addr_t * src, addr_t * flags) { \
211     ushort_t tmp_dst = *dst, tmp_src = *src;                            \
212                                                                         \
213     /* Some of the flags values are not copied out in a pushf, we save them here */ \
214     addr_t flags_rsvd = *flags & ~0xfffe7fff;                           \
215                                                                         \
216     asm volatile (                                                      \
217          "pushf; "                                                      \
218          "push %3; "                                                    \
219          "popf; "                                                       \
220          #iname"w %2, %0; "                                             \
221          "pushf; "                                                      \
222          "pop %1; "                                                     \
223          "popf; "                                                       \
224          : "=q"(tmp_dst),"=q"(*flags)                                   \
225          : "q"(tmp_src),"q"(*flags), "0"(tmp_dst)                       \
226          );                                                             \
227     *dst = tmp_dst;                                                     \
228     *flags |= flags_rsvd;                                               \
229                                                                         \
230   }
231
232 #define MAKE_2OP_8FLAGS_INST(iname) static inline void iname##8(addr_t * dst, addr_t * src, addr_t * flags) { \
233     uchar_t tmp_dst = *dst, tmp_src = *src;                             \
234                                                                         \
235     /* Some of the flags values are not copied out in a pushf, we save them here */ \
236     addr_t flags_rsvd = *flags & ~0xfffe7fff;                           \
237                                                                         \
238     asm volatile (                                                      \
239          "pushf; "                                                      \
240          "push %3; "                                                    \
241          "popf; "                                                       \
242          #iname"b %2, %0; "                                             \
243          "pushf; "                                                      \
244          "pop %1; "                                                     \
245          "popf; "                                                       \
246          : "=q"(tmp_dst),"=q"(*flags)                                   \
247          : "q"(tmp_src),"q"(*flags), "0"(tmp_dst)                       \
248          );                                                             \
249     *dst = tmp_dst;                                                     \
250     *flags |= flags_rsvd;                                               \
251                                                                         \
252   }
253
254
255
256
257
258 #define MAKE_2OP_64STR_INST(iname) static inline void iname##64(addr_t * dst, \
259                                                                  addr_t * src, \
260                                                                  addr_t * ecx, addr_t * flags) { \
261     /* Some of the flags values are not copied out in a pushf, we save them here */ \
262     addr_t flags_rsvd = *flags & ~0xfffe7fff;                           \
263                                                                         \
264     asm volatile (                                                      \
265          "pushfq; "                                                     \
266          "pushq %4; "                                                   \
267          "popfq; "                                                      \
268          "rep; "                                                        \
269          #iname"q; "                                                    \
270          "pushfq; "                                                     \
271          "popq %0; "                                                    \
272          "popfq; "                                                      \
273          : "=q"(*flags)                                                 \
274          : "D"(*dst),"S"(*src),"c"(*ecx),"q"(*flags)                    \
275          );                                                             \
276                                                                         \
277     /*   : "=D"(*dst),"=S"(*src),"=c"(*ecx),"=q"(*flags)*/              \
278     *flags |= flags_rsvd;                                               \
279   }
280
281
282 #define MAKE_2OP_32STR_INST(iname) static inline void iname##32(addr_t * dst, \
283                                                                 addr_t * src, \
284                                                                 addr_t * ecx, addr_t * flags) { \
285     /* Some of the flags values are not copied out in a pushf, we save them here */ \
286     addr_t flags_rsvd = *flags & ~0xfffe7fff;                           \
287                                                                         \
288     asm volatile (                                                      \
289          "pushf; "                                                      \
290          "push %4; "                                                    \
291          "popf; "                                                       \
292          "rep; "                                                        \
293          #iname"l; "                                                    \
294          "pushf; "                                                      \
295          "pop %0; "                                                     \
296          "popf; "                                                       \
297          : "=q"(*flags)                                                 \
298          : "D"(*dst),"S"(*src),"c"(*ecx),"q"(*flags)                    \
299          );                                                             \
300                                                                         \
301     /*   : "=D"(*dst),"=S"(*src),"=c"(*ecx),"=q"(*flags)*/              \
302     *flags |= flags_rsvd;                                               \
303   }
304
305 #define MAKE_2OP_16STR_INST(iname) static inline void iname##16(addr_t * dst, \
306                                                                 addr_t * src, \
307                                                                 addr_t * ecx, addr_t * flags) { \
308      /* Some of the flags values are not copied out in a pushf, we save them here */ \
309     addr_t flags_rsvd = *flags & ~0xfffe7fff;                           \
310                                                                         \
311     asm volatile (                                                      \
312          "pushf; "                                                      \
313          "push %4; "                                                    \
314          "popf; "                                                       \
315          "rep; "                                                        \
316          #iname"w; "                                                    \
317          "pushf; "                                                      \
318          "pop %0; "                                                     \
319          "popf; "                                                       \
320          : "=q"(*flags)                                                 \
321          : "D"(*dst),"S"(*src),"c"(*ecx),"q"(*flags)                    \
322          );                                                             \
323     *flags |= flags_rsvd;                                               \
324   }
325
326
327
328 #define MAKE_2OP_8STR_INST(iname) static inline void iname##8(addr_t * dst, \
329                                                               addr_t * src, \
330                                                               addr_t * ecx, addr_t * flags) { \
331     /* Some of the flags values are not copied out in a pushf, we save them here */ \
332     addr_t flags_rsvd = *flags & ~0xfffe7fff;                           \
333                                                                         \
334     asm volatile (                                                      \
335          "pushf; "                                                      \
336          "push %4; "                                                    \
337          "popf; "                                                       \
338          "rep; "                                                        \
339          #iname"b; "                                                    \
340          "pushf; "                                                      \
341          "pop %0; "                                                     \
342          "popf; "                                                       \
343          : "=q"(*flags)                                                 \
344          : "D"(*dst),"S"(*src),"c"(*ecx),"q"(*flags)                    \
345          );                                                             \
346     *flags |= flags_rsvd;                                               \
347   }
348
349
350
351
352 #define MAKE_2OP_64_INST(iname) static inline void iname##64(addr_t * dst, addr_t * src) { \
353     uint64_t tmp_dst = *dst, tmp_src = *src;                            \
354                                                                         \
355     asm volatile (                                                      \
356          #iname"q %1, %0; "                                             \
357          : "=q"(tmp_dst)                                                \
358          : "q"(tmp_src), "0"(tmp_dst)                                   \
359          );                                                             \
360     *dst = tmp_dst;                                                     \
361   }
362
363 #define MAKE_2OP_32_INST(iname) static inline void iname##32(addr_t * dst, addr_t * src) { \
364     uint32_t tmp_dst = *dst, tmp_src = *src;                            \
365                                                                         \
366     asm volatile (                                                      \
367          #iname"l %1, %0; "                                             \
368          : "=q"(tmp_dst)                                                \
369          : "q"(tmp_src), "0"(tmp_dst)                                   \
370          );                                                             \
371     *dst = tmp_dst;                                                     \
372   }
373
374 #define MAKE_2OP_16_INST(iname) static inline void iname##16(addr_t * dst, addr_t * src) { \
375     ushort_t tmp_dst = *dst, tmp_src = *src;                            \
376                                                                         \
377     asm volatile (                                                      \
378          #iname"w %1, %0; "                                             \
379          : "=q"(tmp_dst)                                                \
380          : "q"(tmp_src), "0"(tmp_dst)                                   \
381          );                                                             \
382     *dst = tmp_dst;                                                     \
383   }
384
385 #define MAKE_2OP_8_INST(iname) static inline void iname##8(addr_t * dst, addr_t * src) { \
386     uchar_t tmp_dst = *dst, tmp_src = *src;                             \
387                                                                         \
388     asm volatile (                                                      \
389          #iname"b %1, %0; "                                             \
390          : "=q"(tmp_dst)                                                \
391          : "q"(tmp_src), "0"(tmp_dst)                                   \
392          );                                                             \
393     *dst = tmp_dst;                                                     \
394   }
395
396
397
398
399
400 #define MAKE_2OP_8EXT_INST(iname) static inline void iname##8(addr_t * dst, addr_t * src, uint_t dst_len) { \
401     if (dst_len == 2) {                                                 \
402       asm volatile (                                                    \
403                     #iname" %1, %0; "                                   \
404                     : "=q"(*(uint16_t *)dst)                            \
405                     : "q"(*(uint8_t *)src), "0"(*(uint16_t *)dst)       \
406                     );                                                  \
407     } else if (dst_len == 4) {                                          \
408       asm volatile (                                                    \
409                     #iname" %1, %0; "                                   \
410                     : "=q"(*(uint32_t *)dst)                            \
411                     : "q"(*(uint8_t *)src), "0"(*(uint32_t *)dst)       \
412                     );                                                  \
413     } else if (dst_len == 8) {                                          \
414       asm volatile (                                                    \
415                     #iname" %1, %0; "                                   \
416                     : "=q"(*(uint64_t *)dst)                            \
417                     : "q"(*(uint8_t *)src), "0"(*(uint64_t *)dst)       \
418                     );                                                  \
419     }                                                                   \
420   }
421
422 #define MAKE_2OP_16EXT_INST(iname) static inline void iname##16(addr_t * dst, addr_t * src, uint_t dst_len) { \
423     if (dst_len == 4) {                                                 \
424       asm volatile (                                                    \
425                     #iname" %1, %0; "                                   \
426                     : "=q"(*(uint32_t *)dst)                            \
427                     : "q"(*(uint16_t *)src), "0"(*(uint32_t *)dst)      \
428                     );                                                  \
429     } else if (dst_len == 8) {                                          \
430       asm volatile (                                                    \
431                     #iname" %1, %0; "                                   \
432                     : "=q"(*(uint64_t *)dst)                            \
433                     : "q"(*(uint16_t *)src), "0"(*(uint64_t *)dst)      \
434                     );                                                  \
435     }                                                                   \
436   }
437
438
439
440
441
442
443 /****************************/
444 /* 8 Bit instruction forms  */
445 /****************************/
446
447 MAKE_2OP_8FLAGS_INST(adc);
448 MAKE_2OP_8FLAGS_INST(add);
449 MAKE_2OP_8FLAGS_INST(and);
450 MAKE_2OP_8FLAGS_INST(or);
451 MAKE_2OP_8FLAGS_INST(xor);
452 MAKE_2OP_8FLAGS_INST(sub);
453
454
455 MAKE_1OP_8FLAGS_INST(inc);
456 MAKE_1OP_8FLAGS_INST(dec);
457 MAKE_1OP_8FLAGS_INST(neg);
458 MAKE_1OP_8FLAGS_INST(setb);
459 MAKE_1OP_8FLAGS_INST(setbe);
460 MAKE_1OP_8FLAGS_INST(setl);
461 MAKE_1OP_8FLAGS_INST(setle);
462 MAKE_1OP_8FLAGS_INST(setnb);
463 MAKE_1OP_8FLAGS_INST(setnbe);
464 MAKE_1OP_8FLAGS_INST(setnl);
465 MAKE_1OP_8FLAGS_INST(setnle);
466 MAKE_1OP_8FLAGS_INST(setno);
467 MAKE_1OP_8FLAGS_INST(setnp);
468 MAKE_1OP_8FLAGS_INST(setns);
469 MAKE_1OP_8FLAGS_INST(setnz);
470 MAKE_1OP_8FLAGS_INST(seto);
471 MAKE_1OP_8FLAGS_INST(setp);
472 MAKE_1OP_8FLAGS_INST(sets);
473 MAKE_1OP_8FLAGS_INST(setz);
474
475
476 MAKE_1OP_8_INST(not);
477
478 MAKE_2OP_8_INST(mov);
479 MAKE_2OP_8EXT_INST(movzx);
480 MAKE_2OP_8EXT_INST(movsx);
481
482 MAKE_2OP_8_INST(xchg);
483
484 MAKE_2OP_8STR_INST(movs);
485
486
487 /****************************/
488 /* 16 Bit instruction forms */
489 /****************************/
490 MAKE_2OP_16FLAGS_INST(adc);
491 MAKE_2OP_16FLAGS_INST(add);
492 MAKE_2OP_16FLAGS_INST(and);
493 MAKE_2OP_16FLAGS_INST(or);
494 MAKE_2OP_16FLAGS_INST(xor);
495 MAKE_2OP_16FLAGS_INST(sub);
496
497
498 MAKE_1OP_16FLAGS_INST(inc);
499 MAKE_1OP_16FLAGS_INST(dec);
500 MAKE_1OP_16FLAGS_INST(neg);
501
502 MAKE_1OP_16_INST(not);
503
504 MAKE_2OP_16_INST(mov);
505 MAKE_2OP_16EXT_INST(movzx);
506 MAKE_2OP_16EXT_INST(movsx);
507 MAKE_2OP_16_INST(xchg);
508
509 MAKE_2OP_16STR_INST(movs);
510
511 /****************************/
512 /* 32 Bit instruction forms */
513 /****************************/
514 MAKE_2OP_32FLAGS_INST(adc);
515 MAKE_2OP_32FLAGS_INST(add);
516 MAKE_2OP_32FLAGS_INST(and);
517 MAKE_2OP_32FLAGS_INST(or);
518 MAKE_2OP_32FLAGS_INST(xor);
519 MAKE_2OP_32FLAGS_INST(sub);
520
521
522 MAKE_1OP_32FLAGS_INST(inc);
523 MAKE_1OP_32FLAGS_INST(dec);
524 MAKE_1OP_32FLAGS_INST(neg);
525
526 MAKE_1OP_32_INST(not);
527
528 MAKE_2OP_32_INST(mov);
529
530 MAKE_2OP_32_INST(xchg);
531
532
533
534 MAKE_2OP_32STR_INST(movs);
535
536 #ifdef __V3_64BIT__
537
538 /****************************/
539 /* 64 Bit instruction forms */
540 /****************************/
541 MAKE_2OP_64FLAGS_INST(adc);
542 MAKE_2OP_64FLAGS_INST(add);
543 MAKE_2OP_64FLAGS_INST(and);
544 MAKE_2OP_64FLAGS_INST(or);
545 MAKE_2OP_64FLAGS_INST(xor);
546 MAKE_2OP_64FLAGS_INST(sub);
547
548 MAKE_1OP_64FLAGS_INST(inc);
549 MAKE_1OP_64FLAGS_INST(dec);
550 MAKE_1OP_64FLAGS_INST(neg);
551
552 MAKE_1OP_64_INST(not);
553
554
555 MAKE_2OP_64_INST(mov);
556
557
558 MAKE_2OP_64_INST(xchg);
559
560
561 #endif