ChangeSet 1.1577, 2005/05/28 09:53:55+01:00, arun.sharma@xxxxxxxxx
[PATCH] vmx-worldswitch-1-to-1.patch
Fix VMX world switch to use 1:1 page tables when the guest has paging
disabled. Also do a printk instead of VMX_DBG_LOG() anytime we crash
a domain.
Signed-off-by: Arun Sharma <arun.sharma@xxxxxxxxx>
tools/libxc/xc_vmx_build.c | 2 -
xen/arch/x86/domain.c | 1
xen/arch/x86/vmx.c | 58 ++++++++++++++++++++---------------------
xen/arch/x86/vmx_io.c | 2 -
xen/arch/x86/vmx_platform.c | 10 ++++---
xen/arch/x86/vmx_vmcs.c | 2 -
xen/arch/x86/x86_32/traps.c | 8 ++++-
xen/include/asm-x86/shadow.h | 7 +++-
xen/include/asm-x86/vmx.h | 11 +++++++
xen/include/asm-x86/vmx_vmcs.h | 1
10 files changed, 61 insertions(+), 41 deletions(-)
diff -Nru a/tools/libxc/xc_vmx_build.c b/tools/libxc/xc_vmx_build.c
--- a/tools/libxc/xc_vmx_build.c 2005-05-28 05:03:50 -04:00
+++ b/tools/libxc/xc_vmx_build.c 2005-05-28 05:03:50 -04:00
@@ -10,7 +10,7 @@
#include <zlib.h>
#include "linux_boot_params.h"
-#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
+#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER)
#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
diff -Nru a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c 2005-05-28 05:03:50 -04:00
+++ b/xen/arch/x86/domain.c 2005-05-28 05:03:50 -04:00
@@ -339,7 +339,6 @@
}
ed->arch.schedule_tail = arch_vmx_do_launch;
- clear_bit(VMX_CPU_STATE_PG_ENABLED, &ed->arch.arch_vmx.cpu_state);
#if defined (__i386)
ed->arch.arch_vmx.vmx_platform.real_mode_data =
diff -Nru a/xen/arch/x86/vmx.c b/xen/arch/x86/vmx.c
--- a/xen/arch/x86/vmx.c 2005-05-28 05:03:50 -04:00
+++ b/xen/arch/x86/vmx.c 2005-05-28 05:03:50 -04:00
@@ -122,7 +122,6 @@
static int vmx_do_page_fault(unsigned long va, struct cpu_user_regs *regs)
{
- struct exec_domain *ed = current;
unsigned long eip;
l1_pgentry_t gpte;
unsigned long gpa; /* FIXME: PAE */
@@ -137,15 +136,8 @@
}
#endif
- /*
- * If vpagetable is zero, then we are still emulating 1:1 page tables,
- * and we should have never gotten here.
- */
- if ( !test_bit(VMX_CPU_STATE_PG_ENABLED, &ed->arch.arch_vmx.cpu_state) )
- {
- printk("vmx_do_page_fault while running on 1:1 page table\n");
- return 0;
- }
+ if (!vmx_paging_enabled(current))
+ handle_mmio(va, va);
gpte = gva_to_gpte(va);
if (!(l1e_get_flags(gpte) & _PAGE_PRESENT) )
@@ -399,7 +391,7 @@
vio = (vcpu_iodata_t *) d->arch.arch_vmx.vmx_platform.shared_page_va;
if (vio == 0) {
- VMX_DBG_LOG(DBG_LEVEL_1, "bad shared page: %lx", (unsigned long) vio);
+ printk("bad shared page: %lx", (unsigned long) vio);
domain_crash_synchronous();
}
p = &vio->vp_ioreq;
@@ -423,7 +415,10 @@
laddr = (p->dir == IOREQ_WRITE) ? regs->esi : regs->edi;
}
p->pdata_valid = 1;
- p->u.pdata = (void *) gva_to_gpa(laddr);
+
+ p->u.data = laddr;
+ if (vmx_paging_enabled(d))
+ p->u.pdata = (void *) gva_to_gpa(p->u.data);
p->df = (eflags & X86_EFLAGS_DF) ? 1 : 0;
if (test_bit(5, &exit_qualification)) /* "rep" prefix */
@@ -481,7 +476,7 @@
return 0;
}
- mfn = phys_to_machine_mapping(l1e_get_pfn(gva_to_gpte(laddr)));
+ mfn = phys_to_machine_mapping(laddr >> PAGE_SHIFT);
addr = map_domain_mem((mfn << PAGE_SHIFT) | (laddr & ~PAGE_MASK));
if (dir == COPY_IN)
@@ -570,6 +565,12 @@
error |= __vmwrite(CR0_READ_SHADOW, c->cr0);
+ if (!vmx_paging_enabled(d)) {
+ VMX_DBG_LOG(DBG_LEVEL_VMMU, "switching to vmxassist. use phys table");
+ __vmwrite(GUEST_CR3, pagetable_val(d->domain->arch.phys_table));
+ goto skip_cr3;
+ }
+
if (c->cr3 == d->arch.arch_vmx.cpu_cr3) {
/*
* This is simple TLB flush, implying the guest has
@@ -578,7 +579,7 @@
*/
mfn = phys_to_machine_mapping(c->cr3 >> PAGE_SHIFT);
if ((mfn << PAGE_SHIFT) != pagetable_val(d->arch.guest_table)) {
- VMX_DBG_LOG(DBG_LEVEL_VMMU, "Invalid CR3 value=%lx", c->cr3);
+ printk("Invalid CR3 value=%lx", c->cr3);
domain_crash_synchronous();
return 0;
}
@@ -590,7 +591,7 @@
*/
VMX_DBG_LOG(DBG_LEVEL_VMMU, "CR3 c->cr3 = %lx", c->cr3);
if ((c->cr3 >> PAGE_SHIFT) > d->domain->max_pages) {
- VMX_DBG_LOG(DBG_LEVEL_VMMU, "Invalid CR3 value=%lx", c->cr3);
+ printk("Invalid CR3 value=%lx", c->cr3);
domain_crash_synchronous();
return 0;
}
@@ -605,6 +606,8 @@
__vmwrite(GUEST_CR3, pagetable_val(d->arch.shadow_table));
}
+skip_cr3:
+
error |= __vmread(CR4_READ_SHADOW, &old_cr4);
error |= __vmwrite(GUEST_CR4, (c->cr4 | X86_CR4_VMXE));
error |= __vmwrite(CR4_READ_SHADOW, c->cr4);
@@ -731,18 +734,18 @@
struct exec_domain *d = current;
unsigned long old_base_mfn, mfn;
unsigned long eip;
+ int paging_enabled;
/*
* CR0: We don't want to lose PE and PG.
*/
+ paging_enabled = vmx_paging_enabled(d);
__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);
+ VMX_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx\n", value);
+ if ((value & X86_CR0_PE) && (value & X86_CR0_PG)
+ && !paging_enabled) {
/*
* The guest CR3 must be pointing to the guest physical.
*/
@@ -750,8 +753,7 @@
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);
+ printk("Invalid CR3 value = %lx", d->arch.arch_vmx.cpu_cr3);
domain_crash_synchronous(); /* need to take a clean path */
}
old_base_mfn = pagetable_get_pfn(d->arch.guest_table);
@@ -776,8 +778,7 @@
} 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);
+ VMX_DBG_LOG(DBG_LEVEL_1, "Disabling CR0.PE at %%eip 0x%lx\n", eip);
if (vmx_assist(d, VMX_ASSIST_INVOKE)) {
set_bit(VMX_CPU_STATE_ASSIST_ENABLED,
&d->arch.arch_vmx.cpu_state);
@@ -838,7 +839,6 @@
switch(cr) {
case 0:
{
- __vmwrite(CR0_READ_SHADOW, value);
return vmx_set_cr0(value);
}
case 3:
@@ -848,7 +848,7 @@
/*
* If paging is not enabled yet, simply copy the value to CR3.
*/
- if (!test_bit(VMX_CPU_STATE_PG_ENABLED, &d->arch.arch_vmx.cpu_state)) {
+ if (!vmx_paging_enabled(d)) {
d->arch.arch_vmx.cpu_cr3 = value;
break;
}
@@ -876,8 +876,7 @@
!VALID_MFN(mfn = phys_to_machine_mapping(value >>
PAGE_SHIFT)) ||
!get_page(pfn_to_page(mfn), d->domain) )
{
- VMX_DBG_LOG(DBG_LEVEL_VMMU,
- "Invalid CR3 value=%lx", value);
+ printk("Invalid CR3 value=%lx", value);
domain_crash_synchronous(); /* need to take a clean path */
}
old_base_mfn = pagetable_get_pfn(d->arch.guest_table);
@@ -1133,6 +1132,7 @@
VMX_DBG_LOG(DBG_LEVEL_0, "exit reason = %x", exit_reason);
if (exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) {
+ printk("Failed vm entry\n");
domain_crash_synchronous();
return;
}
diff -Nru a/xen/arch/x86/vmx_io.c b/xen/arch/x86/vmx_io.c
--- a/xen/arch/x86/vmx_io.c 2005-05-28 05:03:50 -04:00
+++ b/xen/arch/x86/vmx_io.c 2005-05-28 05:03:50 -04:00
@@ -465,7 +465,7 @@
void vmx_do_resume(struct exec_domain *d)
{
vmx_stts();
- if ( test_bit(VMX_CPU_STATE_PG_ENABLED, &d->arch.arch_vmx.cpu_state) )
+ if ( vmx_paging_enabled(d) )
__vmwrite(GUEST_CR3, pagetable_val(d->arch.shadow_table));
else
// paging is not enabled in the guest
diff -Nru a/xen/arch/x86/vmx_platform.c b/xen/arch/x86/vmx_platform.c
--- a/xen/arch/x86/vmx_platform.c 2005-05-28 05:03:50 -04:00
+++ b/xen/arch/x86/vmx_platform.c 2005-05-28 05:03:50 -04:00
@@ -418,8 +418,12 @@
}
if ((guest_eip & PAGE_MASK) == ((guest_eip + inst_len) & PAGE_MASK)) {
- gpte = gva_to_gpte(guest_eip);
- mfn = phys_to_machine_mapping(l1e_get_pfn(gpte));
+ if (vmx_paging_enabled(current)) {
+ gpte = gva_to_gpte(guest_eip);
+ mfn = phys_to_machine_mapping(l1e_get_pfn(gpte));
+ } else {
+ mfn = phys_to_machine_mapping(guest_eip >> PAGE_SHIFT);
+ }
ma = (mfn << PAGE_SHIFT) | (guest_eip & (PAGE_SIZE - 1));
inst_start = (unsigned char *)map_domain_mem(ma);
@@ -508,7 +512,7 @@
} else
p->count = 1;
- if (pvalid)
+ if ((pvalid) && vmx_paging_enabled(current))
p->u.pdata = (void *) gva_to_gpa(p->u.data);
#if 0
diff -Nru a/xen/arch/x86/vmx_vmcs.c b/xen/arch/x86/vmx_vmcs.c
--- a/xen/arch/x86/vmx_vmcs.c 2005-05-28 05:03:50 -04:00
+++ b/xen/arch/x86/vmx_vmcs.c 2005-05-28 05:03:50 -04:00
@@ -291,7 +291,7 @@
/* Initally PG, PE are not set*/
shadow_cr = host_env->cr0;
- shadow_cr &= ~(X86_CR0_PE | X86_CR0_PG);
+ shadow_cr &= ~X86_CR0_PG;
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|