[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [PATCH] [PATCH] Assorted VMX patches
ChangeSet 1.1379, 2005/04/25 08:55:36+01:00, leendert@xxxxxxxxxxxxxx [PATCH] [PATCH] Assorted VMX patches This patch contains the following VMX patches: - ioemu: Update the address when doing a stosb/stosw/stosl. Without this patch stosb writes req->count times at the same location req->addr. Not exactly the intended semantics. - xc_ptrace.c: Use the page_array to refer to partition memory. This allows you to use gdbserver on a VMX partition (and presumably partitions that use shadow page tables). - dom0_ops.c: Preserve ECF_VMX_GUEST flag for gdbserver. Without it you cannot (re)set the VMX domain state. - vmx.c: Added support for lmsw. Unmodified FreeBSD uses this when running inside a VMX partition. Signed-Off-By: Leendert van Doorn <leendert@xxxxxxxxxxxxxx> ===== tools/ioemu/iodev/cpu.cc 1.8 vs edited ===== tools/ioemu/iodev/cpu.cc | 6 - tools/libxc/xc_ptrace.c | 28 ++++++- xen/arch/x86/dom0_ops.c | 4 + xen/arch/x86/vmx.c | 166 ++++++++++++++++++++++++---------------------- xen/include/asm-x86/vmx.h | 2 5 files changed, 121 insertions(+), 85 deletions(-) diff -Nru a/tools/ioemu/iodev/cpu.cc b/tools/ioemu/iodev/cpu.cc --- a/tools/ioemu/iodev/cpu.cc 2005-04-25 04:04:22 -04:00 +++ b/tools/ioemu/iodev/cpu.cc 2005-04-25 04:04:22 -04:00 @@ -128,15 +128,13 @@ if (!req->pdata_valid) { if(req->dir == IOREQ_READ){//read //BX_INFO(("mmio[value]: <READ> addr:%llx, value:%llx, size: %llx, count: %llx\n", req->addr, req->u.data, req->size, req->count)); - for (i = 0; i < req->count; i++) { - BX_MEM_READ_PHYSICAL(req->addr, req->size, &req->u.data); + BX_MEM_READ_PHYSICAL(req->addr + (sign * i * req->size), req->size, &req->u.data); } } else if(req->dir == IOREQ_WRITE) {//write //BX_INFO(("mmio[value]: <WRITE> addr:%llx, value:%llx, size: %llx, count: %llx\n", req->addr, req->u.data, req->size, req->count)); - for (i = 0; i < req->count; i++) { - BX_MEM_WRITE_PHYSICAL(req->addr, req->size, &req->u.data); + BX_MEM_WRITE_PHYSICAL(req->addr + (sign * i * req->size), req->size, &req->u.data); } } } else { diff -Nru a/tools/libxc/xc_ptrace.c b/tools/libxc/xc_ptrace.c --- a/tools/libxc/xc_ptrace.c 2005-04-25 04:04:22 -04:00 +++ b/tools/libxc/xc_ptrace.c 2005-04-25 04:04:22 -04:00 @@ -75,7 +75,7 @@ int retval = xc_domain_getfullinfo(xc_handle, domid, cpu, NULL, &ctxt[cpu]); \ if (retval) \ goto error_out; \ - cr3[cpu] = ctxt[cpu].pt_base; \ + cr3[cpu] = ctxt[cpu].pt_base; /* physical address */ \ regs_valid[cpu] = 1; \ } \ @@ -128,11 +128,12 @@ static int xc_handle; +static long nr_pages = 0; +unsigned long *page_array = NULL; static int regs_valid[MAX_VIRT_CPUS]; static unsigned long cr3[MAX_VIRT_CPUS]; static full_execution_context_t ctxt[MAX_VIRT_CPUS]; - /* --------------------- */ static void * @@ -140,6 +141,7 @@ { unsigned long pde, page; unsigned long va = (unsigned long)guest_va; + long npgs = xc_get_tot_pages(xc_handle, domid); static unsigned long cr3_phys[MAX_VIRT_CPUS]; static unsigned long *cr3_virt[MAX_VIRT_CPUS]; @@ -150,6 +152,21 @@ static int prev_perm[MAX_VIRT_CPUS]; + if (nr_pages != npgs) { + if (nr_pages > 0) + free(page_array); + nr_pages = npgs; + if ((page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL) { + printf("Could not allocate memory\n"); + goto error_out; + } + + if (xc_get_pfn_list(xc_handle, domid, page_array, nr_pages) != nr_pages) { + printf("Could not get the page frame list\n"); + goto error_out; + } + } + FETCH_REGS(cpu); if (cr3[cpu] != cr3_phys[cpu]) @@ -162,8 +179,9 @@ cr3_phys[cpu] >> PAGE_SHIFT)) == NULL) goto error_out; } - if ((pde = cr3_virt[cpu][vtopdi(va)]) == 0) + if ((pde = cr3_virt[cpu][vtopdi(va)]) == 0) /* logical address */ goto error_out; + pde = page_array[pde >> PAGE_SHIFT] << PAGE_SHIFT; if (pde != pde_phys[cpu]) { pde_phys[cpu] = pde; @@ -174,8 +192,9 @@ pde_phys[cpu] >> PAGE_SHIFT)) == NULL) goto error_out; } - if ((page = pde_virt[cpu][vtopti(va)]) == 0) + if ((page = pde_virt[cpu][vtopti(va)]) == 0) /* logical address */ goto error_out; + page = page_array[page >> PAGE_SHIFT] << PAGE_SHIFT; if (page != page_phys[cpu] || perm != prev_perm[cpu]) { page_phys[cpu] = page; @@ -330,6 +349,7 @@ perror("dom0 op failed"); goto error_out; } + /* FALLTHROUGH */ case PTRACE_CONT: case PTRACE_DETACH: if (request != PTRACE_SINGLESTEP) { diff -Nru a/xen/arch/x86/dom0_ops.c b/xen/arch/x86/dom0_ops.c --- a/xen/arch/x86/dom0_ops.c 2005-04-25 04:04:22 -04:00 +++ b/xen/arch/x86/dom0_ops.c 2005-04-25 04:04:22 -04:00 @@ -402,6 +402,10 @@ c->flags |= ECF_I387_VALID; if ( KERNEL_MODE(ed, &ed->arch.user_ctxt) ) c->flags |= ECF_IN_KERNEL; +#ifdef CONFIG_VMX + if (VMX_DOMAIN(ed)) + c->flags |= ECF_VMX_GUEST; +#endif memcpy(&c->fpu_ctxt, &ed->arch.i387, sizeof(ed->arch.i387)); diff -Nru a/xen/arch/x86/vmx.c b/xen/arch/x86/vmx.c --- a/xen/arch/x86/vmx.c 2005-04-25 04:04:22 -04:00 +++ b/xen/arch/x86/vmx.c 2005-04-25 04:04:22 -04:00 @@ -640,6 +640,84 @@ return 0; } +static int vmx_set_cr0(unsigned long value) +{ + struct exec_domain *d = current; + unsigned long old_base_mfn, mfn; + unsigned long eip; + + /* + * CR0: We don't want to lose PE and PG. + */ + __vmwrite(GUEST_CR0, (value | X86_CR0_PE | X86_CR0_PG)); + + if (value & (X86_CR0_PE | X86_CR0_PG) && + !test_bit(VMX_CPU_STATE_PG_ENABLED, &d->arch.arch_vmx.cpu_state)) { + /* + * Enable paging + */ + set_bit(VMX_CPU_STATE_PG_ENABLED, &d->arch.arch_vmx.cpu_state); + /* + * The guest CR3 must be pointing to the guest physical. + */ + if ( !VALID_MFN(mfn = phys_to_machine_mapping( + d->arch.arch_vmx.cpu_cr3 >> PAGE_SHIFT)) || + !get_page(pfn_to_page(mfn), d->domain) ) + { + VMX_DBG_LOG(DBG_LEVEL_VMMU, "Invalid CR3 value = %lx", + d->arch.arch_vmx.cpu_cr3); + domain_crash_synchronous(); /* need to take a clean path */ + } + old_base_mfn = pagetable_val(d->arch.guest_table) >> PAGE_SHIFT; + if (old_base_mfn) + put_page(pfn_to_page(old_base_mfn)); + + /* + * Now arch.guest_table points to machine physical. + */ + d->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT); + update_pagetables(d); + + VMX_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx", + (unsigned long) (mfn << PAGE_SHIFT)); + + __vmwrite(GUEST_CR3, pagetable_val(d->arch.shadow_table)); + /* + * arch->shadow_table should hold the next CR3 for shadow + */ + VMX_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx", + d->arch.arch_vmx.cpu_cr3, mfn); + } else { + if ((value & X86_CR0_PE) == 0) { + __vmread(GUEST_EIP, &eip); + VMX_DBG_LOG(DBG_LEVEL_1, + "Disabling CR0.PE at %%eip 0x%lx", eip); + if (vmx_assist(d, VMX_ASSIST_INVOKE)) { + set_bit(VMX_CPU_STATE_ASSIST_ENABLED, + &d->arch.arch_vmx.cpu_state); + __vmread(GUEST_EIP, &eip); + VMX_DBG_LOG(DBG_LEVEL_1, + "Transfering control to vmxassist %%eip 0x%lx", eip); + return 0; /* do not update eip! */ + } + } else if (test_bit(VMX_CPU_STATE_ASSIST_ENABLED, + &d->arch.arch_vmx.cpu_state)) { + __vmread(GUEST_EIP, &eip); + VMX_DBG_LOG(DBG_LEVEL_1, + "Enabling CR0.PE at %%eip 0x%lx", eip); + if (vmx_assist(d, VMX_ASSIST_RESTORE)) { + clear_bit(VMX_CPU_STATE_ASSIST_ENABLED, + &d->arch.arch_vmx.cpu_state); + __vmread(GUEST_EIP, &eip); + VMX_DBG_LOG(DBG_LEVEL_1, + "Restoring to %%eip 0x%lx", eip); + return 0; /* do not update eip! */ + } + } + } + return 1; +} + #define CASE_GET_REG(REG, reg) \ case REG_ ## REG: value = regs->reg; break @@ -650,7 +728,6 @@ { unsigned long value; unsigned long old_cr; - unsigned long eip; struct exec_domain *d = current; switch (gp) { @@ -675,80 +752,8 @@ switch(cr) { case 0: { - unsigned long old_base_mfn, mfn; - - /* - * CR0: - * We don't want to lose PE and PG. - */ - __vmwrite(GUEST_CR0, (value | X86_CR0_PE | X86_CR0_PG)); - __vmwrite(CR0_READ_SHADOW, value); - - if (value & (X86_CR0_PE | X86_CR0_PG) && - !test_bit(VMX_CPU_STATE_PG_ENABLED, &d->arch.arch_vmx.cpu_state)) { - /* - * Enable paging - */ - set_bit(VMX_CPU_STATE_PG_ENABLED, &d->arch.arch_vmx.cpu_state); - /* - * The guest CR3 must be pointing to the guest physical. - */ - if ( !VALID_MFN(mfn = phys_to_machine_mapping( - d->arch.arch_vmx.cpu_cr3 >> PAGE_SHIFT)) || - !get_page(pfn_to_page(mfn), d->domain) ) - { - VMX_DBG_LOG(DBG_LEVEL_VMMU, "Invalid CR3 value = %lx", - d->arch.arch_vmx.cpu_cr3); - domain_crash_synchronous(); /* need to take a clean path */ - } - old_base_mfn = pagetable_val(d->arch.guest_table) >> PAGE_SHIFT; - if ( old_base_mfn ) - put_page(pfn_to_page(old_base_mfn)); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |