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.


Support for full memory hooks with string instructions
[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 CONFIG_DEBUG_EMULATOR
28 #undef PrintDebug
29 #define PrintDebug(fmt, args...)
30 #endif
31
32
33 static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_addr, addr_t dst_addr, int src_op_size, int dst_op_size);
34
35 // We emulate up to the next 4KB page boundry
36 static int emulate_string_write_op(struct guest_info * info, struct x86_instr * dec_instr, 
37                                    addr_t write_gva, addr_t write_gpa, addr_t dst_addr, 
38                                    int (*write_fn)(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data), 
39                                    void * priv_data) {
40     uint_t emulation_length = 0;
41     uint_t emulation_iter_cnt = 0;
42     addr_t tmp_rcx = 0;
43     addr_t src_addr = 0;
44
45     if (info->shdw_pg_mode == SHADOW_PAGING) {
46         if (dec_instr->dst_operand.operand != write_gva) {
47             PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
48                        (void *)dec_instr->dst_operand.operand, (void *)write_gva);
49             return -1;
50         }
51     } else {
52         // Nested paging (Need check??) 
53     }
54
55     /*emulation_length = ( (dec_instr->str_op_length  < (0x1000 - PAGE_OFFSET_4KB(write_gva))) ? 
56                          dec_instr->str_op_length :
57                          (0x1000 - PAGE_OFFSET_4KB(write_gva)));*/
58
59     if ((dec_instr->str_op_length * (dec_instr->dst_operand.size))  < (0x1000 - PAGE_OFFSET_4KB(write_gva))) { 
60         emulation_length = dec_instr->str_op_length * dec_instr->dst_operand.size;
61     } else {
62         emulation_length = (0x1000 - PAGE_OFFSET_4KB(write_gva));
63         PrintError("Warning: emulate_string_write_op emulating %u length operation, but request is for %u length\n", 
64                    emulation_length, (uint32_t)(dec_instr->str_op_length*(dec_instr->dst_operand.size)));
65     }
66   
67     /* ** Fix emulation length so that it doesn't overrun over the src page either ** */
68     emulation_iter_cnt = emulation_length / dec_instr->dst_operand.size;
69     tmp_rcx = emulation_iter_cnt;
70   
71     if (dec_instr->op_type == V3_OP_MOVS) {
72
73         // figure out addresses here....
74         if (info->mem_mode == PHYSICAL_MEM) {
75             if (v3_gpa_to_hva(info, dec_instr->src_operand.operand, &src_addr) == -1) {
76                 PrintError("Could not translate write Source (Physical) to host VA\n");
77                 return -1;
78             }
79         } else {
80             if (v3_gva_to_hva(info, dec_instr->src_operand.operand, &src_addr) == -1) {
81                 PrintError("Could not translate write Source (Virtual) to host VA\n");
82                 return -1;
83             }
84         }
85
86         if (dec_instr->dst_operand.size == 1) {
87             movs8((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
88         } else if (dec_instr->dst_operand.size == 2) {
89             movs16((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
90         } else if (dec_instr->dst_operand.size == 4) {
91             movs32((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
92 #ifdef __V3_64BIT__
93         } else if (dec_instr->dst_operand.size == 8) {
94             movs64((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
95 #endif
96         } else {
97             PrintError("Invalid operand length\n");
98             return -1;
99         }
100
101         info->vm_regs.rdi += emulation_length;
102         info->vm_regs.rsi += emulation_length;
103
104         // RCX is only modified if the rep prefix is present
105         if (dec_instr->prefixes.rep == 1) {
106             info->vm_regs.rcx -= emulation_iter_cnt;
107         }
108
109     } else if (dec_instr->op_type == V3_OP_STOS) {
110
111         if (dec_instr->dst_operand.size == 1) {
112             stos8((addr_t *)&dst_addr, (addr_t  *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
113         } else if (dec_instr->dst_operand.size == 2) {
114             stos16((addr_t *)&dst_addr, (addr_t  *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
115         } else if (dec_instr->dst_operand.size == 4) {
116             stos32((addr_t *)&dst_addr, (addr_t  *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
117 #ifdef __V3_64BIT__
118         } else if (dec_instr->dst_operand.size == 8) {
119             stos64((addr_t *)&dst_addr, (addr_t  *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
120 #endif
121         } else {
122             PrintError("Invalid operand length\n");
123             return -1;
124         }
125
126         info->vm_regs.rdi += emulation_length;
127     
128         // RCX is only modified if the rep prefix is present
129         if (dec_instr->prefixes.rep == 1) {
130             info->vm_regs.rcx -= emulation_iter_cnt;
131         }
132
133     } else {
134         PrintError("Unimplemented String operation\n");
135         return -1;
136     }
137
138     if (write_fn(info, write_gpa, (void *)dst_addr, emulation_length, priv_data) != emulation_length) {
139         PrintError("Did not fully read hooked data\n");
140         return -1;
141     }
142
143     if (emulation_length == dec_instr->str_op_length) {
144         info->rip += dec_instr->instr_length;
145     }
146
147     return emulation_length;
148 }
149
150
151
152 /*
153   This function is intended to handle pure read hooks, pure write hook, and full hooks, 
154   with and without backing memory for writes
155   
156   read_fn == NULL  
157       orig_src_addr == NULL => data at read_gpa is read
158       orig_src_addr != NULL => data at orig_src_addr is read
159   read_fn != NULL  data is collected using read_fn
160
161   write_fn == NULL 
162       orig_dst_addr == NULL => data is written to write_gpa
163       orig_dst_addr != NULL => data is written to orig_dst_addr
164   write_fn != NULL 
165       orig_dst_addr == NULL => data is sent to write_fn
166       orig_dst_addr != NULL => data is written to orig_dst_addr, then via write_fn
167
168
169 */
170 static int emulate_string_op(struct guest_info * info, struct x86_instr * dec_instr, 
171                              addr_t read_gva, addr_t read_gpa, addr_t orig_src_addr,
172                              addr_t write_gva, addr_t write_gpa, addr_t orig_dst_addr,
173                              int (*read_fn)(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data), 
174                              int (*write_fn)(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data), 
175                              void * priv_data) 
176 {
177     uint_t src_emulation_length = 0;
178     uint_t dst_emulation_length = 0;
179     uint_t emulation_length = 0;
180     uint_t emulation_iter_cnt = 0;
181     addr_t tmp_rcx = 0;
182     addr_t src_addr, dst_addr;
183
184     
185     // Sanity check the decoded instruction
186     
187     if (info->shdw_pg_mode == SHADOW_PAGING) {
188         if (!read_fn && (dec_instr->src_operand.operand != read_gva)) { 
189             PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p (Read)\n",
190                        (void *)dec_instr->src_operand.operand, (void *)read_gva);
191                 return -1;
192         }
193         if (!write_fn && (dec_instr->dst_operand.operand != write_gva)) {
194             PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p (Write)\n",
195                        (void *)dec_instr->dst_operand.operand, (void *)write_gva);
196             return -1;
197         }
198     } else {
199         // Nested paging (Need check??) 
200     }
201     
202
203     if (dec_instr->src_operand.size != dec_instr->dst_operand.size) { 
204         PrintError("Source and Destination Operands are of different sizes\n");
205         return -1;
206     }
207     
208
209     // We will only read up to the next page boundary
210
211     if ((dec_instr->str_op_length * (dec_instr->src_operand.size))  < (0x1000 - PAGE_OFFSET_4KB(read_gva))) { 
212         src_emulation_length = dec_instr->str_op_length * dec_instr->src_operand.size;
213     } else {
214         src_emulation_length = (0x1000 - PAGE_OFFSET_4KB(read_gva));
215         PrintError("Warning: emulate_string_op emulating src of %u length operation, but request is for %u length\n", 
216                    src_emulation_length, (uint32_t) (dec_instr->str_op_length*(dec_instr->src_operand.size)));
217     }
218
219     // We will only write up to the next page boundary
220
221     if ((dec_instr->str_op_length * (dec_instr->dst_operand.size))  < (0x1000 - PAGE_OFFSET_4KB(write_gva))) { 
222         dst_emulation_length = dec_instr->str_op_length * dec_instr->dst_operand.size;
223     } else {
224         dst_emulation_length = (0x1000 - PAGE_OFFSET_4KB(write_gva));
225         PrintError("Warning: emulate_string_op emulating dst of %u length operation, but request is for %u length\n", 
226                    dst_emulation_length, (uint32_t) (dec_instr->str_op_length*(dec_instr->dst_operand.size)));
227     }
228
229     // We will only copy the minimum of what is available to be read or written
230
231     if (src_emulation_length<dst_emulation_length) { 
232         emulation_length=src_emulation_length;
233         PrintError("Warning: emulate_string_op has src length %u but dst length %u\n", src_emulation_length, dst_emulation_length);
234     } else if (src_emulation_length>dst_emulation_length) { 
235         emulation_length=dst_emulation_length;
236         PrintError("Warning: emulate_string_op has src length %u but dst length %u\n", src_emulation_length, dst_emulation_length);
237     } else {
238         // equal
239         emulation_length=src_emulation_length;
240     }
241         
242
243     // Fetch the data
244
245     if (read_fn) { 
246         src_addr = (addr_t) V3_Malloc(emulation_length);  // hideous - should reuse memory
247         if (!src_addr) { 
248             PrintError("Unable to allocate space for read operation in emulate_string_read_op\n");
249             return -1;
250         }
251         if (read_fn(info, read_gpa, (void *)src_addr, emulation_length, priv_data) != emulation_length) {
252             PrintError("Did not fully read hooked data in emulate_string_op\n");
253             return -1;
254         }
255     } else {
256         if (orig_src_addr) { 
257             src_addr=orig_src_addr;
258         } else {
259             if (info->mem_mode == PHYSICAL_MEM) {
260                 if (v3_gpa_to_hva(info, dec_instr->src_operand.operand, &src_addr) == -1) {
261                     PrintError("Could not translate write Source (Physical) to host VA\n");
262                     return -1;
263                 }
264             } else {
265                 if (v3_gva_to_hva(info, dec_instr->src_operand.operand, &src_addr) == -1) {
266                     PrintError("Could not translate write Source (Virtual) to host VA\n");
267                     return -1;
268             }
269             }
270         }
271     }
272
273     // Now src_addr points to the fetched data in HVA
274
275     // Allocate space for the write, in case we need to copy out later
276     if (write_fn) { 
277         if (orig_dst_addr) { 
278             dst_addr=orig_dst_addr;
279         } else {
280             dst_addr = (addr_t) V3_Malloc(emulation_length);  // yuck
281             if (!dst_addr) { 
282                 PrintError("Unable to allocate space for write operation in emulate_string_op\n");
283                 if (read_fn) { 
284                     V3_Free((void*)src_addr); 
285                 }
286                 return -1;
287             }
288         }
289     } else {
290         if (orig_dst_addr) { 
291             dst_addr=orig_dst_addr;
292         } else {
293             if (info->mem_mode == PHYSICAL_MEM) {
294                 if (v3_gpa_to_hva(info, dec_instr->dst_operand.operand, &dst_addr) == -1) {
295                     PrintError("Could not translate write Dest (Physical) to host VA\n");
296                     return -1;
297                 }
298             } else {
299                 if (v3_gva_to_hva(info, dec_instr->dst_operand.operand, &dst_addr) == -1) {
300                     PrintError("Could not translate write Dest (Virtual) to host VA\n");
301                     return -1;
302                 }
303             }
304         }
305     }
306
307     // Now dst_addr points to where we will copy the data
308
309     // How many items to copy 
310     emulation_iter_cnt = emulation_length / dec_instr->dst_operand.size;
311     tmp_rcx = emulation_iter_cnt;
312
313
314     switch (dec_instr->op_type) { 
315
316         case V3_OP_MOVS: {
317             
318             if (dec_instr->dst_operand.size == 1) {
319                 movs8((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
320             } else if (dec_instr->dst_operand.size == 2) {
321                 movs16((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
322             } else if (dec_instr->dst_operand.size == 4) {
323                 movs32((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
324 #ifdef __V3_64BIT__
325             } else if (dec_instr->dst_operand.size == 8) {
326                 movs64((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
327 #endif
328             } else {
329                 PrintError("Invalid operand length\n");
330                 return -1;
331             }
332
333             // Can't these count down too? - PAD
334
335             info->vm_regs.rdi += emulation_length;
336             info->vm_regs.rsi += emulation_length;
337             
338             // RCX is only modified if the rep prefix is present
339             if (dec_instr->prefixes.rep == 1) {
340                 info->vm_regs.rcx -= emulation_iter_cnt;
341             }
342             
343         } 
344             break;
345
346         case V3_OP_STOS: {
347             
348             if (dec_instr->dst_operand.size == 1) {
349                 stos8((addr_t *)&dst_addr, (addr_t  *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
350             } else if (dec_instr->dst_operand.size == 2) {
351                 stos16((addr_t *)&dst_addr, (addr_t  *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
352             } else if (dec_instr->dst_operand.size == 4) {
353                 stos32((addr_t *)&dst_addr, (addr_t  *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
354 #ifdef __V3_64BIT__
355             } else if (dec_instr->dst_operand.size == 8) {
356                 stos64((addr_t *)&dst_addr, (addr_t  *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
357 #endif
358             } else {
359                 PrintError("Invalid operand length\n");
360                 return -1;
361             }
362             
363             info->vm_regs.rdi += emulation_length;
364             
365             // RCX is only modified if the rep prefix is present
366             if (dec_instr->prefixes.rep == 1) {
367                 info->vm_regs.rcx -= emulation_iter_cnt;
368             }
369             
370         } 
371             break;
372             
373         default:  {
374             PrintError("Unimplemented String operation\n");
375             return -1;
376         }
377             break;
378     }
379
380     // At this point, the data has been written over dst_addr, which 
381     // is either our temporary buffer, or it's the requested target in orig_dst_addr
382
383     if (write_fn) { 
384         if (write_fn(info, write_gpa, (void *)dst_addr, emulation_length, priv_data) != emulation_length) {
385             PrintError("Did not fully write hooked data\n");
386             return -1;
387         }
388     }
389
390     if (emulation_length == dec_instr->str_op_length) {
391         info->rip += dec_instr->instr_length;
392     }
393     
394
395     // Delete temporary buffers
396     if (read_fn) { 
397         V3_Free((void*)src_addr); 
398     }
399     if (write_fn && !orig_dst_addr) { 
400         V3_Free((void*)dst_addr);
401     }
402         
403
404     return emulation_length;
405 }
406
407
408
409
410
411 static int emulate_xchg_write_op(struct guest_info * info, struct x86_instr * dec_instr, 
412                                  addr_t write_gva, addr_t write_gpa, addr_t dst_addr, 
413                                  int (*write_fn)(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data), 
414                                  void * priv_data) {
415     addr_t src_addr = 0;
416     addr_t em_dst_addr = 0;
417     int src_op_len = 0;
418     int dst_op_len = 0;  
419     PrintDebug("Emulating XCHG write\n");
420
421     if (dec_instr->src_operand.type == MEM_OPERAND) {
422         if (info->shdw_pg_mode == SHADOW_PAGING) {
423             if (dec_instr->src_operand.operand != write_gva) {
424                 PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
425                            (void *)dec_instr->src_operand.operand, (void *)write_gva);
426                 return -1;
427             }
428         }
429
430         src_addr = dst_addr;
431     } else if (dec_instr->src_operand.type == REG_OPERAND) {
432         src_addr = dec_instr->src_operand.operand;
433     } else {
434         src_addr = (addr_t)&(dec_instr->src_operand.operand);
435     }
436
437
438
439     if (dec_instr->dst_operand.type == MEM_OPERAND) {
440         if (info->shdw_pg_mode == SHADOW_PAGING) {
441             if (dec_instr->dst_operand.operand != write_gva) {
442                 PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
443                            (void *)dec_instr->dst_operand.operand, (void *)write_gva);
444                 return -1;
445             }
446         } else {
447             //check that the operand (GVA) maps to the the faulting GPA
448         }
449         
450         em_dst_addr = dst_addr;
451     } else if (dec_instr->src_operand.type == REG_OPERAND) {
452         em_dst_addr = dec_instr->src_operand.operand;
453     } else {
454         em_dst_addr = (addr_t)&(dec_instr->src_operand.operand);
455     }
456     
457     dst_op_len = dec_instr->dst_operand.size;
458     src_op_len = dec_instr->src_operand.size;
459     
460     PrintDebug("Dst_Addr = %p, SRC operand = %p\n", 
461                (void *)dst_addr, (void *)src_addr);
462     
463     
464     if (run_op(info, dec_instr->op_type, src_addr, em_dst_addr, src_op_len, dst_op_len) == -1) {
465         PrintError("Instruction Emulation Failed\n");
466         return -1;
467     }
468     
469     if (write_fn(info, write_gpa, (void *)dst_addr, dst_op_len, priv_data) != dst_op_len) {
470         PrintError("Did not fully write hooked data\n");
471         return -1;
472     }
473     
474     info->rip += dec_instr->instr_length;
475     
476     return dst_op_len;
477 }
478     
479
480
481 static int emulate_xchg_read_op(struct guest_info * info, struct x86_instr * dec_instr, 
482                                 addr_t read_gva, addr_t read_gpa, addr_t src_addr, 
483                                 int (*read_fn)(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data), 
484                                 int (*write_fn)(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data),                      
485                                 void * priv_data) {
486     addr_t em_src_addr = 0;
487     addr_t em_dst_addr = 0;
488     int src_op_len = 0;
489     int dst_op_len = 0;
490
491     PrintDebug("Emulating XCHG Read\n");
492
493     if (dec_instr->src_operand.type == MEM_OPERAND) {
494         if (dec_instr->src_operand.operand != read_gva) {
495             PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
496                        (void *)dec_instr->src_operand.operand, (void *)read_gva);
497             return -1;
498         }
499     
500         em_src_addr = src_addr;
501     } else if (dec_instr->src_operand.type == REG_OPERAND) {
502         em_src_addr = dec_instr->src_operand.operand;
503     } else {
504         em_src_addr = (addr_t)&(dec_instr->src_operand.operand);
505     }
506
507
508
509     if (dec_instr->dst_operand.type == MEM_OPERAND) {
510         if (info->shdw_pg_mode == SHADOW_PAGING) {
511             if (dec_instr->dst_operand.operand != read_gva) {
512                 PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
513                            (void *)dec_instr->dst_operand.operand, (void *)read_gva);
514                 return -1;
515             }
516         } else {
517             //check that the operand (GVA) maps to the the faulting GPA
518         }
519
520         em_dst_addr = src_addr;
521     } else if (dec_instr->src_operand.type == REG_OPERAND) {
522         em_dst_addr = dec_instr->src_operand.operand;
523     } else {
524         em_dst_addr = (addr_t)&(dec_instr->src_operand.operand);
525     }
526
527     dst_op_len = dec_instr->dst_operand.size;
528     src_op_len = dec_instr->src_operand.size;
529
530     PrintDebug("Dst_Addr = %p, SRC operand = %p\n", 
531                (void *)em_dst_addr, (void *)em_src_addr);
532
533
534     if (read_fn(info, read_gpa, (void *)src_addr, src_op_len, priv_data) != src_op_len) {
535         PrintError("Did not fully read hooked data\n");
536         return -1;
537     }
538
539     if (run_op(info, dec_instr->op_type, em_src_addr, em_dst_addr, src_op_len, dst_op_len) == -1) {
540         PrintError("Instruction Emulation Failed\n");
541         return -1;
542     }
543
544     if (write_fn(info, read_gpa, (void *)src_addr, dst_op_len, priv_data) != dst_op_len) {
545         PrintError("Did not fully write hooked data\n");
546         return -1;
547     }
548
549     info->rip += dec_instr->instr_length;
550
551     return dst_op_len;
552 }
553
554
555
556
557 int v3_emulate_write_op(struct guest_info * info, addr_t write_gva, addr_t write_gpa,  addr_t dst_addr, 
558                         int (*write_fn)(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data), 
559                         void * priv_data) {
560     struct x86_instr dec_instr;
561     uchar_t instr[15];
562     int ret = 0;
563     addr_t src_addr = 0;
564     int src_op_len = 0;
565     int dst_op_len = 0;
566
567     PrintDebug("Emulating Write for instruction at %p\n", (void *)(addr_t)(info->rip));
568     PrintDebug("GVA=%p Dst_Addr=%p\n", (void *)write_gva, (void *)dst_addr);
569
570     if (info->mem_mode == PHYSICAL_MEM) { 
571         ret = v3_read_gpa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
572     } else { 
573         ret = v3_read_gva_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
574     }
575
576     if (ret == -1) {
577         return -1;
578     }
579
580     if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
581         PrintError("Decoding Error\n");
582         // Kick off single step emulator
583         return -1;
584     }
585   
586     /* 
587      * Instructions needing to be special cased.... *
588      */
589     if (dec_instr.is_str_op) {
590         return emulate_string_write_op(info, &dec_instr, write_gva, write_gpa, dst_addr, write_fn, priv_data);
591     } else if (dec_instr.op_type == V3_OP_XCHG) {
592         return emulate_xchg_write_op(info, &dec_instr, write_gva, write_gpa, dst_addr, write_fn, priv_data);
593     }
594
595
596     if (info->shdw_pg_mode == SHADOW_PAGING) {
597         if ((dec_instr.dst_operand.type != MEM_OPERAND) ||
598             (dec_instr.dst_operand.operand != write_gva)) {
599             PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
600                        (void *)dec_instr.dst_operand.operand, (void *)write_gva);
601             return -1;
602         }
603     } else {
604         //check that the operand (GVA) maps to the the faulting GPA
605     }
606
607
608     if (dec_instr.src_operand.type == MEM_OPERAND) {
609         if (info->mem_mode == PHYSICAL_MEM) {
610             if (v3_gpa_to_hva(info, dec_instr.src_operand.operand, &src_addr) == -1) {
611                 PrintError("Could not translate write Source (Physical) to host VA\n");
612                 return -1;
613             }
614         } else {
615             if (v3_gva_to_hva(info, dec_instr.src_operand.operand, &src_addr) == -1) {
616                 PrintError("Could not translate write Source (Virtual) to host VA\n");
617                 return -1;
618             }
619         }
620     } else if (dec_instr.src_operand.type == REG_OPERAND) {
621         src_addr = dec_instr.src_operand.operand;
622     } else {
623         src_addr = (addr_t)&(dec_instr.src_operand.operand);
624     }
625
626     dst_op_len = dec_instr.dst_operand.size;
627     src_op_len = dec_instr.src_operand.size;
628
629     PrintDebug("Dst_Addr = %p, SRC operand = %p\n", 
630                (void *)dst_addr, (void *)src_addr);
631
632
633     if (run_op(info, dec_instr.op_type, src_addr, dst_addr, src_op_len, dst_op_len) == -1) {
634         PrintError("Instruction Emulation Failed\n");
635         return -1;
636     }
637
638     if (write_fn(info, write_gpa, (void *)dst_addr, dst_op_len, priv_data) != dst_op_len) {
639         PrintError("Did not fully write hooked data\n");
640         return -1;
641     }
642
643     info->rip += dec_instr.instr_length;
644
645     return dst_op_len;
646 }
647
648
649 int v3_emulate_read_op(struct guest_info * info, addr_t read_gva, addr_t read_gpa, addr_t src_addr,
650                        int (*read_fn)(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data),
651                        int (*write_fn)(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data),  
652                        void * priv_data) {
653     struct x86_instr dec_instr;
654     uchar_t instr[15];
655     int ret = 0;
656     addr_t dst_addr = 0;
657     int src_op_len = 0;
658     int dst_op_len = 0;
659
660     PrintDebug("Emulating Read for instruction at %p\n", (void *)(addr_t)(info->rip));
661     PrintDebug("GVA=%p\n", (void *)read_gva);
662
663     if (info->mem_mode == PHYSICAL_MEM) { 
664         ret = v3_read_gpa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
665     } else { 
666         ret = v3_read_gva_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
667     }
668     
669     if (ret == -1) {
670         PrintError("Could not read instruction for Emulated Read at %p\n", (void *)(addr_t)(info->rip));
671         return -1;
672     }
673
674
675     if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
676         PrintError("Decoding Error\n");
677         // Kick off single step emulator
678         return -1;
679     }
680   
681     if (dec_instr.is_str_op) {
682         return emulate_string_op(info,&dec_instr,
683                                  read_gva,read_gpa,0,
684                                  0, 0, 0,
685                                  read_fn,write_fn,
686                                  priv_data);
687     } else if (dec_instr.op_type == V3_OP_XCHG) {
688         return emulate_xchg_read_op(info, &dec_instr, read_gva, read_gpa, src_addr, read_fn, write_fn, priv_data);
689     }
690
691     if (info->shdw_pg_mode == SHADOW_PAGING) {
692         if ((dec_instr.src_operand.type != MEM_OPERAND) ||
693             (dec_instr.src_operand.operand != read_gva)) {
694             PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p operand_type=%d\n",
695                        (void *)dec_instr.src_operand.operand, (void *)read_gva, dec_instr.src_operand.type);
696             return -1;
697         }
698     } else {
699         //check that the operand (GVA) maps to the the faulting GPA
700     }
701
702     if (dec_instr.dst_operand.type == MEM_OPERAND) {
703         if (info->mem_mode == PHYSICAL_MEM) {
704             if (v3_gpa_to_hva(info, dec_instr.dst_operand.operand, &dst_addr) == -1) {
705                 PrintError("Could not translate Read Destination (Physical) to host VA\n");
706                 return -1;
707             }
708         } else {
709             if (v3_gva_to_hva(info, dec_instr.dst_operand.operand, &dst_addr) == -1) {
710                 PrintError("Could not translate Read Destination (Virtual) to host VA\n");
711                 return -1;
712             }
713         }
714     } else if (dec_instr.dst_operand.type == REG_OPERAND) {
715         dst_addr = dec_instr.dst_operand.operand;
716     } else {
717         dst_addr = (addr_t)&(dec_instr.dst_operand.operand);
718     }
719
720     src_op_len = dec_instr.src_operand.size;
721     dst_op_len = dec_instr.dst_operand.size;
722
723     PrintDebug("Dst_Addr = %p, SRC Addr = %p\n", 
724                (void *)dst_addr, (void *)src_addr);
725
726     if (read_fn(info, read_gpa, (void *)src_addr, src_op_len, priv_data) != src_op_len) {
727         PrintError("Did not fully read hooked data\n");
728         return -1;
729     }
730
731     if (run_op(info, dec_instr.op_type, src_addr, dst_addr, src_op_len, dst_op_len) == -1) {
732         PrintError("Instruction Emulation Failed\n");
733         return -1;
734     }
735
736     info->rip += dec_instr.instr_length;
737
738     return src_op_len;
739 }
740
741
742
743
744
745
746 static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_addr, addr_t dst_addr, int src_op_size, int dst_op_size) {
747
748     if (src_op_size == 1) {
749         PrintDebug("Executing 8 bit instruction\n");
750
751         switch (op_type) {
752             case V3_OP_ADC:
753                 adc8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
754                 break;
755             case V3_OP_ADD:
756                 add8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
757                 break;
758             case V3_OP_AND:
759                 and8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
760                 break;
761             case V3_OP_OR:
762                 or8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
763                 break;
764             case V3_OP_XOR:
765                 xor8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
766                 break;
767             case V3_OP_SUB:
768                 sub8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
769                 break;
770
771             case V3_OP_MOV:
772                 mov8((addr_t *)dst_addr, (addr_t *)src_addr);
773                 break;
774
775             case V3_OP_MOVZX:
776                 movzx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
777                 break;
778             case V3_OP_MOVSX:
779                 movsx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
780                 break;
781
782             case V3_OP_NOT:
783                 not8((addr_t *)dst_addr);
784                 break;
785             case V3_OP_XCHG:
786                 xchg8((addr_t *)dst_addr, (addr_t *)src_addr);
787                 break;
788       
789
790             case V3_OP_INC:
791                 inc8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
792                 break;
793             case V3_OP_DEC:
794                 dec8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
795                 break;
796             case V3_OP_NEG:
797                 neg8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
798                 break;
799             case V3_OP_SETB:
800                 setb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
801                 break;
802             case V3_OP_SETBE:
803                 setbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
804                 break;
805             case V3_OP_SETL:
806                 setl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
807                 break;
808             case V3_OP_SETLE:
809                 setle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
810                 break;
811             case V3_OP_SETNB:
812                 setnb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
813                 break;
814             case V3_OP_SETNBE:
815                 setnbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
816                 break;
817             case V3_OP_SETNL:
818                 setnl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
819                 break;
820             case V3_OP_SETNLE:
821                 setnle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
822                 break;
823             case V3_OP_SETNO:
824                 setno8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
825                 break;
826             case V3_OP_SETNP:
827                 setnp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
828                 break;
829             case V3_OP_SETNS:
830                 setns8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
831                 break;
832             case V3_OP_SETNZ:
833                 setnz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
834                 break;
835             case V3_OP_SETO:
836                 seto8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
837                 break;
838             case V3_OP_SETP:
839                 setp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
840                 break;
841             case V3_OP_SETS:
842                 sets8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
843                 break;
844             case V3_OP_SETZ:
845                 setz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
846                 break;
847
848             default:
849                 PrintError("Unknown 8 bit instruction\n");
850                 return -1;
851         }
852
853     } else if (src_op_size == 2) {
854         PrintDebug("Executing 16 bit instruction\n");
855
856         switch (op_type) {
857             case V3_OP_ADC:
858                 adc16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
859                 break;
860             case V3_OP_ADD:
861                 add16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
862                 break;
863             case V3_OP_AND:
864                 and16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
865                 break;
866             case V3_OP_OR:
867                 or16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
868                 break;
869             case V3_OP_XOR:
870                 xor16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
871                 break;
872             case V3_OP_SUB:
873                 sub16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
874                 break;
875
876
877             case V3_OP_INC:
878                 inc16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
879                 break;
880             case V3_OP_DEC:
881                 dec16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
882                 break;
883             case V3_OP_NEG:
884                 neg16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
885                 break;
886
887             case V3_OP_MOV:
888                 mov16((addr_t *)dst_addr, (addr_t *)src_addr);
889                 break;
890             case V3_OP_MOVZX:
891                 movzx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
892                 break;
893             case V3_OP_MOVSX:
894                 movsx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
895                 break;
896             case V3_OP_NOT:
897                 not16((addr_t *)dst_addr);
898                 break;
899             case V3_OP_XCHG:
900                 xchg16((addr_t *)dst_addr, (addr_t *)src_addr);
901                 break;
902       
903             default:
904                 PrintError("Unknown 16 bit instruction\n");
905                 return -1;
906         }
907
908     } else if (src_op_size == 4) {
909         PrintDebug("Executing 32 bit instruction\n");
910
911         switch (op_type) {
912             case V3_OP_ADC:
913                 adc32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
914                 break;
915             case V3_OP_ADD:
916                 add32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
917                 break;
918             case V3_OP_AND:
919                 and32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
920                 break;
921             case V3_OP_OR:
922                 or32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
923                 break;
924             case V3_OP_XOR:
925                 xor32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
926                 break;
927             case V3_OP_SUB:
928                 sub32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
929                 break;
930
931             case V3_OP_INC:
932                 inc32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
933                 break;
934             case V3_OP_DEC:
935                 dec32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
936                 break;
937             case V3_OP_NEG:
938                 neg32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
939                 break;
940
941             case V3_OP_MOV:
942                 mov32((addr_t *)dst_addr, (addr_t *)src_addr);
943                 break;
944
945             case V3_OP_NOT:
946                 not32((addr_t *)dst_addr);
947                 break;
948             case V3_OP_XCHG:
949                 xchg32((addr_t *)dst_addr, (addr_t *)src_addr);
950                 break;
951       
952             default:
953                 PrintError("Unknown 32 bit instruction\n");
954                 return -1;
955         }
956
957 #ifdef __V3_64BIT__
958     } else if (src_op_size == 8) {
959         PrintDebug("Executing 64 bit instruction\n");
960
961         switch (op_type) {
962             case V3_OP_ADC:
963                 adc64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
964                 break;
965             case V3_OP_ADD:
966                 add64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
967                 break;
968             case V3_OP_AND:
969                 and64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
970                 break;
971             case V3_OP_OR:
972                 or64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
973                 break;
974             case V3_OP_XOR:
975                 xor64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
976                 break;
977             case V3_OP_SUB:
978                 sub64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
979                 break;
980
981             case V3_OP_INC:
982                 inc64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
983                 break;
984             case V3_OP_DEC:
985                 dec64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
986                 break;
987             case V3_OP_NEG:
988                 neg64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
989                 break;
990
991             case V3_OP_MOV:
992                 mov64((addr_t *)dst_addr, (addr_t *)src_addr);
993                 break;
994
995             case V3_OP_NOT:
996                 not64((addr_t *)dst_addr);
997                 break;
998             case V3_OP_XCHG:
999                 xchg64((addr_t *)dst_addr, (addr_t *)src_addr);
1000                 break;
1001       
1002             default:
1003                 PrintError("Unknown 64 bit instruction\n");
1004                 return -1;
1005         }
1006 #endif
1007
1008     } else {
1009         PrintError("Invalid Operation Size\n");
1010         return -1;
1011     }
1012
1013     return 0;
1014 }