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 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->op_type == V3_OP_MOVS) {
47 // PrintError("MOVS emulation\n");
49 if (dec_instr->dst_operand.operand != write_gva) {
50 PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
51 (void *)dec_instr->dst_operand.operand, (void *)write_gva);
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)));
58 /* ** Fix emulation length so that it doesn't overrun over the src page either ** */
61 PrintDebug("STR_OP_LEN: %d, Page Len: %d\n",
62 (uint_t)dec_instr->str_op_length,
63 (uint_t)(0x1000 - PAGE_OFFSET_4KB(write_gva)));
64 PrintDebug("Emulation length: %d\n", emulation_length);
65 tmp_rcx = emulation_length;
69 // figure out addresses here....
70 if (info->mem_mode == PHYSICAL_MEM) {
71 if (guest_pa_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) {
72 PrintError("Could not translate write Source (Physical) to host VA\n");
76 if (guest_va_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) {
77 PrintError("Could not translate write Source (Virtual) to host VA\n");
83 PrintDebug("Dst Operand: %p (size=%d), Src Operand: %p\n",
84 (void *)dec_instr->dst_operand.operand,
85 dec_instr->dst_operand.size,
86 (void *)dec_instr->src_operand.operand);
87 PrintDebug("Dst Addr: %p, Src Addr: %p\n", (void *)dst_addr, (void *)src_addr);
95 if (dec_instr->dst_operand.size == 1) {
96 movs8((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
97 } else if (dec_instr->dst_operand.size == 2) {
98 movs16((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
99 } else if (dec_instr->dst_operand.size == 4) {
100 movs32((addr_t*)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
102 PrintError("Invalid operand length\n");
106 PrintDebug("Calling Write function\n");
108 if (write_fn(write_gpa, (void *)dst_addr, emulation_length, priv_data) != emulation_length) {
109 PrintError("Did not fully read hooked data\n");
114 PrintDebug("RDI=%p, RSI=%p, RCX=%p\n",
115 (void *)*(addr_t *)&(info->vm_regs.rdi),
116 (void *)*(addr_t *)&(info->vm_regs.rsi),
117 (void *)*(addr_t *)&(info->vm_regs.rcx));
119 info->vm_regs.rdi += emulation_length;
120 info->vm_regs.rsi += emulation_length;
121 info->vm_regs.rcx -= emulation_length;
123 PrintDebug("RDI=%p, RSI=%p, RCX=%p\n",
124 (void *)*(addr_t *)&(info->vm_regs.rdi),
125 (void *)*(addr_t *)&(info->vm_regs.rsi),
126 (void *)*(addr_t *)&(info->vm_regs.rcx));
128 if (emulation_length == dec_instr->str_op_length) {
129 info->rip += dec_instr->instr_length;
132 return emulation_length;
145 int v3_emulate_write_op(struct guest_info * info, addr_t write_gva, addr_t write_gpa, addr_t dst_addr,
146 int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
148 struct x86_instr dec_instr;
154 PrintDebug("Emulating Write for instruction at %p\n", (void *)(addr_t)(info->rip));
155 PrintDebug("GVA=%p\n", (void *)write_gva);
157 if (info->mem_mode == PHYSICAL_MEM) {
158 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
160 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
167 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
168 PrintError("Decoding Error\n");
169 // Kick off single step emulator
173 if (dec_instr.is_str_op) {
174 return emulate_string_write_op(info, &dec_instr, write_gva, write_gpa, dst_addr, write_fn, priv_data);
178 if ((dec_instr.dst_operand.type != MEM_OPERAND) ||
179 (dec_instr.dst_operand.operand != write_gva)) {
180 PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
181 (void *)dec_instr.dst_operand.operand, (void *)write_gva);
186 if (dec_instr.src_operand.type == MEM_OPERAND) {
187 if (info->mem_mode == PHYSICAL_MEM) {
188 if (guest_pa_to_host_va(info, dec_instr.src_operand.operand, &src_addr) == -1) {
189 PrintError("Could not translate write Source (Physical) to host VA\n");
193 if (guest_va_to_host_va(info, dec_instr.src_operand.operand, &src_addr) == -1) {
194 PrintError("Could not translate write Source (Virtual) to host VA\n");
198 } else if (dec_instr.src_operand.type == REG_OPERAND) {
199 src_addr = dec_instr.src_operand.operand;
201 src_addr = (addr_t)&(dec_instr.src_operand.operand);
204 op_len = dec_instr.dst_operand.size;
206 PrintDebug("Dst_Addr = %p, SRC operand = %p\n",
207 (void *)dst_addr, (void *)src_addr);
210 if (run_op(info, dec_instr.op_type, src_addr, dst_addr, op_len) == -1) {
211 PrintError("Instruction Emulation Failed\n");
215 if (write_fn(write_gpa, (void *)dst_addr, op_len, priv_data) != op_len) {
216 PrintError("Did not fully write hooked data\n");
220 info->rip += dec_instr.instr_length;
226 int v3_emulate_read_op(struct guest_info * info, addr_t read_gva, addr_t read_gpa, addr_t src_addr,
227 int (*read_fn)(addr_t guest_addr, void * dst, uint_t length, void * priv_data),
229 struct x86_instr dec_instr;
235 PrintDebug("Emulating Read for instruction at %p\n", (void *)(addr_t)(info->rip));
236 PrintDebug("GVA=%p\n", (void *)read_gva);
238 if (info->mem_mode == PHYSICAL_MEM) {
239 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
241 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
248 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
249 PrintError("Decoding Error\n");
250 // Kick off single step emulator
254 if (dec_instr.is_str_op) {
255 PrintError("String operations not implemented on fully hooked regions\n");
260 if ((dec_instr.src_operand.type != MEM_OPERAND) ||
261 (dec_instr.src_operand.operand != read_gva)) {
262 PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
263 (void *)dec_instr.src_operand.operand, (void *)read_gva);
268 if (dec_instr.dst_operand.type == MEM_OPERAND) {
269 if (info->mem_mode == PHYSICAL_MEM) {
270 if (guest_pa_to_host_va(info, dec_instr.dst_operand.operand, &dst_addr) == -1) {
271 PrintError("Could not translate Read Destination (Physical) to host VA\n");
275 if (guest_va_to_host_va(info, dec_instr.dst_operand.operand, &dst_addr) == -1) {
276 PrintError("Could not translate Read Destination (Virtual) to host VA\n");
280 } else if (dec_instr.dst_operand.type == REG_OPERAND) {
281 dst_addr = dec_instr.dst_operand.operand;
283 dst_addr = (addr_t)&(dec_instr.dst_operand.operand);
286 op_len = dec_instr.src_operand.size;
288 PrintDebug("Dst_Addr = %p, SRC Addr = %p\n",
289 (void *)dst_addr, (void *)src_addr);
291 if (read_fn(read_gpa, (void *)src_addr,op_len, priv_data) != op_len) {
292 PrintError("Did not fully read hooked data\n");
296 if (run_op(info, dec_instr.op_type, src_addr, dst_addr, op_len) == -1) {
297 PrintError("Instruction Emulation Failed\n");
301 info->rip += dec_instr.instr_length;
311 static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_addr, addr_t dst_addr, int op_size) {
317 adc8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
320 add8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
323 and8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
326 or8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
329 xor8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
332 sub8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
336 mov8((addr_t *)dst_addr, (addr_t *)src_addr);
339 not8((addr_t *)dst_addr);
342 xchg8((addr_t *)dst_addr, (addr_t *)src_addr);
347 inc8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
350 dec8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
353 neg8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
356 setb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
359 setbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
362 setl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
365 setle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
368 setnb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
371 setnbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
374 setnl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
377 setnle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
380 setno8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
383 setnp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
386 setns8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
389 setnz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
392 seto8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
395 setp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
398 sets8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
401 setz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
405 PrintError("Unknown 8 bit instruction\n");
409 } else if (op_size == 2) {
413 adc16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
416 add16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
419 and16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
422 or16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
425 xor16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
428 sub16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
433 inc16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
436 dec16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
439 neg16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
443 mov16((addr_t *)dst_addr, (addr_t *)src_addr);
446 not16((addr_t *)dst_addr);
449 xchg16((addr_t *)dst_addr, (addr_t *)src_addr);
453 PrintError("Unknown 16 bit instruction\n");
457 } else if (op_size == 4) {
461 adc32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
464 add32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
467 and32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
470 or32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
473 xor32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
476 sub32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
480 inc32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
483 dec32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
486 neg32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
490 mov32((addr_t *)dst_addr, (addr_t *)src_addr);
493 not32((addr_t *)dst_addr);
496 xchg32((addr_t *)dst_addr, (addr_t *)src_addr);
500 PrintError("Unknown 32 bit instruction\n");
505 } else if (op_size == 8) {
510 adc64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
513 add64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
516 and64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
519 or64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
522 xor64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
525 sub64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
529 inc64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
532 dec64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
535 neg64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
539 mov64((addr_t *)dst_addr, (addr_t *)src_addr);
542 not64((addr_t *)dst_addr);
545 xchg64((addr_t *)dst_addr, (addr_t *)src_addr);
549 PrintError("Unknown 64 bit instruction\n");
555 PrintError("Invalid Operation Size\n");