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.


cleaned up emulation interface
[palacios.git] / palacios / src / palacios / vmm_emulator.c
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.h>
21 #include <palacios/vmm_emulator.h>
22 #include <palacios/vm_guest_mem.h>
23 #include <palacios/vmm_decoder.h>
24 #include <palacios/vmm_paging.h>
25 #include <palacios/vmm_instr_emulator.h>
26
27 #ifndef DEBUG_EMULATOR
28 #undef PrintDebug
29 #define PrintDebug(fmt, args...)
30 #endif
31
32
33
34
35
36
37 static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_addr, addr_t dst_addr, int op_size);
38
39 // We emulate up to the next 4KB page boundry
40 static int emulate_string_write_op(struct guest_info * info, struct x86_instr * dec_instr, 
41                                    addr_t write_gva, addr_t write_gpa, addr_t dst_addr, 
42                                    int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data), 
43                                    void * priv_data) {
44   uint_t emulation_length = 0;
45   addr_t tmp_rcx = 0;
46   addr_t src_addr = 0;
47
48   if (dec_instr->op_type == V3_OP_MOVS) {
49     PrintError("MOVS emulation\n");
50
51     if (dec_instr->dst_operand.operand != write_gva) {
52       PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
53                  (void *)dec_instr->dst_operand.operand, (void *)write_gva);
54       return -1;
55     }
56
57     emulation_length = ( (dec_instr->str_op_length  < (0x1000 - PAGE_OFFSET_4KB(write_gva))) ? 
58                          dec_instr->str_op_length :
59                          (0x1000 - PAGE_OFFSET_4KB(write_gva)));
60     /* ** Fix emulation length so that it doesn't overrun over the src page either ** */
61
62
63     PrintDebug("STR_OP_LEN: %d, Page Len: %d\n", 
64                (uint_t)dec_instr->str_op_length, 
65                (uint_t)(0x1000 - PAGE_OFFSET_4KB(write_gva)));
66     PrintDebug("Emulation length: %d\n", emulation_length);
67     tmp_rcx = emulation_length;
68  
69
70
71     // figure out addresses here....
72     if (info->mem_mode == PHYSICAL_MEM) {
73       if (guest_pa_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) {
74         PrintError("Could not translate write Source (Physical) to host VA\n");
75         return -1;
76       }
77     } else {
78       if (guest_va_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) {
79         PrintError("Could not translate write Source (Virtual) to host VA\n");
80         return -1;
81       }
82     }
83
84
85     PrintDebug("Dst Operand: %p (size=%d), Src Operand: %p\n", 
86                (void *)dec_instr->dst_operand.operand, 
87                dec_instr->dst_operand.size,
88                (void *)dec_instr->src_operand.operand);
89     PrintDebug("Dst Addr: %p, Src Addr: %p\n", (void *)dst_addr, (void *)src_addr);
90
91     //return -1;
92
93
94  
95
96
97     if (dec_instr->dst_operand.size == 1) {
98       movs8((addr_t *)dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
99     } else if (dec_instr->dst_operand.size == 2) {
100       movs16((addr_t *)dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
101     } else if (dec_instr->dst_operand.size == 4) {
102       movs32((addr_t*)dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
103     } else {
104       PrintError("Invalid operand length\n");
105       return -1;
106     }
107
108
109     if (write_fn(write_gpa, (void *)dst_addr, emulation_length, priv_data) != emulation_length) {
110       PrintError("Did not fully read hooked data\n");
111       return -1;
112     }
113
114
115     PrintDebug("RDI=%p, RSI=%p, RCX=%p\n", 
116                (void *)*(addr_t *)&(info->vm_regs.rdi), 
117                (void *)*(addr_t *)&(info->vm_regs.rsi), 
118                (void *)*(addr_t *)&(info->vm_regs.rcx)); 
119
120     info->vm_regs.rdi += emulation_length;
121     info->vm_regs.rsi += emulation_length;
122     info->vm_regs.rcx -= emulation_length;
123     
124     PrintDebug("RDI=%p, RSI=%p, RCX=%p\n", 
125                (void *)*(addr_t *)&(info->vm_regs.rdi), 
126                (void *)*(addr_t *)&(info->vm_regs.rsi), 
127                (void *)*(addr_t *)&(info->vm_regs.rcx)); 
128
129     if (emulation_length == dec_instr->str_op_length) {
130       info->rip += dec_instr->instr_length;
131     }
132
133     return emulation_length;
134   }
135
136   
137
138
139   return -1;
140 }
141
142
143
144
145
146 int v3_emulate_write_op(struct guest_info * info, addr_t write_gva, addr_t write_gpa,  addr_t dst_addr, 
147                        int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data), 
148                        void * priv_data) {
149   struct x86_instr dec_instr;
150   uchar_t instr[15];
151   int ret = 0;
152   addr_t src_addr = 0;
153   int op_len = 0;
154
155   PrintDebug("Emulating Write for instruction at %p\n", (void *)(addr_t)(info->rip));
156   PrintDebug("GVA=%p\n", (void *)write_gva);
157
158   if (info->mem_mode == PHYSICAL_MEM) { 
159     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
160   } else { 
161     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
162   }
163
164   if (ret == -1) {
165     return -1;
166   }
167
168   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
169     PrintError("Decoding Error\n");
170     // Kick off single step emulator
171     return -1;
172   }
173   
174   if (dec_instr.is_str_op) {
175     return emulate_string_write_op(info, &dec_instr, write_gva, write_gpa, dst_addr, write_fn, priv_data);
176   }
177
178
179   if ((dec_instr.dst_operand.type != MEM_OPERAND) ||
180       (dec_instr.dst_operand.operand != write_gva)) {
181     PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
182                (void *)dec_instr.dst_operand.operand, (void *)write_gva);
183     return -1;
184   }
185
186
187   if (dec_instr.src_operand.type == MEM_OPERAND) {
188     if (info->mem_mode == PHYSICAL_MEM) {
189       if (guest_pa_to_host_va(info, dec_instr.src_operand.operand, &src_addr) == -1) {
190         PrintError("Could not translate write Source (Physical) to host VA\n");
191         return -1;
192       }
193     } else {
194       if (guest_va_to_host_va(info, dec_instr.src_operand.operand, &src_addr) == -1) {
195         PrintError("Could not translate write Source (Virtual) to host VA\n");
196         return -1;
197       }
198     }
199   } else if (dec_instr.src_operand.type == REG_OPERAND) {
200     src_addr = dec_instr.src_operand.operand;
201   } else {
202     src_addr = (addr_t)&(dec_instr.src_operand.operand);
203   }
204
205   op_len = dec_instr.dst_operand.size;
206
207   PrintDebug("Dst_Addr = %p, SRC operand = %p\n", 
208              (void *)dst_addr, (void *)src_addr);
209
210
211   if (run_op(info, dec_instr.op_type, src_addr, dst_addr, op_len) == -1) {
212     PrintError("Instruction Emulation Failed\n");
213     return -1;
214   }
215
216   if (write_fn(write_gpa, (void *)dst_addr, op_len, priv_data) != op_len) {
217     PrintError("Did not fully read hooked data\n");
218     return -1;
219   }
220
221   info->rip += dec_instr.instr_length;
222
223   return op_len;
224 }
225
226
227 int v3_emulate_read_op(struct guest_info * info, addr_t read_gva, addr_t read_gpa, addr_t src_addr,
228                        int (*read_fn)(addr_t guest_addr, void * dst, uint_t length, void * priv_data), 
229                        void * priv_data) {
230   struct x86_instr dec_instr;
231   uchar_t instr[15];
232   int ret = 0;
233   addr_t dst_addr = 0;
234   int op_len = 0;
235
236   PrintDebug("Emulating Read for instruction at %p\n", (void *)(addr_t)(info->rip));
237   PrintDebug("GVA=%p\n", (void *)write_gva);
238
239   if (info->mem_mode == PHYSICAL_MEM) { 
240     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
241   } else { 
242     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
243   }
244
245   if (ret == -1) {
246     return -1;
247   }
248
249   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
250     PrintError("Decoding Error\n");
251     // Kick off single step emulator
252     return -1;
253   }
254   
255   if (dec_instr.is_str_op) {
256     PrintError("String operations not implemented on fully hooked regions\n");
257     return -1;
258   }
259
260
261   if ((dec_instr.src_operand.type != MEM_OPERAND) ||
262       (dec_instr.src_operand.operand != read_gva)) {
263     PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
264                (void *)dec_instr.src_operand.operand, (void *)read_gva);
265     return -1;
266   }
267
268
269   if (dec_instr.dst_operand.type == MEM_OPERAND) {
270     if (info->mem_mode == PHYSICAL_MEM) {
271       if (guest_pa_to_host_va(info, dec_instr.dst_operand.operand, &dst_addr) == -1) {
272         PrintError("Could not translate Read Destination (Physical) to host VA\n");
273         return -1;
274       }
275     } else {
276       if (guest_va_to_host_va(info, dec_instr.dst_operand.operand, &dst_addr) == -1) {
277         PrintError("Could not translate Read Destination (Virtual) to host VA\n");
278         return -1;
279       }
280     }
281   } else if (dec_instr.dst_operand.type == REG_OPERAND) {
282     dst_addr = dec_instr.dst_operand.operand;
283   } else {
284     dst_addr = (addr_t)&(dec_instr.dst_operand.operand);
285   }
286
287   op_len = dec_instr.src_operand.size;
288
289   PrintDebug("Dst_Addr = %p, SRC Addr = %p\n", 
290              (void *)dst_addr, (void *)src_addr);
291
292   if (read_fn(read_gpa, (void *)src_addr,op_len, priv_data) != op_len) {
293     PrintError("Did not fully read hooked data\n");
294     return -1;
295   }
296
297   if (run_op(info, dec_instr.op_type, src_addr, dst_addr, op_len) == -1) {
298     PrintError("Instruction Emulation Failed\n");
299     return -1;
300   }
301
302   info->rip += dec_instr.instr_length;
303
304   return op_len;
305 }
306
307
308
309
310
311
312 static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_addr, addr_t dst_addr, int op_size) {
313
314   if (op_size == 1) {
315
316     switch (op_type) {
317     case V3_OP_ADC:
318       adc8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
319       break;
320     case V3_OP_ADD:
321       add8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
322       break;
323     case V3_OP_AND:
324       and8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
325       break;
326     case V3_OP_OR:
327       or8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
328       break;
329     case V3_OP_XOR:
330       xor8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
331       break;
332     case V3_OP_SUB:
333       sub8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
334       break;
335
336     case V3_OP_MOV:
337       mov8((addr_t *)dst_addr, (addr_t *)src_addr);
338       break;
339     case V3_OP_NOT:
340       not8((addr_t *)dst_addr);
341       break;
342     case V3_OP_XCHG:
343       xchg8((addr_t *)dst_addr, (addr_t *)src_addr);
344       break;
345       
346
347     case V3_OP_INC:
348       inc8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
349       break;
350     case V3_OP_DEC:
351       dec8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
352       break;
353     case V3_OP_NEG:
354       neg8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
355       break;
356     case V3_OP_SETB:
357       setb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
358       break;
359     case V3_OP_SETBE:
360       setbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
361       break;
362     case V3_OP_SETL:
363       setl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
364       break;
365     case V3_OP_SETLE:
366       setle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
367       break;
368     case V3_OP_SETNB:
369       setnb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
370       break;
371     case V3_OP_SETNBE:
372       setnbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
373       break;
374     case V3_OP_SETNL:
375       setnl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
376       break;
377     case V3_OP_SETNLE:
378       setnle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
379       break;
380     case V3_OP_SETNO:
381       setno8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
382       break;
383     case V3_OP_SETNP:
384       setnp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
385       break;
386     case V3_OP_SETNS:
387       setns8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
388       break;
389     case V3_OP_SETNZ:
390       setnz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
391       break;
392     case V3_OP_SETO:
393       seto8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
394       break;
395     case V3_OP_SETP:
396       setp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
397       break;
398     case V3_OP_SETS:
399       sets8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
400       break;
401     case V3_OP_SETZ:
402       setz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
403       break;
404
405     default:
406       PrintError("Unknown 8 bit instruction\n");
407       return -1;
408     }
409
410   } else if (op_size == 2) {
411
412     switch (op_type) {
413     case V3_OP_ADC:
414       adc16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
415       break;
416     case V3_OP_ADD:
417       add16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
418       break;
419     case V3_OP_AND:
420       and16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
421       break;
422     case V3_OP_OR:
423       or16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
424       break;
425     case V3_OP_XOR:
426       xor16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
427       break;
428     case V3_OP_SUB:
429       sub16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
430       break;
431
432
433     case V3_OP_INC:
434       inc16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
435       break;
436     case V3_OP_DEC:
437       dec16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
438       break;
439     case V3_OP_NEG:
440       neg16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
441       break;
442
443     case V3_OP_MOV:
444       mov16((addr_t *)dst_addr, (addr_t *)src_addr);
445       break;
446     case V3_OP_NOT:
447       not16((addr_t *)dst_addr);
448       break;
449     case V3_OP_XCHG:
450       xchg16((addr_t *)dst_addr, (addr_t *)src_addr);
451       break;
452       
453     default:
454       PrintError("Unknown 16 bit instruction\n");
455       return -1;
456     }
457
458   } else if (op_size == 4) {
459
460     switch (op_type) {
461     case V3_OP_ADC:
462       adc32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
463       break;
464     case V3_OP_ADD:
465       add32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
466       break;
467     case V3_OP_AND:
468       and32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
469       break;
470     case V3_OP_OR:
471       or32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
472       break;
473     case V3_OP_XOR:
474       xor32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
475       break;
476     case V3_OP_SUB:
477       sub32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
478       break;
479
480     case V3_OP_INC:
481       inc32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
482       break;
483     case V3_OP_DEC:
484       dec32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
485       break;
486     case V3_OP_NEG:
487       neg32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
488       break;
489
490     case V3_OP_MOV:
491       mov32((addr_t *)dst_addr, (addr_t *)src_addr);
492       break;
493     case V3_OP_NOT:
494       not32((addr_t *)dst_addr);
495       break;
496     case V3_OP_XCHG:
497       xchg32((addr_t *)dst_addr, (addr_t *)src_addr);
498       break;
499       
500     default:
501       PrintError("Unknown 32 bit instruction\n");
502       return -1;
503     }
504
505   } else if (op_size == 8) {
506     PrintError("64 bit instructions not handled\n");
507     return -1;
508   } else {
509     PrintError("Invalid Operation Size\n");
510     return -1;
511   }
512
513   return 0;
514 }