From: Jack Lange Date: Mon, 4 Aug 2008 20:21:06 +0000 (+0000) Subject: changed the emulator to use single step break points instead of page insertion X-Git-Tag: vmmhack1-ramdisk-boot-iso-puppy~24 X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=c373d9a80b116014c546e7761982fedf7419664b changed the emulator to use single step break points instead of page insertion can now handle rep instructions --- diff --git a/palacios/build/Makefile b/palacios/build/Makefile index f057439..9d2c700 100644 --- a/palacios/build/Makefile +++ b/palacios/build/Makefile @@ -1,6 +1,6 @@ # Makefile for GeekOS kernel, userspace, and tools # Copyright (c) 2004,2005 David H. Hovemeyer -# $Revision: 1.55 $ +# $Revision: 1.56 $ # This is free software. You are permitted to use, # redistribute, and modify it as specified in the file "COPYING". @@ -49,7 +49,7 @@ DEBUG=1 DEBUG_SECTIONS= ifeq ($(DEBUG_ALL),1) - DEBUG_SECTIONS:= $(DEBUG_SECTIONS) -DDEBUG_SHADOW_PAGING -DDEBUG_CTRL_REGS -DDEBUG_INTERRUPTS -DDEBUG_IO -DDEBUG_KEYBOARD -DDEBUG_PIC -DDEBUG_PIT -DDEBUG_NVRAM + DEBUG_SECTIONS:= $(DEBUG_SECTIONS) -DDEBUG_SHADOW_PAGING -DDEBUG_CTRL_REGS -DDEBUG_INTERRUPTS -DDEBUG_IO -DDEBUG_KEYBOARD -DDEBUG_PIC -DDEBUG_PIT -DDEBUG_NVRAM -DDEBUG_EMULATOR -DDEBUG_GENERIC endif ifeq ($(DEBUG_SHADOW_PAGING),1) DEBUG_SECTIONS := $(DEBUG_SECTIONS) -DDEBUG_SHADOW_PAGING @@ -75,6 +75,12 @@ endif ifeq ($(DEBUG_NVRAM),1) DEBUG_SECTIONS := $(DEBUG_SECTIONS) -DDEBUG_NVRAM endif +ifeq ($(DEBUG_GENERIC),1) +DEBUG_SECTIONS := $(DEBUG_SECTIONS) -DDEBUG_GENERIC +endif +ifeq ($(DEBUG_EMULATOR),1) +DEBUG_SECTIONS := $(DEBUG_SECTIONS) -DDEBUG_EMULATOR +endif ifeq ($(DEBUG),1) @@ -191,7 +197,6 @@ VMM_C_SRCS := vm_guest.c \ svm_halt.c svm_pause.c vmm_config.c vmm_hashtable.c \ vmm_string.c vmm_emulator.c \ $(DECODER_SRCS) -#\ # vmx.c vmcs_gen.c vmcs.c VMM_C_OBJS := $(VMM_C_SRCS:%.c=palacios/%.o) diff --git a/palacios/include/palacios/vm_guest.h b/palacios/include/palacios/vm_guest.h index 79ba15d..2aea24c 100644 --- a/palacios/include/palacios/vm_guest.h +++ b/palacios/include/palacios/vm_guest.h @@ -40,6 +40,16 @@ struct v3_ctrl_regs { }; + +struct v3_dbg_regs { + v3_reg_t dr0; + v3_reg_t dr1; + v3_reg_t dr2; + v3_reg_t dr3; + v3_reg_t dr6; + v3_reg_t dr7; +}; + struct v3_segment { ushort_t selector; uint_t limit; @@ -120,6 +130,7 @@ struct guest_info { struct v3_gprs vm_regs; struct v3_ctrl_regs ctrl_regs; + struct v3_dbg_regs dbg_regs; struct v3_segments segments; struct vm_ctrl_ops vm_ops; diff --git a/palacios/include/palacios/vmm_debug.h b/palacios/include/palacios/vmm_debug.h index db37060..2e846cd 100644 --- a/palacios/include/palacios/vmm_debug.h +++ b/palacios/include/palacios/vmm_debug.h @@ -2,6 +2,100 @@ #define __VMM_DEBUG_H +#ifdef __V3VEE__ +#include + +struct dbg_bp32 { + uint_t breakpoint : 32; +}; + +struct dbg_bp64 { + ullong_t breakpoint; +}; + +struct dr6_32 { + uint_t bp0 : 1; + uint_t bp1 : 1; + uint_t bp2 : 1; + uint_t bp3 : 1; + uint_t rsvd1 : 8; // read as ones + uint_t rsvd2 : 1; // read as zero + uint_t bd : 1; + uint_t bs : 1; + uint_t bt : 1; + uint_t rsvd3 : 16; // read as one +}; + + +struct dr6_64 { + uint_t bp0 : 1; + uint_t bp1 : 1; + uint_t bp2 : 1; + uint_t bp3 : 1; + uint_t rsvd1 : 8; // read as ones + uint_t rsvd2 : 1; // read as zero + uint_t bd : 1; + uint_t bs : 1; + uint_t bt : 1; + uint_t rsvd3 : 16; // read as one + uint_t rsvd4 : 32; // MBZ +}; + + +struct dr7_32 { + uint_t L0 : 1; + uint_t G0 : 1; + uint_t L1 : 1; + uint_t G1 : 1; + uint_t L2 : 1; + uint_t G2 : 1; + uint_t L3 : 1; + uint_t G3 : 1; + uint_t LE : 1; + uint_t GE : 1; + uint_t rsvd1 : 1; // Read as one + uint_t rsvd2 : 2; // Read as zero + uint_t GD : 1; + uint_t rsvd3 : 2; // Read as zero + uint_t rw0 : 1; + uint_t len0 : 1; + uint_t rw1 : 1; + uint_t len1 : 1; + uint_t rw2 : 1; + uint_t len2 : 1; + uint_t rw3 : 1; + uint_t len3 : 1; +}; + + +struct dr7_64 { + uint_t L0 : 1; + uint_t G0 : 1; + uint_t L1 : 1; + uint_t G1 : 1; + uint_t L2 : 1; + uint_t G2 : 1; + uint_t L3 : 1; + uint_t G3 : 1; + uint_t LE : 1; + uint_t GE : 1; + uint_t rsvd1 : 1; // Read as one + uint_t rsvd2 : 2; // Read as zero + uint_t GD : 1; + uint_t rsvd3 : 2; // Read as zero + uint_t rw0 : 1; + uint_t len0 : 1; + uint_t rw1 : 1; + uint_t len1 : 1; + uint_t rw2 : 1; + uint_t len2 : 1; + uint_t rw3 : 1; + uint_t len3 : 1; + uint_t rsvd4 : 32; // MBZ +}; + + + @@ -10,5 +104,6 @@ void PrintDebugMemDump(unsigned char *start, int n); +#endif // !__V3VEE__ #endif diff --git a/palacios/include/palacios/vmm_emulator.h b/palacios/include/palacios/vmm_emulator.h index 3780d1c..6e909a6 100644 --- a/palacios/include/palacios/vmm_emulator.h +++ b/palacios/include/palacios/vmm_emulator.h @@ -49,6 +49,8 @@ struct emulation_state { uint_t running : 1; uint_t instr_length; + + uint_t tf_enabled : 1; }; diff --git a/palacios/include/palacios/vmm_mem.h b/palacios/include/palacios/vmm_mem.h index 3e418ec..c51802c 100644 --- a/palacios/include/palacios/vmm_mem.h +++ b/palacios/include/palacios/vmm_mem.h @@ -115,8 +115,6 @@ void print_shadow_map(struct shadow_map * map); - - struct vmm_mem_hook { // Called when data is read from a memory page int (*read)(addr_t guest_addr, void * dst, uint_t length, void * priv_data); diff --git a/palacios/src/palacios/svm_handler.c b/palacios/src/palacios/svm_handler.c index 96ab5fb..e634b2b 100644 --- a/palacios/src/palacios/svm_handler.c +++ b/palacios/src/palacios/svm_handler.c @@ -30,6 +30,8 @@ int handle_svm_exit(struct guest_info * info) { info->ctrl_regs.cr2 = guest_state->cr2; info->ctrl_regs.cr3 = guest_state->cr3; info->ctrl_regs.cr4 = guest_state->cr4; + info->dbg_regs.dr6 = guest_state->dr6; + info->dbg_regs.dr7 = guest_state->dr7; info->ctrl_regs.cr8 = guest_ctrl->guest_ctrl.V_TPR; info->ctrl_regs.rflags = guest_state->rflags; info->ctrl_regs.efer = guest_state->efer; @@ -192,8 +194,22 @@ int handle_svm_exit(struct guest_info * info) { if (handle_svm_pause(info) == -1) { return -1; } + } else if (exit_code == VMEXIT_EXCP1) { +#ifdef DEBUG_EMULATOR + PrintDebug("DEBUG EXCEPTION\n"); +#endif + if (info->run_state == VM_EMULATING) { + if (v3_emulation_exit_handler(info) == -1) { + return -1; + } + } else { + PrintError("VMMCALL with not emulator...\n"); + return -1; + } } else if (exit_code == VMEXIT_VMMCALL) { +#ifdef DEBUG_EMULATOR PrintDebug("VMMCALL\n"); +#endif if (info->run_state == VM_EMULATING) { if (v3_emulation_exit_handler(info) == -1) { return -1; @@ -343,6 +359,8 @@ int handle_svm_exit(struct guest_info * info) { guest_state->cr2 = info->ctrl_regs.cr2; guest_state->cr3 = info->ctrl_regs.cr3; guest_state->cr4 = info->ctrl_regs.cr4; + guest_state->dr6 = info->dbg_regs.dr6; + guest_state->dr7 = info->dbg_regs.dr7; guest_ctrl->guest_ctrl.V_TPR = info->ctrl_regs.cr8 & 0xff; guest_state->rflags = info->ctrl_regs.rflags; guest_state->efer = info->ctrl_regs.efer; diff --git a/palacios/src/palacios/vmm_config.c b/palacios/src/palacios/vmm_config.c index 1e3e2f3..65c6eff 100644 --- a/palacios/src/palacios/vmm_config.c +++ b/palacios/src/palacios/vmm_config.c @@ -11,15 +11,20 @@ #include -static int passthrough_mem_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data) { - // memcpy(dst, (void*)guest_addr, length); - int foo = 20; + +static int mem_test_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data) { + int foo = 20; memcpy(dst, &foo, length); PrintDebug("Passthrough mem read returning: %d (length=%d)\n", foo + (guest_addr & 0xfff), length); return length; + } + +static int passthrough_mem_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data) { + memcpy(dst, (void*)guest_addr, length); + return length; } static int passthrough_mem_write(addr_t guest_addr, void * src, uint_t length, void * priv_data) { @@ -93,8 +98,8 @@ int config_guest(struct guest_info * info, void * config_ptr) { // add_shadow_region_passthrough(info, 0x0, 0xa0000, (addr_t)V3_AllocPages(160)); - add_shadow_region_passthrough(info, 0xa0000, 0xc0000, 0xa0000); - //hook_guest_mem(info, 0xa0000, 0xc0000, passthrough_mem_read, passthrough_mem_write, NULL); + //add_shadow_region_passthrough(info, 0xa0000, 0xc0000, 0xa0000); + hook_guest_mem(info, 0xa0000, 0xc0000, passthrough_mem_read, passthrough_mem_write, NULL); // TEMP @@ -116,7 +121,7 @@ int config_guest(struct guest_info * info, void * config_ptr) { { /* MEMORY HOOK TEST */ add_shadow_region_passthrough(info, 0x100000, 0xa00000, (addr_t)V3_AllocPages(2304)); - hook_guest_mem(info, 0xa00000, 0xa01000, passthrough_mem_read, passthrough_mem_write, NULL); + hook_guest_mem(info, 0xa00000, 0xa01000, mem_test_read, passthrough_mem_write, NULL); add_shadow_region_passthrough(info, 0xa01000, 0x1000000, (addr_t)V3_AllocPages(1791)); diff --git a/palacios/src/palacios/vmm_emulator.c b/palacios/src/palacios/vmm_emulator.c index fcce7c3..3fedc51 100644 --- a/palacios/src/palacios/vmm_emulator.c +++ b/palacios/src/palacios/vmm_emulator.c @@ -2,9 +2,18 @@ #include #include #include +#include +#include +#include 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); @@ -21,6 +30,8 @@ int init_emulator(struct guest_info * info) { emulator->running = 0; emulator->instr_length = 0; + emulator->tf_enabled = 0; + return 0; } @@ -31,7 +42,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 +63,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 +82,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 @@ -95,21 +135,25 @@ 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); } +#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); @@ -143,7 +187,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; @@ -181,13 +226,14 @@ int v3_emulate_memory_write(struct guest_info * info, addr_t write_gva, return -1; } + /* 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 +271,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 +337,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");