+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
#include <palacios/vmm.h>
#include <palacios/vmm_emulator.h>
#include <palacios/vm_guest_mem.h>
#include <palacios/vmm_decoder.h>
+#include <palacios/vmm_debug.h>
+#include <palacios/vmcb.h>
+#include <palacios/vmm_ctrl_regs.h>
static const char VMMCALL[3] = {0x0f, 0x01, 0xd9};
+#ifndef DEBUG_EMULATOR
+#undef PrintDebug
+#define PrintDebug(fmt, args...)
+#endif
+
+
int init_emulator(struct guest_info * info) {
struct emulation_state * emulator = &(info->emulator);
emulator->running = 0;
emulator->instr_length = 0;
+ emulator->tf_enabled = 0;
+
return 0;
}
return (addr_t)page;
}
-
+/*
static int setup_code_page(struct guest_info * info, char * instr, struct basic_instr_info * instr_info ) {
addr_t code_page_offset = PT32_PAGE_OFFSET(info->rip);
addr_t code_page = get_new_page();
memcpy((void *)(code_page + code_page_offset), instr, instr_info->instr_length);
memcpy((void *)(code_page + code_page_offset + instr_info->instr_length), VMMCALL, 3);
+#ifdef DEBUG_EMULATOR
PrintDebug("New Instr Stream:\n");
PrintTraceMemDump((void *)(code_page + code_page_offset), 32);
PrintDebug("rip =%x\n", info->rip);
-
+#endif
return 0;
}
+*/
+
+
+static int set_stepping(struct guest_info * info) {
+ vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
+ ctrl_area->exceptions.db = 1;
+
+ info->emulator.tf_enabled = ((struct rflags *)&(info->ctrl_regs.rflags))->tf;
+
+ ((struct rflags *)&(info->ctrl_regs.rflags))->tf = 1;
+
+ return 0;
+}
+
+
+static int unset_stepping(struct guest_info * info) {
+ vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
+ ctrl_area->exceptions.db = 0;
+
+ ((struct rflags *)&(info->ctrl_regs.rflags))->tf = info->emulator.tf_enabled;
+
+ if (info->emulator.tf_enabled) {
+ // Inject breakpoint exception into guest
+ }
+
+ return 0;
+
+}
// get the current instr
ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
}
+#ifdef DEBUG_EMULATOR
PrintDebug("Instr (15 bytes) at %x:\n", instr);
PrintTraceMemDump(instr, 15);
-
+#endif
+
+
if (v3_basic_mem_decode(info, (addr_t)instr, &instr_info) == -1) {
PrintError("Could not do a basic memory instruction decode\n");
V3_Free(data_page);
return -1;
}
+ /*
if (instr_info.has_rep == 1) {
PrintError("We currently don't handle rep* instructions\n");
V3_Free(data_page);
return -1;
}
-
+ */
data_page->page_addr = get_new_page();
data_page->va = PT32_PAGE_ADDR(read_gva);
}
- setup_code_page(info, instr, &instr_info);
+ // setup_code_page(info, instr, &instr_info);
+ set_stepping(info);
info->emulator.running = 1;
info->run_state = VM_EMULATING;
struct emulated_page * data_page = V3_Malloc(sizeof(struct emulated_page));
addr_t data_addr_offset = PT32_PAGE_OFFSET(write_gva);
pte32_t saved_pte;
+ int i;
- PrintDebug("Emulating Write\n");
+ PrintDebug("Emulating Write for instruction at 0x%x\n",info->rip);
if (info->mem_mode == PHYSICAL_MEM) {
ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
} else {
ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
}
+
+
+ PrintDebug("Instruction is");
+ for (i=0;i<15;i++) { PrintDebug(" 0x%x",instr[i]); }
+ PrintDebug("\n");
if (v3_basic_mem_decode(info, (addr_t)instr, &instr_info) == -1) {
PrintError("Could not do a basic memory instruction decode\n");
return -1;
}
+ if (instr_info.has_rep==1) {
+ PrintDebug("Emulated instruction has rep\n");
+ }
+
+ /*
if (instr_info.has_rep == 1) {
PrintError("We currently don't handle rep* instructions\n");
V3_Free(write_op);
V3_Free(data_page);
return -1;
}
-
+ */
data_page->page_addr = get_new_page();
data_page->va = PT32_PAGE_ADDR(write_gva);
if (info->emulator.running == 0) {
- setup_code_page(info, instr, &instr_info);
+ // setup_code_page(info, instr, &instr_info);
+ set_stepping(info);
info->emulator.running = 1;
info->run_state = VM_EMULATING;
info->emulator.instr_length = instr_info.instr_length;
info->emulator.running = 0;
//info->rip += info->emulator.instr_length;
+
+ PrintDebug("Returning to rip: 0x%x\n", info->rip);
+
info->emulator.instr_length = 0;
+
+
+ unset_stepping(info);
+
PrintDebug("returning from emulation\n");