From: Jack Lange Date: Wed, 25 Mar 2009 23:43:30 +0000 (-0500) Subject: fixes to the emulator to handle nested paging X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=d3c1f093de953d47c55c11692f27aa2220c840b4 fixes to the emulator to handle nested paging --- diff --git a/palacios/src/palacios/vm_guest.c b/palacios/src/palacios/vm_guest.c index d5faa6c..c981a3c 100644 --- a/palacios/src/palacios/vm_guest.c +++ b/palacios/src/palacios/vm_guest.c @@ -63,13 +63,16 @@ v3_vm_cpu_mode_t v3_get_cpu_mode(struct guest_info * info) { uint_t v3_get_addr_width(struct guest_info * info) { struct cr0_32 * cr0; struct cr4_32 * cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4); - struct efer_64 * efer = (struct efer_64 *)&(info->guest_efer); + struct efer_64 * efer; struct v3_segment * cs = &(info->segments.cs); + vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data)); if (info->shdw_pg_mode == SHADOW_PAGING) { cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0); + efer = (struct efer_64 *)&(info->guest_efer); } else if (info->shdw_pg_mode == NESTED_PAGING) { cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0); + efer = (struct efer_64 *)&(guest_state->efer); } else { PrintError("Invalid Paging Mode...\n"); V3_ASSERT(0); diff --git a/palacios/src/palacios/vmm_emulator.c b/palacios/src/palacios/vmm_emulator.c index e6adab1..2df0469 100644 --- a/palacios/src/palacios/vmm_emulator.c +++ b/palacios/src/palacios/vmm_emulator.c @@ -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,41 +168,45 @@ 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) { 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, @@ -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; @@ -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 } @@ -401,15 +414,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\n", + (void *)dec_instr.src_operand.operand, (void *)read_gva); + 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) { diff --git a/palacios/src/palacios/vmm_mem.c b/palacios/src/palacios/vmm_mem.c index 38eb602..c244793 100644 --- a/palacios/src/palacios/vmm_mem.c +++ b/palacios/src/palacios/vmm_mem.c @@ -264,7 +264,7 @@ addr_t v3_get_shadow_addr(struct v3_shadow_region * reg, addr_t guest_addr) { (reg->host_type != SHDW_REGION_INVALID) ) { return (guest_addr - reg->guest_start) + reg->host_addr; } else { - PrintError("MEM Region Invalid\n"); + PrintDebug("MEM Region Invalid\n"); return 0; } } diff --git a/palacios/src/palacios/vmm_xed.c b/palacios/src/palacios/vmm_xed.c index 2e7d853..25ca076 100644 --- a/palacios/src/palacios/vmm_xed.c +++ b/palacios/src/palacios/vmm_xed.c @@ -568,7 +568,7 @@ static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xe int addr_width = v3_get_addr_width(info);; // struct v3_segment * seg_reg; - PrintDebug("Xen mode = %s\n", xed_machine_mode_enum_t2str(xed_state_get_machine_mode(info->decoder_state))); + PrintDebug("Xed mode = %s\n", xed_machine_mode_enum_t2str(xed_state_get_machine_mode(info->decoder_state))); PrintDebug("Address width: %s\n", xed_address_width_enum_t2str(xed_state_get_address_width(info->decoder_state))); PrintDebug("Stack Address width: %s\n",