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.


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