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...)
37 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);
39 // We emulate up to the next 4KB page boundry
40 static int emulate_string_write_op(struct guest_info * info, struct x86_instr * dec_instr,
41 addr_t write_gva, addr_t write_gpa, addr_t dst_addr,
42 int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
44 uint_t emulation_length = 0;
48 if (dec_instr->op_type == V3_OP_MOVS) {
49 PrintError("MOVS emulation\n");
51 if (dec_instr->dst_operand.operand != write_gva) {
52 PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
53 (void *)dec_instr->dst_operand.operand, (void *)write_gva);
57 emulation_length = ( (dec_instr->str_op_length < (0x1000 - PAGE_OFFSET_4KB(write_gva))) ?
58 dec_instr->str_op_length :
59 (0x1000 - PAGE_OFFSET_4KB(write_gva)));
60 /* ** Fix emulation length so that it doesn't overrun over the src page either ** */
63 PrintDebug("STR_OP_LEN: %d, Page Len: %d\n",
64 (uint_t)dec_instr->str_op_length,
65 (uint_t)(0x1000 - PAGE_OFFSET_4KB(write_gva)));
66 PrintDebug("Emulation length: %d\n", emulation_length);
67 tmp_rcx = emulation_length;
71 // figure out addresses here....
72 if (info->mem_mode == PHYSICAL_MEM) {
73 if (guest_pa_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) {
74 PrintError("Could not translate write Source (Physical) to host VA\n");
78 if (guest_va_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) {
79 PrintError("Could not translate write Source (Virtual) to host VA\n");
85 PrintDebug("Dst Operand: %p (size=%d), Src Operand: %p\n",
86 (void *)dec_instr->dst_operand.operand,
87 dec_instr->dst_operand.size,
88 (void *)dec_instr->src_operand.operand);
89 PrintDebug("Dst Addr: %p, Src Addr: %p\n", (void *)dst_addr, (void *)src_addr);
97 if (dec_instr->dst_operand.size == 1) {
98 movs8((addr_t *)dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
99 } else if (dec_instr->dst_operand.size == 2) {
100 movs16((addr_t *)dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
101 } else if (dec_instr->dst_operand.size == 4) {
102 movs32((addr_t*)dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
104 PrintError("Invalid operand length\n");
109 if (write_fn(write_gpa, (void *)dst_addr, emulation_length, priv_data) != emulation_length) {
110 PrintError("Did not fully read hooked data\n");
115 PrintDebug("RDI=%p, RSI=%p, RCX=%p\n",
116 (void *)*(addr_t *)&(info->vm_regs.rdi),
117 (void *)*(addr_t *)&(info->vm_regs.rsi),
118 (void *)*(addr_t *)&(info->vm_regs.rcx));
120 info->vm_regs.rdi += emulation_length;
121 info->vm_regs.rsi += emulation_length;
122 info->vm_regs.rcx -= emulation_length;
124 PrintDebug("RDI=%p, RSI=%p, RCX=%p\n",
125 (void *)*(addr_t *)&(info->vm_regs.rdi),
126 (void *)*(addr_t *)&(info->vm_regs.rsi),
127 (void *)*(addr_t *)&(info->vm_regs.rcx));
129 if (emulation_length == dec_instr->str_op_length) {
130 info->rip += dec_instr->instr_length;
133 return emulation_length;
146 int v3_emulate_write_op(struct guest_info * info, addr_t write_gva, addr_t write_gpa, addr_t dst_addr,
147 int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
149 struct x86_instr dec_instr;
155 PrintDebug("Emulating Write for instruction at %p\n", (void *)(addr_t)(info->rip));
156 PrintDebug("GVA=%p\n", (void *)write_gva);
158 if (info->mem_mode == PHYSICAL_MEM) {
159 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
161 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
168 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
169 PrintError("Decoding Error\n");
170 // Kick off single step emulator
174 if (dec_instr.is_str_op) {
175 return emulate_string_write_op(info, &dec_instr, write_gva, write_gpa, dst_addr, write_fn, priv_data);
179 if ((dec_instr.dst_operand.type != MEM_OPERAND) ||
180 (dec_instr.dst_operand.operand != write_gva)) {
181 PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
182 (void *)dec_instr.dst_operand.operand, (void *)write_gva);
187 if (dec_instr.src_operand.type == MEM_OPERAND) {
188 if (info->mem_mode == PHYSICAL_MEM) {
189 if (guest_pa_to_host_va(info, dec_instr.src_operand.operand, &src_addr) == -1) {
190 PrintError("Could not translate write Source (Physical) to host VA\n");
194 if (guest_va_to_host_va(info, dec_instr.src_operand.operand, &src_addr) == -1) {
195 PrintError("Could not translate write Source (Virtual) to host VA\n");
199 } else if (dec_instr.src_operand.type == REG_OPERAND) {
200 src_addr = dec_instr.src_operand.operand;
202 src_addr = (addr_t)&(dec_instr.src_operand.operand);
205 op_len = dec_instr.dst_operand.size;
207 PrintDebug("Dst_Addr = %p, SRC operand = %p\n",
208 (void *)dst_addr, (void *)src_addr);
211 if (run_op(info, dec_instr.op_type, src_addr, dst_addr, op_len) == -1) {
212 PrintError("Instruction Emulation Failed\n");
216 if (write_fn(write_gpa, (void *)dst_addr, op_len, priv_data) != op_len) {
217 PrintError("Did not fully read hooked data\n");
221 info->rip += dec_instr.instr_length;
227 int v3_emulate_read_op(struct guest_info * info, addr_t read_gva, addr_t read_gpa, addr_t src_addr,
228 int (*read_fn)(addr_t guest_addr, void * dst, uint_t length, void * priv_data),
230 struct x86_instr dec_instr;
236 PrintDebug("Emulating Read for instruction at %p\n", (void *)(addr_t)(info->rip));
237 PrintDebug("GVA=%p\n", (void *)write_gva);
239 if (info->mem_mode == PHYSICAL_MEM) {
240 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
242 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
249 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
250 PrintError("Decoding Error\n");
251 // Kick off single step emulator
255 if (dec_instr.is_str_op) {
256 PrintError("String operations not implemented on fully hooked regions\n");
261 if ((dec_instr.src_operand.type != MEM_OPERAND) ||
262 (dec_instr.src_operand.operand != read_gva)) {
263 PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
264 (void *)dec_instr.src_operand.operand, (void *)read_gva);
269 if (dec_instr.dst_operand.type == MEM_OPERAND) {
270 if (info->mem_mode == PHYSICAL_MEM) {
271 if (guest_pa_to_host_va(info, dec_instr.dst_operand.operand, &dst_addr) == -1) {
272 PrintError("Could not translate Read Destination (Physical) to host VA\n");
276 if (guest_va_to_host_va(info, dec_instr.dst_operand.operand, &dst_addr) == -1) {
277 PrintError("Could not translate Read Destination (Virtual) to host VA\n");
281 } else if (dec_instr.dst_operand.type == REG_OPERAND) {
282 dst_addr = dec_instr.dst_operand.operand;
284 dst_addr = (addr_t)&(dec_instr.dst_operand.operand);
287 op_len = dec_instr.src_operand.size;
289 PrintDebug("Dst_Addr = %p, SRC Addr = %p\n",
290 (void *)dst_addr, (void *)src_addr);
292 if (read_fn(read_gpa, (void *)src_addr,op_len, priv_data) != op_len) {
293 PrintError("Did not fully read hooked data\n");
297 if (run_op(info, dec_instr.op_type, src_addr, dst_addr, op_len) == -1) {
298 PrintError("Instruction Emulation Failed\n");
302 info->rip += dec_instr.instr_length;
312 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) {
318 adc8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
321 add8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
324 and8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
327 or8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
330 xor8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
333 sub8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
337 mov8((addr_t *)dst_addr, (addr_t *)src_addr);
340 not8((addr_t *)dst_addr);
343 xchg8((addr_t *)dst_addr, (addr_t *)src_addr);
348 inc8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
351 dec8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
354 neg8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
357 setb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
360 setbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
363 setl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
366 setle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
369 setnb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
372 setnbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
375 setnl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
378 setnle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
381 setno8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
384 setnp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
387 setns8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
390 setnz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
393 seto8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
396 setp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
399 sets8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
402 setz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
406 PrintError("Unknown 8 bit instruction\n");
410 } else if (op_size == 2) {
414 adc16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
417 add16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
420 and16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
423 or16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
426 xor16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
429 sub16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
434 inc16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
437 dec16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
440 neg16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
444 mov16((addr_t *)dst_addr, (addr_t *)src_addr);
447 not16((addr_t *)dst_addr);
450 xchg16((addr_t *)dst_addr, (addr_t *)src_addr);
454 PrintError("Unknown 16 bit instruction\n");
458 } else if (op_size == 4) {
462 adc32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
465 add32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
468 and32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
471 or32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
474 xor32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
477 sub32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
481 inc32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
484 dec32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
487 neg32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
491 mov32((addr_t *)dst_addr, (addr_t *)src_addr);
494 not32((addr_t *)dst_addr);
497 xchg32((addr_t *)dst_addr, (addr_t *)src_addr);
501 PrintError("Unknown 32 bit instruction\n");
505 } else if (op_size == 8) {
506 PrintError("64 bit instructions not handled\n");
509 PrintError("Invalid Operation Size\n");