From: Jack Lange Date: Sat, 7 Feb 2009 01:11:04 +0000 (-0600) Subject: bug fixes for: X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=af10c7cdec94c879b207983a60581feae911546b bug fixes for: xed decoder passthrough paging emulator added apic memory hooks --- diff --git a/palacios/include/palacios/vmm_direct_paging.h b/palacios/include/palacios/vmm_direct_paging.h index c33833a..00eac31 100644 --- a/palacios/include/palacios/vmm_direct_paging.h +++ b/palacios/include/palacios/vmm_direct_paging.h @@ -8,7 +8,7 @@ pde32_t * v3_create_direct_passthrough_pts(struct guest_info * guest_info); -int v3_handle_shadow_pagefault_physical_mode(struct guest_info * info, addr_t fault_addr, pf_error_t error_code); +int v3_handle_passthrough_pagefault(struct guest_info * info, addr_t fault_addr, pf_error_t error_code); #endif // ! __V3VEE__ diff --git a/palacios/src/devices/apic.c b/palacios/src/devices/apic.c index 8f4b8fe..f899419 100644 --- a/palacios/src/devices/apic.c +++ b/palacios/src/devices/apic.c @@ -23,15 +23,29 @@ #include #define BASE_ADDR_MSR 0x0000001B +#define DEFAULT_BASE_ADDR 0xfee00000 +struct apic_base_addr_reg { + uchar_t rsvd; + uint_t bsc : 1; + uint_t rsvd2 : 2; + uint_t apic_enable : 1; + ullong_t base_addr : 40; + uint_t rsvd3 : 12; +} __attribute__((packed)); + struct apic_state { + addr_t base_addr; + v3_msr_t base_addr_reg; + + }; -static int read_base_addr(uint_t msr, v3_msr_t * dst, void * priv_data) { +static int read_apic_msr(uint_t msr, v3_msr_t * dst, void * priv_data) { struct vm_device * dev = (struct vm_device *)priv_data; struct apic_state * apic = (struct apic_state *)dev->private_data; PrintDebug("READING APIC BASE ADDR: HI=%x LO=%x\n", apic->base_addr_reg.hi, apic->base_addr_reg.lo); @@ -40,7 +54,7 @@ static int read_base_addr(uint_t msr, v3_msr_t * dst, void * priv_data) { } -static int write_base_addr(uint_t msr, v3_msr_t src, void * priv_data) { +static int write_apic_msr(uint_t msr, v3_msr_t src, void * priv_data) { // struct vm_device * dev = (struct vm_device *)priv_data; // struct apic_state * apic = (struct apic_state *)dev->private_data; @@ -50,6 +64,18 @@ static int write_base_addr(uint_t msr, v3_msr_t src, void * priv_data) { } +static int apic_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data) { + PrintDebug("Read from apic address space\n"); + return -1; +} + + +static int apic_write(addr_t guest_addr, void * dst, uint_t length, void * priv_data) { + PrintDebug("Write to apic address space\n"); + return -1; +} + + static int apic_deinit(struct vm_device * dev) { struct guest_info * info = dev->vm; @@ -61,8 +87,13 @@ static int apic_deinit(struct vm_device * dev) { static int apic_init(struct vm_device * dev) { struct guest_info * info = dev->vm; + struct apic_state * apic = (struct apic_state *)(dev->private_data); + + apic->base_addr = DEFAULT_BASE_ADDR; + + v3_hook_msr(info, BASE_ADDR_MSR, read_apic_msr, write_apic_msr, dev); - v3_hook_msr(info, BASE_ADDR_MSR, read_base_addr, write_base_addr, dev); + v3_hook_full_mem(info, DEFAULT_BASE_ADDR, DEFAULT_BASE_ADDR + PAGE_SIZE_4KB, apic_read, apic_write, dev); return 0; } diff --git a/palacios/src/palacios/vmm_direct_paging.c b/palacios/src/palacios/vmm_direct_paging.c index c197c4c..44742cb 100644 --- a/palacios/src/palacios/vmm_direct_paging.c +++ b/palacios/src/palacios/vmm_direct_paging.c @@ -1,19 +1,20 @@ #include - -// Inline handler functions for each cpu mode -#include "vmm_direct_paging_32.h" - #include #include #include #include + + +// Inline handler functions for each cpu mode +#include "vmm_direct_paging_32.h" + pde32_t * v3_create_direct_passthrough_pts(struct guest_info * info) { v3_vm_cpu_mode_t mode = v3_get_cpu_mode(info); switch(mode) { case REAL: case PROTECTED: - return v3_create_direct_passthrough_pts_32(info); + return create_direct_passthrough_pts_32(info); case PROTECTED_PAE: break; case LONG: @@ -27,12 +28,13 @@ pde32_t * v3_create_direct_passthrough_pts(struct guest_info * info) { return NULL; } -int v3_handle_shadow_pagefault_physical_mode(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) { +int v3_handle_passthrough_pagefault(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) { v3_vm_cpu_mode_t mode = v3_get_cpu_mode(info); + switch(mode) { case REAL: case PROTECTED: - return v3_handle_shadow_pagefault_physical_mode_32(info, fault_addr, error_code); + return handle_passthrough_pagefault_32(info, fault_addr, error_code); case PROTECTED_PAE: break; case LONG: diff --git a/palacios/src/palacios/vmm_direct_paging_32.h b/palacios/src/palacios/vmm_direct_paging_32.h index d075e74..2b34cf2 100644 --- a/palacios/src/palacios/vmm_direct_paging_32.h +++ b/palacios/src/palacios/vmm_direct_paging_32.h @@ -25,52 +25,67 @@ static pte32_t * create_pte32() { } -static inline pde32_t * v3_create_direct_passthrough_pts_32(struct guest_info * info) { +static inline pde32_t * create_direct_passthrough_pts_32(struct guest_info * info) { return create_pde32(); } -static inline int v3_handle_shadow_pagefault_physical_mode_32(struct guest_info * info, addr_t fault_addr, pf_error_t error_code) { +static inline int handle_passthrough_pagefault_32(struct guest_info * info, + addr_t fault_addr, + pf_error_t error_code) { // Check to see if pde and pte exist (create them if not) pde32_t * pde = CR3_TO_PDE32_VA(info->ctrl_regs.cr3); int pde_index = PDE32_INDEX(fault_addr); int pte_index = PTE32_INDEX(fault_addr); - if(pde[pde_index].present != 1) { + + if (pde[pde_index].present != 1) { + PrintError("Creating new page table for PTE index: %d\n", pde_index); + pte32_t * pte = create_pte32(); addr_t host_addr; + if(guest_pa_to_host_pa(info, fault_addr, &host_addr) == -1) return -1; + struct v3_shadow_region * region = v3_get_shadow_region(info, PAGE_BASE_ADDR(host_addr)); + + pte[pte_index].present = 1; + pte[pte_index].writable = 1; + pte[pte_index].user_page = 1; + pte[pte_index].page_base_addr = PAGE_BASE_ADDR(host_addr); + + pde[pde_index].present = 1; + pde[pde_index].writable = 1; + pde[pde_index].user_page = 1; + pde[pde_index].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte)); + + if (region->host_type == SHDW_REGION_WRITE_HOOK) { + pte[pte_index].writable = 0; + } + + PrintError("Fault Addr: 0x%p\nHost Addr: 0x%p\n", (void*)fault_addr, (void*)host_addr); + + } else { + pte32_t * pte = V3_VAddr((void*)BASE_TO_PAGE_ADDR(pde[pde_index].pt_base_addr)); + + if (pte[pte_index].present != 1) { + addr_t host_addr; + + if (guest_pa_to_host_pa(info, fault_addr, &host_addr) == -1) return -1; + + struct v3_shadow_region * region = v3_get_shadow_region(info, PAGE_BASE_ADDR(host_addr)); + pte[pte_index].present = 1; pte[pte_index].writable = 1; pte[pte_index].user_page = 1; pte[pte_index].page_base_addr = PAGE_BASE_ADDR(host_addr); - - pde[pde_index].present = 1; - pde[pde_index].writable = 1; - pde[pde_index].user_page = 1; - pde[pde_index].pt_base_addr = PAGE_BASE_ADDR((addr_t)V3_PAddr(pte)); - if(region->host_type == SHDW_REGION_WRITE_HOOK) { + + if (region->host_type == SHDW_REGION_WRITE_HOOK) { pte[pte_index].writable = 0; } - PrintError("Fault Addr: 0x%p\nHost Addr: 0x%p\n", (void*)fault_addr, (void*)host_addr); - } - else { - pte32_t * pte = (void*)BASE_TO_PAGE_ADDR(pde[pde_index].pt_base_addr); - if(pte[pte_index].present != 1) { - addr_t host_addr; - if(guest_pa_to_host_pa(info, fault_addr, &host_addr) == -1) return -1; - struct v3_shadow_region * region = v3_get_shadow_region(info, PAGE_BASE_ADDR(host_addr)); - pte[pte_index].present = 1; - pte[pte_index].writable = 1; - pte[pte_index].user_page = 1; - pte[pte_index].page_base_addr = PAGE_BASE_ADDR(host_addr); - if(region->host_type == SHDW_REGION_WRITE_HOOK) { - pte[pte_index].writable = 0; - } - } } - return 0; + } + return 0; } diff --git a/palacios/src/palacios/vmm_emulator.c b/palacios/src/palacios/vmm_emulator.c index 2870ba0..9d166c4 100644 --- a/palacios/src/palacios/vmm_emulator.c +++ b/palacios/src/palacios/vmm_emulator.c @@ -93,16 +93,17 @@ static int emulate_string_write_op(struct guest_info * info, struct x86_instr * if (dec_instr->dst_operand.size == 1) { - movs8((addr_t *)dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags)); + 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)); + 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)); + movs32((addr_t*)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags)); } else { PrintError("Invalid operand length\n"); return -1; } + PrintDebug("Calling Write function\n"); if (write_fn(write_gpa, (void *)dst_addr, emulation_length, priv_data) != emulation_length) { PrintError("Did not fully read hooked data\n"); @@ -232,7 +233,7 @@ int v3_emulate_read_op(struct guest_info * info, addr_t read_gva, addr_t read_gp int 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); diff --git a/palacios/src/palacios/vmm_shadow_paging.c b/palacios/src/palacios/vmm_shadow_paging.c index 3ae28d4..2475734 100644 --- a/palacios/src/palacios/vmm_shadow_paging.c +++ b/palacios/src/palacios/vmm_shadow_paging.c @@ -129,7 +129,7 @@ int v3_handle_shadow_pagefault(struct guest_info * info, addr_t fault_addr, pf_e if (v3_get_mem_mode(info) == PHYSICAL_MEM) { // If paging is not turned on we need to handle the special cases - return v3_handle_shadow_pagefault_physical_mode(info, fault_addr, error_code); + return v3_handle_passthrough_pagefault(info, fault_addr, error_code); } else if (v3_get_mem_mode(info) == VIRTUAL_MEM) { switch (v3_get_cpu_mode(info)) { diff --git a/palacios/src/palacios/vmm_xed.c b/palacios/src/palacios/vmm_xed.c index e6de1e1..5975797 100644 --- a/palacios/src/palacios/vmm_xed.c +++ b/palacios/src/palacios/vmm_xed.c @@ -112,7 +112,6 @@ static int set_decoder_mode(struct guest_info * info, xed_state_t * state) { break; case PROTECTED: case PROTECTED_PAE: - case LONG_32_COMPAT: if (state->mmode != XED_MACHINE_MODE_LEGACY_32) { xed_state_init(state, XED_MACHINE_MODE_LEGACY_32, @@ -120,9 +119,23 @@ static int set_decoder_mode(struct guest_info * info, xed_state_t * state) { XED_ADDRESS_WIDTH_32b); } break; + case LONG_32_COMPAT: + if (state->mmode != XED_MACHINE_MODE_LONG_COMPAT_32) { + xed_state_init(state, + XED_MACHINE_MODE_LONG_COMPAT_32, + XED_ADDRESS_WIDTH_32b, + XED_ADDRESS_WIDTH_32b); + } + break; case LONG: - if (state->mmode != XED_MACHINE_MODE_LONG_64) { - state->mmode = XED_MACHINE_MODE_LONG_64; + if (state->mmode != XED_MACHINE_MODE_LONG_64) { + PrintDebug("Setting decoder to long mode\n"); + // state->mmode = XED_MACHINE_MODE_LONG_64; + //xed_state_set_machine_mode(state, XED_MACHINE_MODE_LONG_64); + xed_state_init(state, + XED_MACHINE_MODE_LONG_64, + XED_ADDRESS_WIDTH_64b, + XED_ADDRESS_WIDTH_64b); } break; default: @@ -154,6 +167,10 @@ int v3_init_decoder(struct guest_info * info) { xed_state_t * decoder_state = (xed_state_t *)V3_Malloc(sizeof(xed_state_t)); xed_state_zero(decoder_state); + xed_state_init(decoder_state, + XED_MACHINE_MODE_LEGACY_32, + XED_ADDRESS_WIDTH_32b, + XED_ADDRESS_WIDTH_32b); info->decoder_state = decoder_state; @@ -527,8 +544,11 @@ static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xe ullong_t displacement; // struct v3_segment * seg_reg; - - + PrintDebug("Xen 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", + xed_address_width_enum_t2str(xed_state_get_stack_address_width(info->decoder_state))); memset((void*)&mem_op, '\0', sizeof(struct memory_operand)); @@ -596,7 +616,8 @@ static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xe base = MASK(mem_op.base, mem_op.base_size); index = MASK(mem_op.index, mem_op.index_size); scale = mem_op.scale; - displacement = MASK(mem_op.displacement, mem_op.displacement_size); + // displacement = MASK(mem_op.displacement, mem_op.displacement_size); + displacement = mem_op.displacement; PrintDebug("Seg=%p, base=%p, index=%p, scale=%p, displacement=%p\n", (void *)seg, (void *)base, (void *)index, (void *)scale, (void *)(addr_t)displacement); @@ -608,7 +629,7 @@ static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xe static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, addr_t * v3_reg, uint_t * reg_len) { - // PrintError("Xed Register: %s\n", xed_reg_enum_t2str(xed_reg)); + PrintDebug("Xed Register: %s\n", xed_reg_enum_t2str(xed_reg)); switch (xed_reg) { case XED_REG_INVALID: