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...)
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)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
40 uint_t emulation_length = 0;
44 if (dec_instr->dst_operand.operand != write_gva) {
45 PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
46 (void *)dec_instr->dst_operand.operand, (void *)write_gva);
50 emulation_length = ( (dec_instr->str_op_length < (0x1000 - PAGE_OFFSET_4KB(write_gva))) ?
51 dec_instr->str_op_length :
52 (0x1000 - PAGE_OFFSET_4KB(write_gva)));
54 /* ** Fix emulation length so that it doesn't overrun over the src page either ** */
55 tmp_rcx = emulation_length;
60 if (dec_instr->op_type == V3_OP_MOVS) {
62 // figure out addresses here....
63 if (info->mem_mode == PHYSICAL_MEM) {
64 if (guest_pa_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) {
65 PrintError("Could not translate write Source (Physical) to host VA\n");
69 if (guest_va_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) {
70 PrintError("Could not translate write Source (Virtual) to host VA\n");
75 if (dec_instr->dst_operand.size == 1) {
76 movs8((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
77 } else if (dec_instr->dst_operand.size == 2) {
78 movs16((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
79 } else if (dec_instr->dst_operand.size == 4) {
80 movs32((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
82 } else if (dec_instr->dst_operand.size == 8) {
83 movs64((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
86 PrintError("Invalid operand length\n");
90 info->vm_regs.rdi += emulation_length;
91 info->vm_regs.rsi += emulation_length;
93 // RCX is only modified if the rep prefix is present
94 if (dec_instr->prefixes.rep == 1) {
95 info->vm_regs.rcx -= emulation_length;
98 } else if (dec_instr->op_type == V3_OP_STOS) {
100 if (dec_instr->dst_operand.size == 1) {
101 stos8((addr_t *)&dst_addr, (addr_t *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
102 } else if (dec_instr->dst_operand.size == 2) {
103 stos16((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 == 4) {
105 stos32((addr_t *)&dst_addr, (addr_t *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
107 } else if (dec_instr->dst_operand.size == 8) {
108 stos64((addr_t *)&dst_addr, (addr_t *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
111 PrintError("Invalid operand length\n");
115 info->vm_regs.rdi += emulation_length;
117 // RCX is only modified if the rep prefix is present
118 if (dec_instr->prefixes.rep == 1) {
119 info->vm_regs.rcx -= emulation_length;
123 PrintError("Unimplemented String operation\n");
127 if (write_fn(write_gpa, (void *)dst_addr, emulation_length, priv_data) != emulation_length) {
128 PrintError("Did not fully read hooked data\n");
132 if (emulation_length == dec_instr->str_op_length) {
133 info->rip += dec_instr->instr_length;
136 return emulation_length;
140 static int emulate_xchg_write_op(struct guest_info * info, struct x86_instr * dec_instr,
141 addr_t write_gva, addr_t write_gpa, addr_t dst_addr,
142 int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
145 addr_t em_dst_addr = 0;
148 PrintDebug("Emulating XCHG write\n");
150 if (dec_instr->src_operand.type == MEM_OPERAND) {
151 if (info->shdw_pg_mode == SHADOW_PAGING) {
152 if (dec_instr->src_operand.operand != write_gva) {
153 PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
154 (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 (info->shdw_pg_mode == SHADOW_PAGING) {
170 if (dec_instr->dst_operand.operand != write_gva) {
171 PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
172 (void *)dec_instr->dst_operand.operand, (void *)write_gva);
176 //check that the operand (GVA) maps to the the faulting GPA
179 em_dst_addr = dst_addr;
180 } else if (dec_instr->src_operand.type == REG_OPERAND) {
181 em_dst_addr = dec_instr->src_operand.operand;
183 em_dst_addr = (addr_t)&(dec_instr->src_operand.operand);
186 dst_op_len = dec_instr->dst_operand.size;
187 src_op_len = dec_instr->src_operand.size;
189 PrintDebug("Dst_Addr = %p, SRC operand = %p\n",
190 (void *)dst_addr, (void *)src_addr);
193 if (run_op(info, dec_instr->op_type, src_addr, em_dst_addr, src_op_len, dst_op_len) == -1) {
194 PrintError("Instruction Emulation Failed\n");
198 if (write_fn(write_gpa, (void *)dst_addr, dst_op_len, priv_data) != dst_op_len) {
199 PrintError("Did not fully write hooked data\n");
203 info->rip += dec_instr->instr_length;
210 static int emulate_xchg_read_op(struct guest_info * info, struct x86_instr * dec_instr,
211 addr_t read_gva, addr_t read_gpa, addr_t src_addr,
212 int (*read_fn)(addr_t guest_addr, void * dst, uint_t length, void * priv_data),
213 int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
215 addr_t em_src_addr = 0;
216 addr_t em_dst_addr = 0;
220 PrintDebug("Emulating XCHG Read\n");
222 if (dec_instr->src_operand.type == MEM_OPERAND) {
223 if (dec_instr->src_operand.operand != read_gva) {
224 PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
225 (void *)dec_instr->src_operand.operand, (void *)read_gva);
229 em_src_addr = src_addr;
230 } else if (dec_instr->src_operand.type == REG_OPERAND) {
231 em_src_addr = dec_instr->src_operand.operand;
233 em_src_addr = (addr_t)&(dec_instr->src_operand.operand);
238 if (dec_instr->dst_operand.type == MEM_OPERAND) {
239 if (info->shdw_pg_mode == SHADOW_PAGING) {
240 if (dec_instr->dst_operand.operand != read_gva) {
241 PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
242 (void *)dec_instr->dst_operand.operand, (void *)read_gva);
246 //check that the operand (GVA) maps to the the faulting GPA
249 em_dst_addr = src_addr;
250 } else if (dec_instr->src_operand.type == REG_OPERAND) {
251 em_dst_addr = dec_instr->src_operand.operand;
253 em_dst_addr = (addr_t)&(dec_instr->src_operand.operand);
256 dst_op_len = dec_instr->dst_operand.size;
257 src_op_len = dec_instr->src_operand.size;
259 PrintDebug("Dst_Addr = %p, SRC operand = %p\n",
260 (void *)em_dst_addr, (void *)em_src_addr);
263 if (read_fn(read_gpa, (void *)src_addr, src_op_len, priv_data) != src_op_len) {
264 PrintError("Did not fully read hooked data\n");
268 if (run_op(info, dec_instr->op_type, em_src_addr, em_dst_addr, src_op_len, dst_op_len) == -1) {
269 PrintError("Instruction Emulation Failed\n");
273 if (write_fn(read_gpa, (void *)src_addr, dst_op_len, priv_data) != dst_op_len) {
274 PrintError("Did not fully write hooked data\n");
278 info->rip += dec_instr->instr_length;
286 int v3_emulate_write_op(struct guest_info * info, addr_t write_gva, addr_t write_gpa, addr_t dst_addr,
287 int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
289 struct x86_instr dec_instr;
296 PrintDebug("Emulating Write for instruction at %p\n", (void *)(addr_t)(info->rip));
297 PrintDebug("GVA=%p\n", (void *)write_gva);
299 if (info->mem_mode == PHYSICAL_MEM) {
300 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
302 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
309 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
310 PrintError("Decoding Error\n");
311 // Kick off single step emulator
316 * Instructions needing to be special cased.... *
318 if (dec_instr.is_str_op) {
319 return emulate_string_write_op(info, &dec_instr, write_gva, write_gpa, dst_addr, write_fn, priv_data);
320 } else if (dec_instr.op_type == V3_OP_XCHG) {
321 return emulate_xchg_write_op(info, &dec_instr, write_gva, write_gpa, dst_addr, write_fn, priv_data);
325 if (info->shdw_pg_mode == SHADOW_PAGING) {
326 if ((dec_instr.dst_operand.type != MEM_OPERAND) ||
327 (dec_instr.dst_operand.operand != write_gva)) {
328 PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
329 (void *)dec_instr.dst_operand.operand, (void *)write_gva);
333 //check that the operand (GVA) maps to the the faulting GPA
337 if (dec_instr.src_operand.type == MEM_OPERAND) {
338 if (info->mem_mode == PHYSICAL_MEM) {
339 if (guest_pa_to_host_va(info, dec_instr.src_operand.operand, &src_addr) == -1) {
340 PrintError("Could not translate write Source (Physical) to host VA\n");
344 if (guest_va_to_host_va(info, dec_instr.src_operand.operand, &src_addr) == -1) {
345 PrintError("Could not translate write Source (Virtual) to host VA\n");
349 } else if (dec_instr.src_operand.type == REG_OPERAND) {
350 src_addr = dec_instr.src_operand.operand;
352 src_addr = (addr_t)&(dec_instr.src_operand.operand);
355 dst_op_len = dec_instr.dst_operand.size;
356 src_op_len = dec_instr.src_operand.size;
358 PrintDebug("Dst_Addr = %p, SRC operand = %p\n",
359 (void *)dst_addr, (void *)src_addr);
362 if (run_op(info, dec_instr.op_type, src_addr, dst_addr, src_op_len, dst_op_len) == -1) {
363 PrintError("Instruction Emulation Failed\n");
367 if (write_fn(write_gpa, (void *)dst_addr, dst_op_len, priv_data) != dst_op_len) {
368 PrintError("Did not fully write hooked data\n");
372 info->rip += dec_instr.instr_length;
378 int v3_emulate_read_op(struct guest_info * info, addr_t read_gva, addr_t read_gpa, addr_t src_addr,
379 int (*read_fn)(addr_t guest_addr, void * dst, uint_t length, void * priv_data),
380 int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
382 struct x86_instr dec_instr;
389 PrintDebug("Emulating Read for instruction at %p\n", (void *)(addr_t)(info->rip));
390 PrintDebug("GVA=%p\n", (void *)read_gva);
392 if (info->mem_mode == PHYSICAL_MEM) {
393 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
395 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
402 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
403 PrintError("Decoding Error\n");
404 // Kick off single step emulator
408 if (dec_instr.is_str_op) {
409 PrintError("String operations not implemented on fully hooked regions\n");
411 } else if (dec_instr.op_type == V3_OP_XCHG) {
412 return emulate_xchg_read_op(info, &dec_instr, read_gva, read_gpa, src_addr, read_fn, write_fn, priv_data);
415 if (info->shdw_pg_mode == SHADOW_PAGING) {
416 if ((dec_instr.src_operand.type != MEM_OPERAND) ||
417 (dec_instr.src_operand.operand != read_gva)) {
418 PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
419 (void *)dec_instr.src_operand.operand, (void *)read_gva);
423 //check that the operand (GVA) maps to the the faulting GPA
426 if (dec_instr.dst_operand.type == MEM_OPERAND) {
427 if (info->mem_mode == PHYSICAL_MEM) {
428 if (guest_pa_to_host_va(info, dec_instr.dst_operand.operand, &dst_addr) == -1) {
429 PrintError("Could not translate Read Destination (Physical) to host VA\n");
433 if (guest_va_to_host_va(info, dec_instr.dst_operand.operand, &dst_addr) == -1) {
434 PrintError("Could not translate Read Destination (Virtual) to host VA\n");
438 } else if (dec_instr.dst_operand.type == REG_OPERAND) {
439 dst_addr = dec_instr.dst_operand.operand;
441 dst_addr = (addr_t)&(dec_instr.dst_operand.operand);
444 src_op_len = dec_instr.src_operand.size;
445 dst_op_len = dec_instr.dst_operand.size;
447 PrintDebug("Dst_Addr = %p, SRC Addr = %p\n",
448 (void *)dst_addr, (void *)src_addr);
450 if (read_fn(read_gpa, (void *)src_addr, src_op_len, priv_data) != src_op_len) {
451 PrintError("Did not fully read hooked data\n");
455 if (run_op(info, dec_instr.op_type, src_addr, dst_addr, src_op_len, dst_op_len) == -1) {
456 PrintError("Instruction Emulation Failed\n");
460 info->rip += dec_instr.instr_length;
470 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) {
472 if (src_op_size == 1) {
473 PrintDebug("Executing 8 bit instruction\n");
477 adc8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
480 add8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
483 and8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
486 or8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
489 xor8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
492 sub8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
496 mov8((addr_t *)dst_addr, (addr_t *)src_addr);
500 movzx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
503 movsx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
507 not8((addr_t *)dst_addr);
510 xchg8((addr_t *)dst_addr, (addr_t *)src_addr);
515 inc8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
518 dec8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
521 neg8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
524 setb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
527 setbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
530 setl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
533 setle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
536 setnb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
539 setnbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
542 setnl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
545 setnle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
548 setno8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
551 setnp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
554 setns8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
557 setnz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
560 seto8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
563 setp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
566 sets8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
569 setz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
573 PrintError("Unknown 8 bit instruction\n");
577 } else if (src_op_size == 2) {
578 PrintDebug("Executing 16 bit instruction\n");
582 adc16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
585 add16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
588 and16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
591 or16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
594 xor16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
597 sub16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
602 inc16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
605 dec16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
608 neg16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
612 mov16((addr_t *)dst_addr, (addr_t *)src_addr);
615 movzx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
618 movsx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
621 not16((addr_t *)dst_addr);
624 xchg16((addr_t *)dst_addr, (addr_t *)src_addr);
628 PrintError("Unknown 16 bit instruction\n");
632 } else if (src_op_size == 4) {
633 PrintDebug("Executing 32 bit instruction\n");
637 adc32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
640 add32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
643 and32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
646 or32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
649 xor32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
652 sub32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
656 inc32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
659 dec32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
662 neg32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
666 mov32((addr_t *)dst_addr, (addr_t *)src_addr);
670 not32((addr_t *)dst_addr);
673 xchg32((addr_t *)dst_addr, (addr_t *)src_addr);
677 PrintError("Unknown 32 bit instruction\n");
682 } else if (src_op_size == 8) {
683 PrintDebug("Executing 64 bit instruction\n");
687 adc64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
690 add64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
693 and64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
696 or64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
699 xor64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
702 sub64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
706 inc64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
709 dec64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
712 neg64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
716 mov64((addr_t *)dst_addr, (addr_t *)src_addr);
720 not64((addr_t *)dst_addr);
723 xchg64((addr_t *)dst_addr, (addr_t *)src_addr);
727 PrintError("Unknown 64 bit instruction\n");
733 PrintError("Invalid Operation Size\n");