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 // 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 uint_t emulation_length = 0;
44 if (dec_instr->op_type == V3_OP_MOVS) {
45 PrintDebug("MOVS emulation\n");
47 if (dec_instr->dst_operand.operand != write_gva) {
48 PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
49 (void *)dec_instr->dst_operand.operand, (void *)write_gva);
53 emulation_length = ( (dec_instr->str_op_length < (0x1000 - PAGE_OFFSET_4KB(write_gva))) ?
54 dec_instr->str_op_length :
55 (0x1000 - PAGE_OFFSET_4KB(write_gva)));
56 /* ** Fix emulation length so that it doesn't overrun over the src page either ** */
59 PrintDebug("STR_OP_LEN: %d, Page Len: %d\n",
60 (uint_t)dec_instr->str_op_length,
61 (uint_t)(0x1000 - PAGE_OFFSET_4KB(write_gva)));
62 PrintDebug("Emulation length: %d\n", emulation_length);
63 tmp_rcx = emulation_length;
65 if (guest_pa_to_host_va(info, write_gpa, dst_addr) == -1) {
66 PrintError("Could not translate write destination to host VA\n");
70 // figure out addresses here....
71 if (info->mem_mode == PHYSICAL_MEM) {
72 if (guest_pa_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) {
73 PrintError("Could not translate write Source (Physical) to host VA\n");
77 if (guest_va_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) {
78 PrintError("Could not translate write Source (Virtual) to host VA\n");
84 PrintDebug("Dst Operand: %p (size=%d), Src Operand: %p\n",
85 (void *)dec_instr->dst_operand.operand,
86 dec_instr->dst_operand.size,
87 (void *)dec_instr->src_operand.operand);
88 PrintDebug("Dst Addr: %p, Src Addr: %p\n", (void *)(addr_t *)*dst_addr, (void *)src_addr);
96 if (dec_instr->dst_operand.size == 1) {
97 movs8(dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
98 } else if (dec_instr->dst_operand.size == 2) {
99 movs16(dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
100 } else if (dec_instr->dst_operand.size == 4) {
101 movs32(dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
103 PrintError("Invalid operand length\n");
111 PrintDebug("RDI=%p, RSI=%p, RCX=%p\n",
112 (void *)*(addr_t *)&(info->vm_regs.rdi),
113 (void *)*(addr_t *)&(info->vm_regs.rsi),
114 (void *)*(addr_t *)&(info->vm_regs.rcx));
116 info->vm_regs.rdi += emulation_length;
117 info->vm_regs.rsi += emulation_length;
118 info->vm_regs.rcx -= emulation_length;
120 PrintDebug("RDI=%p, RSI=%p, RCX=%p\n",
121 (void *)*(addr_t *)&(info->vm_regs.rdi),
122 (void *)*(addr_t *)&(info->vm_regs.rsi),
123 (void *)*(addr_t *)&(info->vm_regs.rcx));
125 if (emulation_length == dec_instr->str_op_length) {
126 info->rip += dec_instr->instr_length;
129 return emulation_length;
139 int v3_emulate_write_op(struct guest_info * info, addr_t write_gva, addr_t write_gpa, addr_t * dst_addr) {
140 struct x86_instr dec_instr;
146 PrintDebug("Emulating Write for instruction at %p\n", (void *)(addr_t)(info->rip));
147 PrintDebug("GPA=%p, GVA=%p\n", (void *)write_gpa, (void *)write_gva);
149 if (info->mem_mode == PHYSICAL_MEM) {
150 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
152 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
160 if (guest_pa_to_host_va(info, write_gpa, dst_addr) == -1) {
161 PrintError("Could not translate write destination to host VA\n");
165 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
166 PrintError("Decoding Error\n");
167 // Kick off single step emulator
171 if (dec_instr.is_str_op) {
172 return emulate_string_write_op(info, &dec_instr, write_gva, write_gpa, dst_addr);
176 if ((dec_instr.dst_operand.type != MEM_OPERAND) ||
177 (dec_instr.dst_operand.operand != write_gva)) {
178 PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
179 (void *)dec_instr.dst_operand.operand, (void *)write_gva);
184 if (dec_instr.src_operand.type == MEM_OPERAND) {
185 if (info->mem_mode == PHYSICAL_MEM) {
186 if (guest_pa_to_host_va(info, dec_instr.src_operand.operand, &src_addr) == -1) {
187 PrintError("Could not translate write Source (Physical) to host VA\n");
191 if (guest_va_to_host_va(info, dec_instr.src_operand.operand, &src_addr) == -1) {
192 PrintError("Could not translate write Source (Virtual) to host VA\n");
196 } else if (dec_instr.src_operand.type == REG_OPERAND) {
197 src_addr = dec_instr.src_operand.operand;
199 src_addr = (addr_t)&(dec_instr.src_operand.operand);
203 PrintDebug("Dst_Addr Ptr = %p (val=%p), SRC operand = %p\n",
204 (void *)dst_addr, (void *)*dst_addr, (void *)src_addr);
207 if (dec_instr.dst_operand.size == 1) {
209 switch (dec_instr.op_type) {
211 adc8((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
214 add8((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
217 and8((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
220 or8((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
223 xor8((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
226 sub8((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
230 mov8((addr_t *)*dst_addr, (addr_t *)src_addr);
233 not8((addr_t *)*dst_addr);
236 xchg8((addr_t *)*dst_addr, (addr_t *)src_addr);
241 inc8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
244 dec8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
247 neg8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
250 setb8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
253 setbe8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
256 setl8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
259 setle8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
262 setnb8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
265 setnbe8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
268 setnl8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
271 setnle8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
274 setno8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
277 setnp8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
280 setns8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
283 setnz8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
286 seto8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
289 setp8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
292 sets8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
295 setz8((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
299 PrintError("Unknown 8 bit instruction\n");
303 } else if (dec_instr.dst_operand.size == 2) {
305 switch (dec_instr.op_type) {
307 adc16((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
310 add16((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
313 and16((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
316 or16((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
319 xor16((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
322 sub16((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
327 inc16((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
330 dec16((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
333 neg16((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
337 mov16((addr_t *)*dst_addr, (addr_t *)src_addr);
340 not16((addr_t *)*dst_addr);
343 xchg16((addr_t *)*dst_addr, (addr_t *)src_addr);
347 PrintError("Unknown 16 bit instruction\n");
351 } else if (dec_instr.dst_operand.size == 4) {
353 switch (dec_instr.op_type) {
355 adc32((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
358 add32((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
361 and32((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
364 or32((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
367 xor32((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
370 sub32((addr_t *)*dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
374 inc32((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
377 dec32((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
380 neg32((addr_t *)*dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
384 mov32((addr_t *)*dst_addr, (addr_t *)src_addr);
387 not32((addr_t *)*dst_addr);
390 xchg32((addr_t *)*dst_addr, (addr_t *)src_addr);
394 PrintError("Unknown 32 bit instruction\n");
398 } else if (dec_instr.dst_operand.size == 8) {
399 PrintError("64 bit instructions not handled\n");
402 PrintError("Invalid Operation Size\n");
406 info->rip += dec_instr.instr_length;
408 return dec_instr.dst_operand.size;