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->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;
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 dst_op_len = dec_instr.dst_operand.size;
206 src_op_len = dec_instr.src_operand.size;
208 PrintDebug("Dst_Addr = %p, SRC operand = %p\n",
209 (void *)dst_addr, (void *)src_addr);
212 if (run_op(info, dec_instr.op_type, src_addr, dst_addr, src_op_len, dst_op_len) == -1) {
213 PrintError("Instruction Emulation Failed\n");
217 if (write_fn(write_gpa, (void *)dst_addr, dst_op_len, priv_data) != dst_op_len) {
218 PrintError("Did not fully write hooked data\n");
222 info->rip += dec_instr.instr_length;
228 int v3_emulate_read_op(struct guest_info * info, addr_t read_gva, addr_t read_gpa, addr_t src_addr,
229 int (*read_fn)(addr_t guest_addr, void * dst, uint_t length, void * priv_data),
231 struct x86_instr dec_instr;
238 PrintDebug("Emulating Read for instruction at %p\n", (void *)(addr_t)(info->rip));
239 PrintDebug("GVA=%p\n", (void *)read_gva);
241 if (info->mem_mode == PHYSICAL_MEM) {
242 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
244 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
251 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
252 PrintError("Decoding Error\n");
253 // Kick off single step emulator
257 if (dec_instr.is_str_op) {
258 PrintError("String operations not implemented on fully hooked regions\n");
263 if ((dec_instr.src_operand.type != MEM_OPERAND) ||
264 (dec_instr.src_operand.operand != read_gva)) {
265 PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
266 (void *)dec_instr.src_operand.operand, (void *)read_gva);
271 if (dec_instr.dst_operand.type == MEM_OPERAND) {
272 if (info->mem_mode == PHYSICAL_MEM) {
273 if (guest_pa_to_host_va(info, dec_instr.dst_operand.operand, &dst_addr) == -1) {
274 PrintError("Could not translate Read Destination (Physical) to host VA\n");
278 if (guest_va_to_host_va(info, dec_instr.dst_operand.operand, &dst_addr) == -1) {
279 PrintError("Could not translate Read Destination (Virtual) to host VA\n");
283 } else if (dec_instr.dst_operand.type == REG_OPERAND) {
284 dst_addr = dec_instr.dst_operand.operand;
286 dst_addr = (addr_t)&(dec_instr.dst_operand.operand);
289 src_op_len = dec_instr.src_operand.size;
290 dst_op_len = dec_instr.dst_operand.size;
292 PrintDebug("Dst_Addr = %p, SRC Addr = %p\n",
293 (void *)dst_addr, (void *)src_addr);
295 if (read_fn(read_gpa, (void *)src_addr, src_op_len, priv_data) != src_op_len) {
296 PrintError("Did not fully read hooked data\n");
300 if (run_op(info, dec_instr.op_type, src_addr, dst_addr, src_op_len, dst_op_len) == -1) {
301 PrintError("Instruction Emulation Failed\n");
305 info->rip += dec_instr.instr_length;
315 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) {
317 if (src_op_size == 1) {
321 adc8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
324 add8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
327 and8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
330 or8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
333 xor8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
336 sub8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
340 mov8((addr_t *)dst_addr, (addr_t *)src_addr);
344 movzx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
347 movsx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
351 not8((addr_t *)dst_addr);
354 xchg8((addr_t *)dst_addr, (addr_t *)src_addr);
359 inc8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
362 dec8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
365 neg8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
368 setb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
371 setbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
374 setl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
377 setle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
380 setnb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
383 setnbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
386 setnl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
389 setnle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
392 setno8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
395 setnp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
398 setns8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
401 setnz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
404 seto8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
407 setp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
410 sets8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
413 setz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
417 PrintError("Unknown 8 bit instruction\n");
421 } else if (src_op_size == 2) {
425 adc16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
428 add16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
431 and16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
434 or16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
437 xor16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
440 sub16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
445 inc16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
448 dec16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
451 neg16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
455 mov16((addr_t *)dst_addr, (addr_t *)src_addr);
458 movzx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
461 movsx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
464 not16((addr_t *)dst_addr);
467 xchg16((addr_t *)dst_addr, (addr_t *)src_addr);
471 PrintError("Unknown 16 bit instruction\n");
475 } else if (src_op_size == 4) {
479 adc32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
482 add32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
485 and32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
488 or32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
491 xor32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
494 sub32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
498 inc32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
501 dec32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
504 neg32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
508 mov32((addr_t *)dst_addr, (addr_t *)src_addr);
512 not32((addr_t *)dst_addr);
515 xchg32((addr_t *)dst_addr, (addr_t *)src_addr);
519 PrintError("Unknown 32 bit instruction\n");
524 } else if (src_op_size == 8) {
529 adc64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
532 add64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
535 and64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
538 or64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
541 xor64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
544 sub64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
548 inc64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
551 dec64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
554 neg64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
558 mov64((addr_t *)dst_addr, (addr_t *)src_addr);
562 not64((addr_t *)dst_addr);
565 xchg64((addr_t *)dst_addr, (addr_t *)src_addr);
569 PrintError("Unknown 64 bit instruction\n");
575 PrintError("Invalid Operation Size\n");