X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_emulator.c;h=83d6d1a01db62874fdbf7a743afa3c565eb50da4;hb=c3cc58c287fd4a912919c4546f41026c571b13ec;hp=e6adab15263207f28f236013b2f599375537d5fb;hpb=266af4b5b19da7bee8e7445288c7c1cb3ee194c7;p=palacios.git diff --git a/palacios/src/palacios/vmm_emulator.c b/palacios/src/palacios/vmm_emulator.c index e6adab1..83d6d1a 100644 --- a/palacios/src/palacios/vmm_emulator.c +++ b/palacios/src/palacios/vmm_emulator.c @@ -24,22 +24,21 @@ #include #include -#ifndef DEBUG_EMULATOR +#ifndef CONFIG_DEBUG_EMULATOR #undef PrintDebug #define PrintDebug(fmt, args...) #endif - - static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_addr, addr_t dst_addr, int src_op_size, int dst_op_size); // We emulate up to the next 4KB page boundry static int emulate_string_write_op(struct guest_info * info, struct x86_instr * dec_instr, addr_t write_gva, addr_t write_gpa, addr_t dst_addr, - int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data), + int (*write_fn)(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data), void * priv_data) { uint_t emulation_length = 0; + uint_t emulation_iter_cnt = 0; addr_t tmp_rcx = 0; addr_t src_addr = 0; @@ -49,16 +48,17 @@ static int emulate_string_write_op(struct guest_info * info, struct x86_instr * return -1; } - emulation_length = ( (dec_instr->str_op_length < (0x1000 - PAGE_OFFSET_4KB(write_gva))) ? + /*emulation_length = ( (dec_instr->str_op_length < (0x1000 - PAGE_OFFSET_4KB(write_gva))) ? dec_instr->str_op_length : + (0x1000 - PAGE_OFFSET_4KB(write_gva)));*/ + emulation_length = ( (dec_instr->str_op_length * (dec_instr->dst_operand.size) < (0x1000 - PAGE_OFFSET_4KB(write_gva))) ? + dec_instr->str_op_length * dec_instr->dst_operand.size : (0x1000 - PAGE_OFFSET_4KB(write_gva))); /* ** Fix emulation length so that it doesn't overrun over the src page either ** */ - tmp_rcx = emulation_length; + emulation_iter_cnt = emulation_length / dec_instr->dst_operand.size; + tmp_rcx = emulation_iter_cnt; - - - if (dec_instr->op_type == V3_OP_MOVS) { // figure out addresses here.... @@ -94,7 +94,7 @@ static int emulate_string_write_op(struct guest_info * info, struct x86_instr * // RCX is only modified if the rep prefix is present if (dec_instr->prefixes.rep == 1) { - info->vm_regs.rcx -= emulation_length; + info->vm_regs.rcx -= emulation_iter_cnt; } } else if (dec_instr->op_type == V3_OP_STOS) { @@ -118,7 +118,7 @@ static int emulate_string_write_op(struct guest_info * info, struct x86_instr * // RCX is only modified if the rep prefix is present if (dec_instr->prefixes.rep == 1) { - info->vm_regs.rcx -= emulation_length; + info->vm_regs.rcx -= emulation_iter_cnt; } } else { @@ -126,7 +126,7 @@ static int emulate_string_write_op(struct guest_info * info, struct x86_instr * return -1; } - if (write_fn(write_gpa, (void *)dst_addr, emulation_length, priv_data) != emulation_length) { + if (write_fn(info, write_gpa, (void *)dst_addr, emulation_length, priv_data) != emulation_length) { PrintError("Did not fully read hooked data\n"); return -1; } @@ -141,7 +141,7 @@ static int emulate_string_write_op(struct guest_info * info, struct x86_instr * static int emulate_xchg_write_op(struct guest_info * info, struct x86_instr * dec_instr, addr_t write_gva, addr_t write_gpa, addr_t dst_addr, - int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data), + int (*write_fn)(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data), void * priv_data) { addr_t src_addr = 0; addr_t em_dst_addr = 0; @@ -150,12 +150,14 @@ static int emulate_xchg_write_op(struct guest_info * info, struct x86_instr * de PrintDebug("Emulating XCHG write\n"); if (dec_instr->src_operand.type == MEM_OPERAND) { - if (dec_instr->src_operand.operand != write_gva) { - PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n", - (void *)dec_instr->src_operand.operand, (void *)write_gva); - return -1; + if (info->shdw_pg_mode == SHADOW_PAGING) { + if (dec_instr->src_operand.operand != write_gva) { + PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n", + (void *)dec_instr->src_operand.operand, (void *)write_gva); + return -1; + } } - + src_addr = dst_addr; } else if (dec_instr->src_operand.type == REG_OPERAND) { src_addr = dec_instr->src_operand.operand; @@ -166,47 +168,51 @@ static int emulate_xchg_write_op(struct guest_info * info, struct x86_instr * de if (dec_instr->dst_operand.type == MEM_OPERAND) { - if (dec_instr->dst_operand.operand != write_gva) { - PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n", - (void *)dec_instr->dst_operand.operand, (void *)write_gva); - return -1; + if (info->shdw_pg_mode == SHADOW_PAGING) { + if (dec_instr->dst_operand.operand != write_gva) { + PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n", + (void *)dec_instr->dst_operand.operand, (void *)write_gva); + return -1; + } + } else { + //check that the operand (GVA) maps to the the faulting GPA } - + em_dst_addr = dst_addr; } else if (dec_instr->src_operand.type == REG_OPERAND) { em_dst_addr = dec_instr->src_operand.operand; } else { em_dst_addr = (addr_t)&(dec_instr->src_operand.operand); } - + dst_op_len = dec_instr->dst_operand.size; src_op_len = dec_instr->src_operand.size; - + PrintDebug("Dst_Addr = %p, SRC operand = %p\n", (void *)dst_addr, (void *)src_addr); - - + + if (run_op(info, dec_instr->op_type, src_addr, em_dst_addr, src_op_len, dst_op_len) == -1) { PrintError("Instruction Emulation Failed\n"); return -1; } - - if (write_fn(write_gpa, (void *)dst_addr, dst_op_len, priv_data) != dst_op_len) { + + if (write_fn(info, write_gpa, (void *)dst_addr, dst_op_len, priv_data) != dst_op_len) { PrintError("Did not fully write hooked data\n"); return -1; } - + info->rip += dec_instr->instr_length; - + return dst_op_len; } - + static int emulate_xchg_read_op(struct guest_info * info, struct x86_instr * dec_instr, addr_t read_gva, addr_t read_gpa, addr_t src_addr, - int (*read_fn)(addr_t guest_addr, void * dst, uint_t length, void * priv_data), - int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data), + int (*read_fn)(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data), + int (*write_fn)(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data), void * priv_data) { addr_t em_src_addr = 0; addr_t em_dst_addr = 0; @@ -232,12 +238,16 @@ static int emulate_xchg_read_op(struct guest_info * info, struct x86_instr * dec if (dec_instr->dst_operand.type == MEM_OPERAND) { - if (dec_instr->dst_operand.operand != read_gva) { - PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n", - (void *)dec_instr->dst_operand.operand, (void *)read_gva); - return -1; + if (info->shdw_pg_mode == SHADOW_PAGING) { + if (dec_instr->dst_operand.operand != read_gva) { + PrintError("XCHG: Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n", + (void *)dec_instr->dst_operand.operand, (void *)read_gva); + return -1; + } + } else { + //check that the operand (GVA) maps to the the faulting GPA } - + em_dst_addr = src_addr; } else if (dec_instr->src_operand.type == REG_OPERAND) { em_dst_addr = dec_instr->src_operand.operand; @@ -252,7 +262,7 @@ static int emulate_xchg_read_op(struct guest_info * info, struct x86_instr * dec (void *)em_dst_addr, (void *)em_src_addr); - if (read_fn(read_gpa, (void *)src_addr, src_op_len, priv_data) != src_op_len) { + if (read_fn(info, read_gpa, (void *)src_addr, src_op_len, priv_data) != src_op_len) { PrintError("Did not fully read hooked data\n"); return -1; } @@ -262,7 +272,7 @@ static int emulate_xchg_read_op(struct guest_info * info, struct x86_instr * dec return -1; } - if (write_fn(read_gpa, (void *)src_addr, dst_op_len, priv_data) != dst_op_len) { + if (write_fn(info, read_gpa, (void *)src_addr, dst_op_len, priv_data) != dst_op_len) { PrintError("Did not fully write hooked data\n"); return -1; } @@ -276,7 +286,7 @@ static int emulate_xchg_read_op(struct guest_info * info, struct x86_instr * dec int v3_emulate_write_op(struct guest_info * info, addr_t write_gva, addr_t write_gpa, addr_t dst_addr, - int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data), + int (*write_fn)(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data), void * priv_data) { struct x86_instr dec_instr; uchar_t instr[15]; @@ -286,7 +296,7 @@ int v3_emulate_write_op(struct guest_info * info, addr_t write_gva, addr_t write int dst_op_len = 0; PrintDebug("Emulating Write for instruction at %p\n", (void *)(addr_t)(info->rip)); - PrintDebug("GVA=%p\n", (void *)write_gva); + PrintDebug("GVA=%p Dst_Addr=%p\n", (void *)write_gva, (void *)dst_addr); if (info->mem_mode == PHYSICAL_MEM) { ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr); @@ -314,12 +324,15 @@ int v3_emulate_write_op(struct guest_info * info, addr_t write_gva, addr_t write } - - if ((dec_instr.dst_operand.type != MEM_OPERAND) || - (dec_instr.dst_operand.operand != write_gva)) { - PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n", - (void *)dec_instr.dst_operand.operand, (void *)write_gva); - return -1; + if (info->shdw_pg_mode == SHADOW_PAGING) { + if ((dec_instr.dst_operand.type != MEM_OPERAND) || + (dec_instr.dst_operand.operand != write_gva)) { + PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n", + (void *)dec_instr.dst_operand.operand, (void *)write_gva); + return -1; + } + } else { + //check that the operand (GVA) maps to the the faulting GPA } @@ -353,7 +366,7 @@ int v3_emulate_write_op(struct guest_info * info, addr_t write_gva, addr_t write return -1; } - if (write_fn(write_gpa, (void *)dst_addr, dst_op_len, priv_data) != dst_op_len) { + if (write_fn(info, write_gpa, (void *)dst_addr, dst_op_len, priv_data) != dst_op_len) { PrintError("Did not fully write hooked data\n"); return -1; } @@ -365,8 +378,8 @@ int v3_emulate_write_op(struct guest_info * info, addr_t write_gva, addr_t write int v3_emulate_read_op(struct guest_info * info, addr_t read_gva, addr_t read_gpa, addr_t src_addr, - int (*read_fn)(addr_t guest_addr, void * dst, uint_t length, void * priv_data), - int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data), + int (*read_fn)(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data), + int (*write_fn)(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data), void * priv_data) { struct x86_instr dec_instr; uchar_t instr[15]; @@ -383,11 +396,13 @@ int v3_emulate_read_op(struct guest_info * info, addr_t read_gva, addr_t read_gp } else { ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr); } - + if (ret == -1) { + PrintError("Could not read instruction for Emulated Read at %p\n", (void *)(addr_t)(info->rip)); return -1; } + if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) { PrintError("Decoding Error\n"); // Kick off single step emulator @@ -401,15 +416,17 @@ int v3_emulate_read_op(struct guest_info * info, addr_t read_gva, addr_t read_gp return emulate_xchg_read_op(info, &dec_instr, read_gva, read_gpa, src_addr, read_fn, write_fn, priv_data); } - - if ((dec_instr.src_operand.type != MEM_OPERAND) || - (dec_instr.src_operand.operand != read_gva)) { - PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n", - (void *)dec_instr.src_operand.operand, (void *)read_gva); - return -1; + if (info->shdw_pg_mode == SHADOW_PAGING) { + if ((dec_instr.src_operand.type != MEM_OPERAND) || + (dec_instr.src_operand.operand != read_gva)) { + PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p operand_type=%d\n", + (void *)dec_instr.src_operand.operand, (void *)read_gva, dec_instr.src_operand.type); + return -1; + } + } else { + //check that the operand (GVA) maps to the the faulting GPA } - if (dec_instr.dst_operand.type == MEM_OPERAND) { if (info->mem_mode == PHYSICAL_MEM) { if (guest_pa_to_host_va(info, dec_instr.dst_operand.operand, &dst_addr) == -1) { @@ -434,7 +451,7 @@ int v3_emulate_read_op(struct guest_info * info, addr_t read_gva, addr_t read_gp PrintDebug("Dst_Addr = %p, SRC Addr = %p\n", (void *)dst_addr, (void *)src_addr); - if (read_fn(read_gpa, (void *)src_addr, src_op_len, priv_data) != src_op_len) { + if (read_fn(info, read_gpa, (void *)src_addr, src_op_len, priv_data) != src_op_len) { PrintError("Did not fully read hooked data\n"); return -1; }