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.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
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.
14 * Author: Jack Lange <jarusl@cs.northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
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>
27 #ifndef CONFIG_DEBUG_EMULATOR
29 #define PrintDebug(fmt, args...)
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);
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),
40 uint_t emulation_length = 0;
41 uint_t emulation_iter_cnt = 0;
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);
52 // Nested paging (Need check??)
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)));*/
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;
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)));
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;
71 if (dec_instr->op_type == V3_OP_MOVS) {
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");
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");
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));
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));
97 PrintError("Invalid operand length\n");
101 info->vm_regs.rdi += emulation_length;
102 info->vm_regs.rsi += emulation_length;
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;
109 } else if (dec_instr->op_type == V3_OP_STOS) {
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));
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));
122 PrintError("Invalid operand length\n");
126 info->vm_regs.rdi += emulation_length;
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;
134 PrintError("Unimplemented String operation\n");
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");
143 if (emulation_length == dec_instr->str_op_length) {
144 info->rip += dec_instr->instr_length;
147 return emulation_length;
153 This function is intended to handle pure read hooks, pure write hook, and full hooks,
154 with and without backing memory for writes
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
162 orig_dst_addr == NULL => data is written to write_gpa
163 orig_dst_addr != NULL => data is written to orig_dst_addr
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
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),
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;
182 addr_t src_addr, dst_addr;
185 // Sanity check the decoded instruction
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);
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);
199 // Nested paging (Need check??)
203 if (dec_instr->src_operand.size != dec_instr->dst_operand.size) {
204 PrintError("Source and Destination Operands are of different sizes\n");
209 // We will only read up to the next page boundary
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;
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)));
219 // We will only write up to the next page boundary
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;
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)));
229 // We will only copy the minimum of what is available to be read or written
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);
239 emulation_length=src_emulation_length;
246 src_addr = (addr_t) V3_Malloc(emulation_length); // hideous - should reuse memory
248 PrintError("Unable to allocate space for read operation in emulate_string_read_op\n");
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");
257 src_addr=orig_src_addr;
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");
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");
273 // Now src_addr points to the fetched data in HVA
275 // Allocate space for the write, in case we need to copy out later
278 dst_addr=orig_dst_addr;
280 dst_addr = (addr_t) V3_Malloc(emulation_length); // yuck
282 PrintError("Unable to allocate space for write operation in emulate_string_op\n");
284 V3_Free((void*)src_addr);
291 dst_addr=orig_dst_addr;
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");
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");
307 // Now dst_addr points to where we will copy the data
309 // How many items to copy
310 emulation_iter_cnt = emulation_length / dec_instr->dst_operand.size;
311 tmp_rcx = emulation_iter_cnt;
314 switch (dec_instr->op_type) {
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));
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));
329 PrintError("Invalid operand length\n");
333 // Can't these count down too? - PAD
335 info->vm_regs.rdi += emulation_length;
336 info->vm_regs.rsi += emulation_length;
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;
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));
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));
359 PrintError("Invalid operand length\n");
363 info->vm_regs.rdi += emulation_length;
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;
374 PrintError("Unimplemented String operation\n");
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
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");
390 if (emulation_length == dec_instr->str_op_length) {
391 info->rip += dec_instr->instr_length;
395 // Delete temporary buffers
397 V3_Free((void*)src_addr);
399 if (write_fn && !orig_dst_addr) {
400 V3_Free((void*)dst_addr);
404 return emulation_length;
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),
416 addr_t em_dst_addr = 0;
419 PrintDebug("Emulating XCHG write\n");
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);
431 } else if (dec_instr->src_operand.type == REG_OPERAND) {
432 src_addr = dec_instr->src_operand.operand;
434 src_addr = (addr_t)&(dec_instr->src_operand.operand);
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);
447 //check that the operand (GVA) maps to the the faulting GPA
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;
454 em_dst_addr = (addr_t)&(dec_instr->src_operand.operand);
457 dst_op_len = dec_instr->dst_operand.size;
458 src_op_len = dec_instr->src_operand.size;
460 PrintDebug("Dst_Addr = %p, SRC operand = %p\n",
461 (void *)dst_addr, (void *)src_addr);
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");
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");
474 info->rip += dec_instr->instr_length;
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),
486 addr_t em_src_addr = 0;
487 addr_t em_dst_addr = 0;
491 PrintDebug("Emulating XCHG Read\n");
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);
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;
504 em_src_addr = (addr_t)&(dec_instr->src_operand.operand);
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);
517 //check that the operand (GVA) maps to the the faulting GPA
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;
524 em_dst_addr = (addr_t)&(dec_instr->src_operand.operand);
527 dst_op_len = dec_instr->dst_operand.size;
528 src_op_len = dec_instr->src_operand.size;
530 PrintDebug("Dst_Addr = %p, SRC operand = %p\n",
531 (void *)em_dst_addr, (void *)em_src_addr);
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");
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");
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");
549 info->rip += dec_instr->instr_length;
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),
560 struct x86_instr dec_instr;
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);
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);
573 ret = v3_read_gva_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
580 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
581 PrintError("Decoding Error\n");
582 // Kick off single step emulator
587 * Instructions needing to be special cased.... *
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);
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);
604 //check that the operand (GVA) maps to the the faulting GPA
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");
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");
620 } else if (dec_instr.src_operand.type == REG_OPERAND) {
621 src_addr = dec_instr.src_operand.operand;
623 src_addr = (addr_t)&(dec_instr.src_operand.operand);
626 dst_op_len = dec_instr.dst_operand.size;
627 src_op_len = dec_instr.src_operand.size;
629 PrintDebug("Dst_Addr = %p, SRC operand = %p\n",
630 (void *)dst_addr, (void *)src_addr);
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");
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");
643 info->rip += dec_instr.instr_length;
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),
653 struct x86_instr dec_instr;
660 PrintDebug("Emulating Read for instruction at %p\n", (void *)(addr_t)(info->rip));
661 PrintDebug("GVA=%p\n", (void *)read_gva);
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);
666 ret = v3_read_gva_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
670 PrintError("Could not read instruction for Emulated Read at %p\n", (void *)(addr_t)(info->rip));
675 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
676 PrintError("Decoding Error\n");
677 // Kick off single step emulator
681 if (dec_instr.is_str_op) {
682 return emulate_string_op(info,&dec_instr,
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);
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);
699 //check that the operand (GVA) maps to the the faulting GPA
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");
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");
714 } else if (dec_instr.dst_operand.type == REG_OPERAND) {
715 dst_addr = dec_instr.dst_operand.operand;
717 dst_addr = (addr_t)&(dec_instr.dst_operand.operand);
720 src_op_len = dec_instr.src_operand.size;
721 dst_op_len = dec_instr.dst_operand.size;
723 PrintDebug("Dst_Addr = %p, SRC Addr = %p\n",
724 (void *)dst_addr, (void *)src_addr);
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");
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");
736 info->rip += dec_instr.instr_length;
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) {
748 if (src_op_size == 1) {
749 PrintDebug("Executing 8 bit instruction\n");
753 adc8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
756 add8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
759 and8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
762 or8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
765 xor8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
768 sub8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
772 mov8((addr_t *)dst_addr, (addr_t *)src_addr);
776 movzx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
779 movsx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
783 not8((addr_t *)dst_addr);
786 xchg8((addr_t *)dst_addr, (addr_t *)src_addr);
791 inc8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
794 dec8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
797 neg8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
800 setb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
803 setbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
806 setl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
809 setle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
812 setnb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
815 setnbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
818 setnl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
821 setnle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
824 setno8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
827 setnp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
830 setns8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
833 setnz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
836 seto8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
839 setp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
842 sets8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
845 setz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
849 PrintError("Unknown 8 bit instruction\n");
853 } else if (src_op_size == 2) {
854 PrintDebug("Executing 16 bit instruction\n");
858 adc16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
861 add16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
864 and16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
867 or16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
870 xor16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
873 sub16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
878 inc16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
881 dec16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
884 neg16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
888 mov16((addr_t *)dst_addr, (addr_t *)src_addr);
891 movzx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
894 movsx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
897 not16((addr_t *)dst_addr);
900 xchg16((addr_t *)dst_addr, (addr_t *)src_addr);
904 PrintError("Unknown 16 bit instruction\n");
908 } else if (src_op_size == 4) {
909 PrintDebug("Executing 32 bit instruction\n");
913 adc32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
916 add32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
919 and32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
922 or32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
925 xor32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
928 sub32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
932 inc32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
935 dec32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
938 neg32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
942 mov32((addr_t *)dst_addr, (addr_t *)src_addr);
946 not32((addr_t *)dst_addr);
949 xchg32((addr_t *)dst_addr, (addr_t *)src_addr);
953 PrintError("Unknown 32 bit instruction\n");
958 } else if (src_op_size == 8) {
959 PrintDebug("Executing 64 bit instruction\n");
963 adc64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
966 add64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
969 and64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
972 or64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
975 xor64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
978 sub64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
982 inc64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
985 dec64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
988 neg64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
992 mov64((addr_t *)dst_addr, (addr_t *)src_addr);
996 not64((addr_t *)dst_addr);
999 xchg64((addr_t *)dst_addr, (addr_t *)src_addr);
1003 PrintError("Unknown 64 bit instruction\n");
1009 PrintError("Invalid Operation Size\n");