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 DEBUG_EMULATOR
29 #define PrintDebug(fmt, args...)
35 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);
37 // We emulate up to the next 4KB page boundry
38 static int emulate_string_write_op(struct guest_info * info, struct x86_instr * dec_instr,
39 addr_t write_gva, addr_t write_gpa, addr_t dst_addr,
40 int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
42 uint_t emulation_length = 0;
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 emulation_length = ( (dec_instr->str_op_length < (0x1000 - PAGE_OFFSET_4KB(write_gva))) ?
53 dec_instr->str_op_length :
54 (0x1000 - PAGE_OFFSET_4KB(write_gva)));
56 /* ** Fix emulation length so that it doesn't overrun over the src page either ** */
57 tmp_rcx = emulation_length;
62 if (dec_instr->op_type == V3_OP_MOVS) {
64 // figure out addresses here....
65 if (info->mem_mode == PHYSICAL_MEM) {
66 if (guest_pa_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) {
67 PrintError("Could not translate write Source (Physical) to host VA\n");
71 if (guest_va_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) {
72 PrintError("Could not translate write Source (Virtual) to host VA\n");
77 if (dec_instr->dst_operand.size == 1) {
78 movs8((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
79 } else if (dec_instr->dst_operand.size == 2) {
80 movs16((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
81 } else if (dec_instr->dst_operand.size == 4) {
82 movs32((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
84 } else if (dec_instr->dst_operand.size == 8) {
85 movs64((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
88 PrintError("Invalid operand length\n");
92 info->vm_regs.rdi += emulation_length;
93 info->vm_regs.rsi += emulation_length;
95 // RCX is only modified if the rep prefix is present
96 if (dec_instr->prefixes.rep == 1) {
97 info->vm_regs.rcx -= emulation_length;
100 } else if (dec_instr->op_type == V3_OP_STOS) {
102 if (dec_instr->dst_operand.size == 1) {
103 stos8((addr_t *)&dst_addr, (addr_t *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
104 } else if (dec_instr->dst_operand.size == 2) {
105 stos16((addr_t *)&dst_addr, (addr_t *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
106 } else if (dec_instr->dst_operand.size == 4) {
107 stos32((addr_t *)&dst_addr, (addr_t *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
109 } else if (dec_instr->dst_operand.size == 8) {
110 stos64((addr_t *)&dst_addr, (addr_t *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
113 PrintError("Invalid operand length\n");
117 info->vm_regs.rdi += emulation_length;
119 // RCX is only modified if the rep prefix is present
120 if (dec_instr->prefixes.rep == 1) {
121 info->vm_regs.rcx -= emulation_length;
125 PrintError("Unimplemented String operation\n");
129 if (write_fn(write_gpa, (void *)dst_addr, emulation_length, priv_data) != emulation_length) {
130 PrintError("Did not fully read hooked data\n");
134 if (emulation_length == dec_instr->str_op_length) {
135 info->rip += dec_instr->instr_length;
138 return emulation_length;
142 static int emulate_xchg_write_op(struct guest_info * info, struct x86_instr * dec_instr,
143 addr_t write_gva, addr_t write_gpa, addr_t dst_addr,
144 int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
147 addr_t em_dst_addr = 0;
150 PrintDebug("Emulating XCHG write\n");
152 if (dec_instr->src_operand.type == MEM_OPERAND) {
153 if (dec_instr->src_operand.operand != write_gva) {
154 PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
155 (void *)dec_instr->src_operand.operand, (void *)write_gva);
160 } else if (dec_instr->src_operand.type == REG_OPERAND) {
161 src_addr = dec_instr->src_operand.operand;
163 src_addr = (addr_t)&(dec_instr->src_operand.operand);
168 if (dec_instr->dst_operand.type == MEM_OPERAND) {
169 if (dec_instr->dst_operand.operand != write_gva) {
170 PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
171 (void *)dec_instr->dst_operand.operand, (void *)write_gva);
175 em_dst_addr = dst_addr;
176 } else if (dec_instr->src_operand.type == REG_OPERAND) {
177 em_dst_addr = dec_instr->src_operand.operand;
179 em_dst_addr = (addr_t)&(dec_instr->src_operand.operand);
182 dst_op_len = dec_instr->dst_operand.size;
183 src_op_len = dec_instr->src_operand.size;
185 PrintDebug("Dst_Addr = %p, SRC operand = %p\n",
186 (void *)dst_addr, (void *)src_addr);
189 if (run_op(info, dec_instr->op_type, src_addr, em_dst_addr, src_op_len, dst_op_len) == -1) {
190 PrintError("Instruction Emulation Failed\n");
194 if (write_fn(write_gpa, (void *)dst_addr, dst_op_len, priv_data) != dst_op_len) {
195 PrintError("Did not fully write hooked data\n");
199 info->rip += dec_instr->instr_length;
206 static int emulate_xchg_read_op(struct guest_info * info, struct x86_instr * dec_instr,
207 addr_t read_gva, addr_t read_gpa, addr_t src_addr,
208 int (*read_fn)(addr_t guest_addr, void * dst, uint_t length, void * priv_data),
209 int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
211 addr_t em_src_addr = 0;
212 addr_t em_dst_addr = 0;
216 PrintDebug("Emulating XCHG Read\n");
218 if (dec_instr->src_operand.type == MEM_OPERAND) {
219 if (dec_instr->src_operand.operand != read_gva) {
220 PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
221 (void *)dec_instr->src_operand.operand, (void *)read_gva);
225 em_src_addr = src_addr;
226 } else if (dec_instr->src_operand.type == REG_OPERAND) {
227 em_src_addr = dec_instr->src_operand.operand;
229 em_src_addr = (addr_t)&(dec_instr->src_operand.operand);
234 if (dec_instr->dst_operand.type == MEM_OPERAND) {
235 if (dec_instr->dst_operand.operand != read_gva) {
236 PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
237 (void *)dec_instr->dst_operand.operand, (void *)read_gva);
241 em_dst_addr = src_addr;
242 } else if (dec_instr->src_operand.type == REG_OPERAND) {
243 em_dst_addr = dec_instr->src_operand.operand;
245 em_dst_addr = (addr_t)&(dec_instr->src_operand.operand);
248 dst_op_len = dec_instr->dst_operand.size;
249 src_op_len = dec_instr->src_operand.size;
251 PrintDebug("Dst_Addr = %p, SRC operand = %p\n",
252 (void *)em_dst_addr, (void *)em_src_addr);
255 if (read_fn(read_gpa, (void *)src_addr, src_op_len, priv_data) != src_op_len) {
256 PrintError("Did not fully read hooked data\n");
260 if (run_op(info, dec_instr->op_type, em_src_addr, em_dst_addr, src_op_len, dst_op_len) == -1) {
261 PrintError("Instruction Emulation Failed\n");
265 if (write_fn(read_gpa, (void *)src_addr, dst_op_len, priv_data) != dst_op_len) {
266 PrintError("Did not fully write hooked data\n");
270 info->rip += dec_instr->instr_length;
278 int v3_emulate_write_op(struct guest_info * info, addr_t write_gva, addr_t write_gpa, addr_t dst_addr,
279 int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
281 struct x86_instr dec_instr;
288 PrintDebug("Emulating Write for instruction at %p\n", (void *)(addr_t)(info->rip));
289 PrintDebug("GVA=%p\n", (void *)write_gva);
291 if (info->mem_mode == PHYSICAL_MEM) {
292 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
294 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
301 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
302 PrintError("Decoding Error\n");
303 // Kick off single step emulator
308 * Instructions needing to be special cased.... *
310 if (dec_instr.is_str_op) {
311 return emulate_string_write_op(info, &dec_instr, write_gva, write_gpa, dst_addr, write_fn, priv_data);
312 } else if (dec_instr.op_type == V3_OP_XCHG) {
313 return emulate_xchg_write_op(info, &dec_instr, write_gva, write_gpa, dst_addr, write_fn, priv_data);
318 if ((dec_instr.dst_operand.type != MEM_OPERAND) ||
319 (dec_instr.dst_operand.operand != write_gva)) {
320 PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
321 (void *)dec_instr.dst_operand.operand, (void *)write_gva);
326 if (dec_instr.src_operand.type == MEM_OPERAND) {
327 if (info->mem_mode == PHYSICAL_MEM) {
328 if (guest_pa_to_host_va(info, dec_instr.src_operand.operand, &src_addr) == -1) {
329 PrintError("Could not translate write Source (Physical) to host VA\n");
333 if (guest_va_to_host_va(info, dec_instr.src_operand.operand, &src_addr) == -1) {
334 PrintError("Could not translate write Source (Virtual) to host VA\n");
338 } else if (dec_instr.src_operand.type == REG_OPERAND) {
339 src_addr = dec_instr.src_operand.operand;
341 src_addr = (addr_t)&(dec_instr.src_operand.operand);
344 dst_op_len = dec_instr.dst_operand.size;
345 src_op_len = dec_instr.src_operand.size;
347 PrintDebug("Dst_Addr = %p, SRC operand = %p\n",
348 (void *)dst_addr, (void *)src_addr);
351 if (run_op(info, dec_instr.op_type, src_addr, dst_addr, src_op_len, dst_op_len) == -1) {
352 PrintError("Instruction Emulation Failed\n");
356 if (write_fn(write_gpa, (void *)dst_addr, dst_op_len, priv_data) != dst_op_len) {
357 PrintError("Did not fully write hooked data\n");
361 info->rip += dec_instr.instr_length;
367 int v3_emulate_read_op(struct guest_info * info, addr_t read_gva, addr_t read_gpa, addr_t src_addr,
368 int (*read_fn)(addr_t guest_addr, void * dst, uint_t length, void * priv_data),
369 int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
371 struct x86_instr dec_instr;
378 PrintDebug("Emulating Read for instruction at %p\n", (void *)(addr_t)(info->rip));
379 PrintDebug("GVA=%p\n", (void *)read_gva);
381 if (info->mem_mode == PHYSICAL_MEM) {
382 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
384 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
391 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
392 PrintError("Decoding Error\n");
393 // Kick off single step emulator
397 if (dec_instr.is_str_op) {
398 PrintError("String operations not implemented on fully hooked regions\n");
400 } else if (dec_instr.op_type == V3_OP_XCHG) {
401 return emulate_xchg_read_op(info, &dec_instr, read_gva, read_gpa, src_addr, read_fn, write_fn, priv_data);
405 if ((dec_instr.src_operand.type != MEM_OPERAND) ||
406 (dec_instr.src_operand.operand != read_gva)) {
407 PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
408 (void *)dec_instr.src_operand.operand, (void *)read_gva);
413 if (dec_instr.dst_operand.type == MEM_OPERAND) {
414 if (info->mem_mode == PHYSICAL_MEM) {
415 if (guest_pa_to_host_va(info, dec_instr.dst_operand.operand, &dst_addr) == -1) {
416 PrintError("Could not translate Read Destination (Physical) to host VA\n");
420 if (guest_va_to_host_va(info, dec_instr.dst_operand.operand, &dst_addr) == -1) {
421 PrintError("Could not translate Read Destination (Virtual) to host VA\n");
425 } else if (dec_instr.dst_operand.type == REG_OPERAND) {
426 dst_addr = dec_instr.dst_operand.operand;
428 dst_addr = (addr_t)&(dec_instr.dst_operand.operand);
431 src_op_len = dec_instr.src_operand.size;
432 dst_op_len = dec_instr.dst_operand.size;
434 PrintDebug("Dst_Addr = %p, SRC Addr = %p\n",
435 (void *)dst_addr, (void *)src_addr);
437 if (read_fn(read_gpa, (void *)src_addr, src_op_len, priv_data) != src_op_len) {
438 PrintError("Did not fully read hooked data\n");
442 if (run_op(info, dec_instr.op_type, src_addr, dst_addr, src_op_len, dst_op_len) == -1) {
443 PrintError("Instruction Emulation Failed\n");
447 info->rip += dec_instr.instr_length;
457 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) {
459 if (src_op_size == 1) {
460 PrintDebug("Executing 8 bit instruction\n");
464 adc8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
467 add8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
470 and8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
473 or8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
476 xor8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
479 sub8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
483 mov8((addr_t *)dst_addr, (addr_t *)src_addr);
487 movzx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
490 movsx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
494 not8((addr_t *)dst_addr);
497 xchg8((addr_t *)dst_addr, (addr_t *)src_addr);
502 inc8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
505 dec8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
508 neg8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
511 setb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
514 setbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
517 setl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
520 setle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
523 setnb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
526 setnbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
529 setnl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
532 setnle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
535 setno8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
538 setnp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
541 setns8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
544 setnz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
547 seto8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
550 setp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
553 sets8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
556 setz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
560 PrintError("Unknown 8 bit instruction\n");
564 } else if (src_op_size == 2) {
565 PrintDebug("Executing 16 bit instruction\n");
569 adc16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
572 add16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
575 and16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
578 or16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
581 xor16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
584 sub16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
589 inc16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
592 dec16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
595 neg16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
599 mov16((addr_t *)dst_addr, (addr_t *)src_addr);
602 movzx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
605 movsx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
608 not16((addr_t *)dst_addr);
611 xchg16((addr_t *)dst_addr, (addr_t *)src_addr);
615 PrintError("Unknown 16 bit instruction\n");
619 } else if (src_op_size == 4) {
620 PrintDebug("Executing 32 bit instruction\n");
624 adc32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
627 add32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
630 and32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
633 or32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
636 xor32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
639 sub32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
643 inc32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
646 dec32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
649 neg32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
653 mov32((addr_t *)dst_addr, (addr_t *)src_addr);
657 not32((addr_t *)dst_addr);
660 xchg32((addr_t *)dst_addr, (addr_t *)src_addr);
664 PrintError("Unknown 32 bit instruction\n");
669 } else if (src_op_size == 8) {
670 PrintDebug("Executing 64 bit instruction\n");
674 adc64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
677 add64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
680 and64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
683 or64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
686 xor64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
689 sub64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
693 inc64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
696 dec64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
699 neg64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
703 mov64((addr_t *)dst_addr, (addr_t *)src_addr);
707 not64((addr_t *)dst_addr);
710 xchg64((addr_t *)dst_addr, (addr_t *)src_addr);
714 PrintError("Unknown 64 bit instruction\n");
720 PrintError("Invalid Operation Size\n");