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_debug.h>
25 #include <palacios/vmcb.h>
26 #include <palacios/vmm_ctrl_regs.h>
29 #ifndef DEBUG_EMULATOR
31 #define PrintDebug(fmt, args...)
35 int v3_init_emulator(struct guest_info * info) {
38 emulator->tf_enabled = 0;
52 static int set_stepping(struct guest_info * info) {
53 vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
54 ctrl_area->exceptions.db = 1;
56 info->emulator.tf_enabled = ((struct rflags *)&(info->ctrl_regs.rflags))->tf;
58 ((struct rflags *)&(info->ctrl_regs.rflags))->tf = 1;
64 static int unset_stepping(struct guest_info * info) {
65 vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
66 ctrl_area->exceptions.db = 0;
68 ((struct rflags *)&(info->ctrl_regs.rflags))->tf = info->emulator.tf_enabled;
70 if (info->emulator.tf_enabled) {
71 // Inject breakpoint exception into guest
79 int v3_emulate_memory_read(struct guest_info * info, addr_t read_gva,
80 int (*read)(addr_t read_addr, void * dst, uint_t length, void * priv_data),
81 addr_t read_gpa, void * private_data) {
82 struct basic_instr_info instr_info;
85 addr_t data_addr_offset = PAGE_OFFSET(read_gva);
87 PrintDebug("Emulating Read\n");
89 if (info->mem_mode == PHYSICAL_MEM) {
90 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
92 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
96 PrintError("Could not read guest memory\n");
100 #ifdef DEBUG_EMULATOR
101 PrintDebug("Instr (15 bytes) at %p:\n", (void *)(addr_t)instr);
102 PrintTraceMemDump(instr, 15);
106 if (v3_basic_mem_decode(info, (addr_t)instr, &instr_info) == -1) {
107 PrintError("Could not do a basic memory instruction decode\n");
112 // Read the data directly onto the emulated page
113 ret = read(read_gpa, (void *)(data_page->page_addr + data_addr_offset), instr_info.op_size, private_data);
114 if ((ret == -1) || ((uint_t)ret != instr_info.op_size)) {
115 PrintError("Read error in emulator\n");
121 // setup_code_page(info, instr, &instr_info);
124 info->emulator.running = 1;
125 info->run_state = VM_EMULATING;
126 info->emulator.instr_length = instr_info.instr_length;
133 int v3_emulate_memory_write(struct guest_info * info, addr_t write_gva,
134 int (*write)(addr_t write_addr, void * src, uint_t length, void * priv_data),
135 addr_t write_gpa, void * private_data) {
137 struct basic_instr_info instr_info;
140 addr_t data_addr_offset = PAGE_OFFSET(write_gva);
143 PrintDebug("Emulating Write for instruction at 0x%p\n", (void *)(addr_t)(info->rip));
145 if (info->mem_mode == PHYSICAL_MEM) {
146 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
148 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
153 if (v3_basic_mem_decode(info, (addr_t)instr, &instr_info) == -1) {
154 PrintError("Could not do a basic memory instruction decode\n");
160 if (instr_info.has_rep==1) {
161 PrintDebug("Emulated instruction has rep\n");
165 if (info->emulator.running == 0) {
166 // setup_code_page(info, instr, &instr_info);
168 info->emulator.running = 1;
169 info->run_state = VM_EMULATING;
170 info->emulator.instr_length = instr_info.instr_length;
178 int v3_emulation_exit_handler(struct guest_info * info) {
180 unset_stepping(info);
183 PrintDebug("returning from emulation\n");