X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_emulator.c;h=b5394900390673b1efb424f69749832dedb5d36f;hb=31f3a09733e4399173dafbed02b7dad6f18bbbb2;hp=fcce7c30505d0a302652997f1fcc5d2eb6801143;hpb=bf0d677f3d92f5949c3a73dad30aaf330201da44;p=palacios-OLD.git diff --git a/palacios/src/palacios/vmm_emulator.c b/palacios/src/palacios/vmm_emulator.c index fcce7c3..b539490 100644 --- a/palacios/src/palacios/vmm_emulator.c +++ b/palacios/src/palacios/vmm_emulator.c @@ -1,11 +1,39 @@ +/* + * 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 + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Jack Lange + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + #include #include #include #include +#include +#include +#include static const char VMMCALL[3] = {0x0f, 0x01, 0xd9}; -int init_emulator(struct guest_info * info) { +#ifndef DEBUG_EMULATOR +#undef PrintDebug +#define PrintDebug(fmt, args...) +#endif + + +int v3_init_emulator(struct guest_info * info) { struct emulation_state * emulator = &(info->emulator); emulator->num_emulated_pages = 0; @@ -21,6 +49,8 @@ int init_emulator(struct guest_info * info) { emulator->running = 0; emulator->instr_length = 0; + emulator->tf_enabled = 0; + return 0; } @@ -31,7 +61,7 @@ static addr_t get_new_page() { 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(); @@ -52,10 +82,11 @@ static int setup_code_page(struct guest_info * info, char * instr, struct basic_ 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 @@ -70,6 +101,34 @@ static int setup_code_page(struct guest_info * info, char * instr, struct basic_ 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 @@ -81,7 +140,7 @@ int v3_emulate_memory_read(struct guest_info * info, addr_t read_gva, int (*read)(addr_t read_addr, void * dst, uint_t length, void * priv_data), addr_t read_gpa, void * private_data) { struct basic_instr_info instr_info; - char instr[15]; + uchar_t instr[15]; int ret; struct emulated_page * data_page = V3_Malloc(sizeof(struct emulated_page)); addr_t data_addr_offset = PT32_PAGE_OFFSET(read_gva); @@ -95,21 +154,30 @@ int v3_emulate_memory_read(struct guest_info * info, addr_t read_gva, ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr); } + if (ret == -1) { + PrintError("Could not read guest memory\n"); + return -1; + } + +#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); @@ -120,7 +188,8 @@ int v3_emulate_memory_read(struct guest_info * info, addr_t read_gva, // Read the data directly onto the emulated page - if (read(read_gpa, (void *)(data_page->page_addr + data_addr_offset), instr_info.op_size, private_data) != instr_info.op_size) { + ret = read(read_gpa, (void *)(data_page->page_addr + data_addr_offset), instr_info.op_size, private_data); + if ((ret == -1) || ((uint_t)ret != instr_info.op_size)) { PrintError("Read error in emulator\n"); V3_FreePage((void *)(data_page->page_addr)); V3_Free(data_page); @@ -143,7 +212,8 @@ int v3_emulate_memory_read(struct guest_info * info, addr_t 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; @@ -159,20 +229,26 @@ int v3_emulate_memory_write(struct guest_info * info, addr_t write_gva, addr_t write_gpa, void * private_data) { struct basic_instr_info instr_info; - char instr[15]; + uchar_t instr[15]; int ret; struct write_region * write_op = V3_Malloc(sizeof(struct write_region )); 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"); @@ -181,13 +257,18 @@ int v3_emulate_memory_write(struct guest_info * info, addr_t write_gva, 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); @@ -225,7 +306,8 @@ int v3_emulate_memory_write(struct guest_info * info, addr_t 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; @@ -290,7 +372,14 @@ int v3_emulation_exit_handler(struct guest_info * info) { 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");