X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_emulator.c;h=9e758874bb9c9739bfecd4c342094818a562a777;hb=f2c389745faae8bbd6e16b60baa59c01e735949f;hp=2870ba05ffdd4df0771d9a85272f2fb52df85697;hpb=c9dc7207b3bd4ccfcc185798415eddfdd09ae641;p=palacios.git diff --git a/palacios/src/palacios/vmm_emulator.c b/palacios/src/palacios/vmm_emulator.c index 2870ba0..9e75887 100644 --- a/palacios/src/palacios/vmm_emulator.c +++ b/palacios/src/palacios/vmm_emulator.c @@ -32,7 +32,7 @@ -static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_addr, addr_t dst_addr, int op_size); +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, @@ -43,98 +43,104 @@ static int emulate_string_write_op(struct guest_info * info, struct x86_instr * addr_t tmp_rcx = 0; addr_t src_addr = 0; - if (dec_instr->op_type == V3_OP_MOVS) { - PrintError("MOVS emulation\n"); - - if (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 (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; + } + + emulation_length = ( (dec_instr->str_op_length < (0x1000 - PAGE_OFFSET_4KB(write_gva))) ? + dec_instr->str_op_length : + (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_length = ( (dec_instr->str_op_length < (0x1000 - PAGE_OFFSET_4KB(write_gva))) ? - dec_instr->str_op_length : - (0x1000 - PAGE_OFFSET_4KB(write_gva))); - /* ** Fix emulation length so that it doesn't overrun over the src page either ** */ - PrintDebug("STR_OP_LEN: %d, Page Len: %d\n", - (uint_t)dec_instr->str_op_length, - (uint_t)(0x1000 - PAGE_OFFSET_4KB(write_gva))); - PrintDebug("Emulation length: %d\n", emulation_length); - tmp_rcx = emulation_length; - + if (dec_instr->op_type == V3_OP_MOVS) { + // figure out addresses here.... + if (info->mem_mode == PHYSICAL_MEM) { + if (guest_pa_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) { + PrintError("Could not translate write Source (Physical) to host VA\n"); + return -1; + } + } else { + if (guest_va_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) { + PrintError("Could not translate write Source (Virtual) to host VA\n"); + return -1; + } + } - // figure out addresses here.... - if (info->mem_mode == PHYSICAL_MEM) { - if (guest_pa_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) { - PrintError("Could not translate write Source (Physical) to host VA\n"); - return -1; - } + if (dec_instr->dst_operand.size == 1) { + movs8((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags)); + } else if (dec_instr->dst_operand.size == 2) { + movs16((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags)); + } else if (dec_instr->dst_operand.size == 4) { + movs32((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags)); +#ifdef __V3_64BIT__ + } else if (dec_instr->dst_operand.size == 8) { + movs64((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags)); +#endif } else { - if (guest_va_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) { - PrintError("Could not translate write Source (Virtual) to host VA\n"); - return -1; - } + PrintError("Invalid operand length\n"); + return -1; } + info->vm_regs.rdi += emulation_length; + info->vm_regs.rsi += emulation_length; - PrintDebug("Dst Operand: %p (size=%d), Src Operand: %p\n", - (void *)dec_instr->dst_operand.operand, - dec_instr->dst_operand.size, - (void *)dec_instr->src_operand.operand); - PrintDebug("Dst Addr: %p, Src Addr: %p\n", (void *)dst_addr, (void *)src_addr); - - //return -1; - - - + // RCX is only modified if the rep prefix is present + if (dec_instr->prefixes.rep == 1) { + info->vm_regs.rcx -= emulation_length; + } + } else if (dec_instr->op_type == V3_OP_STOS) { if (dec_instr->dst_operand.size == 1) { - movs8((addr_t *)dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags)); + stos8((addr_t *)&dst_addr, (addr_t *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags)); } else if (dec_instr->dst_operand.size == 2) { - movs16((addr_t *)dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags)); + stos16((addr_t *)&dst_addr, (addr_t *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags)); } else if (dec_instr->dst_operand.size == 4) { - movs32((addr_t*)dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags)); + stos32((addr_t *)&dst_addr, (addr_t *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags)); +#ifdef __V3_64BIT__ + } else if (dec_instr->dst_operand.size == 8) { + stos64((addr_t *)&dst_addr, (addr_t *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags)); +#endif } else { PrintError("Invalid operand length\n"); return -1; } - - if (write_fn(write_gpa, (void *)dst_addr, emulation_length, priv_data) != emulation_length) { - PrintError("Did not fully read hooked data\n"); - return -1; + info->vm_regs.rdi += emulation_length; + + // RCX is only modified if the rep prefix is present + if (dec_instr->prefixes.rep == 1) { + info->vm_regs.rcx -= emulation_length; } + } else { + PrintError("Unimplemented String operation\n"); + return -1; + } - PrintDebug("RDI=%p, RSI=%p, RCX=%p\n", - (void *)*(addr_t *)&(info->vm_regs.rdi), - (void *)*(addr_t *)&(info->vm_regs.rsi), - (void *)*(addr_t *)&(info->vm_regs.rcx)); + if (write_fn(write_gpa, (void *)dst_addr, emulation_length, priv_data) != emulation_length) { + PrintError("Did not fully read hooked data\n"); + return -1; + } - info->vm_regs.rdi += emulation_length; - info->vm_regs.rsi += emulation_length; - info->vm_regs.rcx -= emulation_length; - - PrintDebug("RDI=%p, RSI=%p, RCX=%p\n", - (void *)*(addr_t *)&(info->vm_regs.rdi), - (void *)*(addr_t *)&(info->vm_regs.rsi), - (void *)*(addr_t *)&(info->vm_regs.rcx)); + if (emulation_length == dec_instr->str_op_length) { + info->rip += dec_instr->instr_length; + } - if (emulation_length == dec_instr->str_op_length) { - info->rip += dec_instr->instr_length; - } + return emulation_length; - return emulation_length; - } - return -1; } @@ -148,7 +154,8 @@ int v3_emulate_write_op(struct guest_info * info, addr_t write_gva, addr_t write uchar_t instr[15]; int ret = 0; addr_t src_addr = 0; - int op_len = 0; + int src_op_len = 0; + 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); @@ -200,25 +207,26 @@ int v3_emulate_write_op(struct guest_info * info, addr_t write_gva, addr_t write src_addr = (addr_t)&(dec_instr.src_operand.operand); } - op_len = dec_instr.dst_operand.size; + 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, dst_addr, op_len) == -1) { + if (run_op(info, dec_instr.op_type, src_addr, dst_addr, src_op_len, dst_op_len) == -1) { PrintError("Instruction Emulation Failed\n"); return -1; } - if (write_fn(write_gpa, (void *)dst_addr, op_len, priv_data) != op_len) { - PrintError("Did not fully read hooked data\n"); + if (write_fn(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 op_len; + return dst_op_len; } @@ -229,10 +237,11 @@ int v3_emulate_read_op(struct guest_info * info, addr_t read_gva, addr_t read_gp uchar_t instr[15]; int ret = 0; addr_t dst_addr = 0; - int op_len = 0; + int src_op_len = 0; + int dst_op_len = 0; PrintDebug("Emulating Read for instruction at %p\n", (void *)(addr_t)(info->rip)); - PrintDebug("GVA=%p\n", (void *)write_gva); + PrintDebug("GVA=%p\n", (void *)read_gva); if (info->mem_mode == PHYSICAL_MEM) { ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr); @@ -282,24 +291,25 @@ int v3_emulate_read_op(struct guest_info * info, addr_t read_gva, addr_t read_gp dst_addr = (addr_t)&(dec_instr.dst_operand.operand); } - op_len = dec_instr.src_operand.size; + src_op_len = dec_instr.src_operand.size; + dst_op_len = dec_instr.dst_operand.size; PrintDebug("Dst_Addr = %p, SRC Addr = %p\n", (void *)dst_addr, (void *)src_addr); - if (read_fn(read_gpa, (void *)src_addr,op_len, priv_data) != op_len) { + if (read_fn(read_gpa, (void *)src_addr, src_op_len, priv_data) != src_op_len) { PrintError("Did not fully read hooked data\n"); return -1; } - if (run_op(info, dec_instr.op_type, src_addr, dst_addr, op_len) == -1) { + if (run_op(info, dec_instr.op_type, src_addr, dst_addr, src_op_len, dst_op_len) == -1) { PrintError("Instruction Emulation Failed\n"); return -1; } info->rip += dec_instr.instr_length; - return op_len; + return src_op_len; } @@ -307,9 +317,10 @@ int v3_emulate_read_op(struct guest_info * info, addr_t read_gva, addr_t read_gp -static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_addr, addr_t dst_addr, int op_size) { +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) { - if (op_size == 1) { + if (src_op_size == 1) { + PrintDebug("Executing 8 bit instruction\n"); switch (op_type) { case V3_OP_ADC: @@ -334,6 +345,14 @@ static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_add case V3_OP_MOV: mov8((addr_t *)dst_addr, (addr_t *)src_addr); break; + + case V3_OP_MOVZX: + movzx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size); + break; + case V3_OP_MOVSX: + movsx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size); + break; + case V3_OP_NOT: not8((addr_t *)dst_addr); break; @@ -405,7 +424,8 @@ static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_add return -1; } - } else if (op_size == 2) { + } else if (src_op_size == 2) { + PrintDebug("Executing 16 bit instruction\n"); switch (op_type) { case V3_OP_ADC: @@ -441,6 +461,12 @@ static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_add case V3_OP_MOV: mov16((addr_t *)dst_addr, (addr_t *)src_addr); break; + case V3_OP_MOVZX: + movzx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size); + break; + case V3_OP_MOVSX: + movsx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size); + break; case V3_OP_NOT: not16((addr_t *)dst_addr); break; @@ -453,7 +479,8 @@ static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_add return -1; } - } else if (op_size == 4) { + } else if (src_op_size == 4) { + PrintDebug("Executing 32 bit instruction\n"); switch (op_type) { case V3_OP_ADC: @@ -488,6 +515,7 @@ static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_add case V3_OP_MOV: mov32((addr_t *)dst_addr, (addr_t *)src_addr); break; + case V3_OP_NOT: not32((addr_t *)dst_addr); break; @@ -501,8 +529,8 @@ static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_add } #ifdef __V3_64BIT__ - } else if (op_size == 8) { - + } else if (src_op_size == 8) { + PrintDebug("Executing 64 bit instruction\n"); switch (op_type) { case V3_OP_ADC: @@ -537,6 +565,7 @@ static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_add case V3_OP_MOV: mov64((addr_t *)dst_addr, (addr_t *)src_addr); break; + case V3_OP_NOT: not64((addr_t *)dst_addr); break;