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 * Authors: Jack Lange <jarusl@cs.northwestern.edu>
15 * Peter Dinda <pdinda@northwestern.edu> (full hook/string ops)
17 * This is free software. You are permitted to use,
18 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
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>
28 #ifndef CONFIG_DEBUG_EMULATOR
30 #define PrintDebug(fmt, args...)
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);
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),
41 uint_t emulation_length = 0;
42 uint_t emulation_iter_cnt = 0;
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);
53 // Nested paging (Need check??)
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)));*/
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;
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)));
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;
72 if (dec_instr->op_type == V3_OP_MOVS) {
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");
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");
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));
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));
98 PrintError("Invalid operand length\n");
102 info->vm_regs.rdi += emulation_length;
103 info->vm_regs.rsi += emulation_length;
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;
110 } else if (dec_instr->op_type == V3_OP_STOS) {
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));
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));
123 PrintError("Invalid operand length\n");
127 info->vm_regs.rdi += emulation_length;
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;
135 PrintError("Unimplemented String operation\n");
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");
144 if (emulation_length == dec_instr->str_op_length) {
145 info->rip += dec_instr->instr_length;
148 return emulation_length;
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
157 A MAXIMUM OF ONE PAGE IS TRANSFERED BUT REGISTERS ARE UPDATED SO THAT
158 THE INSTRUCTION CAN BE RESTARTED
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
166 orig_dst_addr == NULL => data is written to write_gpa
167 orig_dst_addr != NULL => data is written to orig_dst_addr
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
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)
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;
187 addr_t src_hva, dst_hva;
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));
194 // v3_print_instr(dec_instr);
196 // Sanity check the decoded instruction
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);
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);
212 // Nested paging (Need check??)
216 if (dec_instr->src_operand.size != dec_instr->dst_operand.size) {
217 PrintError("Source and Destination Operands are of different sizes\n");
222 // We will only read up to the next page boundary
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;
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)));
232 // We will only write up to the next page boundary
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;
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)));
242 // We will only copy the minimum of what is available to be read or written
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);
254 emulation_length=src_emulation_length;
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
266 PrintError("Unable to allocate space for read operation in emulate_string_read_op\n");
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");
274 // This is ordinary memory
276 // The caller told us where to read from
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");
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");
294 // Now src_hva points to the fetched data or to the in-VM data
296 // Allocate space for the write, in case we need to copy out later
298 // This is a full hook or a write hook
300 // This is a write hook with backing memory
301 // The caller already told us where that memory is
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
308 PrintError("Unable to allocate space for write operation in emulate_string_op\n");
310 V3_Free((void*)src_hva);
316 // This is ordinary memory
318 // The caller told us where to write
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");
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");
336 // Now dst_addr points to where we will copy the data
338 // How many items to copy
339 emulation_iter_cnt = emulation_length / dec_instr->dst_operand.size;
340 tmp_rcx = emulation_iter_cnt;
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) {
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));
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));
363 PrintError("Invalid operand length\n");
367 // Can't these count down too? - PAD
369 info->vm_regs.rdi += emulation_length;
370 info->vm_regs.rsi += emulation_length;
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;
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));
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));
393 PrintError("Invalid operand length\n");
397 info->vm_regs.rdi += emulation_length;
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;
408 PrintError("Unimplemented String operation\n");
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
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");
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;
432 // Delete temporary buffers
434 V3_Free((void*)src_hva);
436 if (write_fn && !write_hva) {
437 V3_Free((void*)dst_hva);
441 return emulation_length;
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),
453 addr_t em_dst_addr = 0;
456 PrintDebug("Emulating XCHG write\n");
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);
468 } else if (dec_instr->src_operand.type == REG_OPERAND) {
469 src_addr = dec_instr->src_operand.operand;
471 src_addr = (addr_t)&(dec_instr->src_operand.operand);
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);
484 //check that the operand (GVA) maps to the the faulting GPA
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;
491 em_dst_addr = (addr_t)&(dec_instr->src_operand.operand);
494 dst_op_len = dec_instr->dst_operand.size;
495 src_op_len = dec_instr->src_operand.size;
497 PrintDebug("Dst_Addr = %p, SRC operand = %p\n",
498 (void *)dst_addr, (void *)src_addr);
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");
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");
511 info->rip += dec_instr->instr_length;
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),
523 addr_t em_src_addr = 0;
524 addr_t em_dst_addr = 0;
528 PrintDebug("Emulating XCHG Read\n");
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);
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;
541 em_src_addr = (addr_t)&(dec_instr->src_operand.operand);
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);
554 //check that the operand (GVA) maps to the the faulting GPA
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;
561 em_dst_addr = (addr_t)&(dec_instr->src_operand.operand);
564 dst_op_len = dec_instr->dst_operand.size;
565 src_op_len = dec_instr->src_operand.size;
567 PrintDebug("Dst_Addr = %p, SRC operand = %p\n",
568 (void *)em_dst_addr, (void *)em_src_addr);
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");
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");
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");
586 info->rip += dec_instr->instr_length;
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),
597 struct x86_instr dec_instr;
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);
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);
610 ret = v3_read_gva_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
617 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
618 PrintError("Decoding Error\n");
619 // Kick off single step emulator
624 * Instructions needing to be special cased.... *
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);
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);
641 //check that the operand (GVA) maps to the the faulting GPA
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");
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");
657 } else if (dec_instr.src_operand.type == REG_OPERAND) {
658 src_addr = dec_instr.src_operand.operand;
660 src_addr = (addr_t)&(dec_instr.src_operand.operand);
663 dst_op_len = dec_instr.dst_operand.size;
664 src_op_len = dec_instr.src_operand.size;
666 PrintDebug("Dst_Addr = %p, SRC operand = %p\n",
667 (void *)dst_addr, (void *)src_addr);
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");
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");
680 info->rip += dec_instr.instr_length;
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),
690 struct x86_instr dec_instr;
697 PrintDebug("Emulating Read for instruction at %p\n", (void *)(addr_t)(info->rip));
698 PrintDebug("GVA=%p\n", (void *)read_gva);
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);
703 ret = v3_read_gva_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
707 PrintError("Could not read instruction for Emulated Read at %p\n", (void *)(addr_t)(info->rip));
712 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
713 PrintError("Decoding Error\n");
714 // Kick off single step emulator
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
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.
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;
737 if (dec_instr.dst_operand.type != MEM_OPERAND) {
740 write_hva=0; // should calc target here and continue
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);
747 if (info->mem_mode == PHYSICAL_MEM) {
748 write_gpa = dec_instr.dst_operand.operand;
749 write_gva = write_gpa;
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;
764 v3_inject_guest_pf(info,write_gva,c);
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);
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);
786 write_hva=0; // no actual writeback - hook function only
789 // Now that we have the write_gpa, we need to find out whether it's a hooked region
790 // or just plain memory
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);
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);
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
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);
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);
827 //check that the operand (GVA) maps to the the faulting GPA
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");
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");
842 } else if (dec_instr.dst_operand.type == REG_OPERAND) {
843 dst_addr = dec_instr.dst_operand.operand;
845 dst_addr = (addr_t)&(dec_instr.dst_operand.operand);
848 src_op_len = dec_instr.src_operand.size;
849 dst_op_len = dec_instr.dst_operand.size;
851 PrintDebug("Dst_Addr = %p, SRC Addr = %p\n",
852 (void *)dst_addr, (void *)src_addr);
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");
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");
864 info->rip += dec_instr.instr_length;
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) {
876 if (src_op_size == 1) {
877 PrintDebug("Executing 8 bit instruction\n");
881 adc8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
884 add8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
887 and8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
890 or8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
893 xor8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
896 sub8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
900 mov8((addr_t *)dst_addr, (addr_t *)src_addr);
904 movzx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
907 movsx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
911 not8((addr_t *)dst_addr);
914 xchg8((addr_t *)dst_addr, (addr_t *)src_addr);
919 inc8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
922 dec8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
925 neg8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
928 setb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
931 setbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
934 setl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
937 setle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
940 setnb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
943 setnbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
946 setnl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
949 setnle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
952 setno8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
955 setnp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
958 setns8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
961 setnz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
964 seto8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
967 setp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
970 sets8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
973 setz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
977 PrintError("Unknown 8 bit instruction\n");
981 } else if (src_op_size == 2) {
982 PrintDebug("Executing 16 bit instruction\n");
986 adc16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
989 add16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
992 and16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
995 or16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
998 xor16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
1001 sub16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
1006 inc16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
1009 dec16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
1012 neg16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
1016 mov16((addr_t *)dst_addr, (addr_t *)src_addr);
1019 movzx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
1022 movsx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
1025 not16((addr_t *)dst_addr);
1028 xchg16((addr_t *)dst_addr, (addr_t *)src_addr);
1032 PrintError("Unknown 16 bit instruction\n");
1036 } else if (src_op_size == 4) {
1037 PrintDebug("Executing 32 bit instruction\n");
1041 adc32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
1044 add32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
1047 and32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
1050 or32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
1053 xor32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
1056 sub32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
1060 inc32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
1063 dec32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
1066 neg32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
1070 mov32((addr_t *)dst_addr, (addr_t *)src_addr);
1074 not32((addr_t *)dst_addr);
1077 xchg32((addr_t *)dst_addr, (addr_t *)src_addr);
1081 PrintError("Unknown 32 bit instruction\n");
1086 } else if (src_op_size == 8) {
1087 PrintDebug("Executing 64 bit instruction\n");
1091 adc64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
1094 add64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
1097 and64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
1100 or64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
1103 xor64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
1106 sub64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
1110 inc64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
1113 dec64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
1116 neg64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
1120 mov64((addr_t *)dst_addr, (addr_t *)src_addr);
1124 not64((addr_t *)dst_addr);
1127 xchg64((addr_t *)dst_addr, (addr_t *)src_addr);
1131 PrintError("Unknown 64 bit instruction\n");
1137 PrintError("Invalid Operation Size\n");