aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Hand <steven@xensource.com>2006-12-15 11:47:24 +0000
committerSteven Hand <steven@xensource.com>2006-12-15 11:47:24 +0000
commitd42281a82c070968e119e898aaf75c267ff0a018 (patch)
tree70de58ba992467ecaca37615d007c0a1f6978f5e
parent5bb62448a55feb4bfd30755ea59bf8d6f2e3704d (diff)
downloadxen-d42281a82c070968e119e898aaf75c267ff0a018.tar.gz
xen-d42281a82c070968e119e898aaf75c267ff0a018.tar.bz2
xen-d42281a82c070968e119e898aaf75c267ff0a018.zip
Clean-up hvm/shadow interaction around cr3 updates.
Signed-off-by: Steven Hand <steven@xensource.com>
-rw-r--r--xen/arch/x86/hvm/hvm.c6
-rw-r--r--xen/arch/x86/hvm/svm/svm.c12
-rw-r--r--xen/arch/x86/hvm/vmx/vmcs.c6
-rw-r--r--xen/arch/x86/hvm/vmx/vmx.c28
-rw-r--r--xen/arch/x86/mm/shadow/common.c4
-rw-r--r--xen/arch/x86/mm/shadow/multi.c6
-rw-r--r--xen/include/asm-x86/hvm/hvm.h7
7 files changed, 43 insertions, 26 deletions
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 7c3d47899b..a4c66ff91a 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -536,6 +536,12 @@ void hvm_do_hypercall(struct cpu_user_regs *pregs)
#endif /* defined(__x86_64__) */
+void hvm_update_guest_cr3(struct vcpu *v, unsigned long guest_cr3)
+{
+ v->arch.hvm_vcpu.hw_cr3 = guest_cr3;
+ hvm_funcs.update_guest_cr3(v);
+}
+
/* Initialise a hypercall transfer page for a VMX domain using
paravirtualised drivers. */
void hvm_hypercall_page_initialise(struct domain *d,
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index 5d19ae536c..55b631660e 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -498,6 +498,11 @@ void svm_update_host_cr3(struct vcpu *v)
/* SVM doesn't have a HOST_CR3 equivalent to update. */
}
+void svm_update_guest_cr3(struct vcpu *v)
+{
+ v->arch.hvm_svm.vmcb->cr3 = v->arch.hvm_vcpu.hw_cr3;
+}
+
unsigned long svm_get_ctrl_reg(struct vcpu *v, unsigned int num)
{
switch ( num )
@@ -883,6 +888,7 @@ int start_svm(void)
hvm_funcs.get_segment_register = svm_get_segment_register;
hvm_funcs.update_host_cr3 = svm_update_host_cr3;
+ hvm_funcs.update_guest_cr3 = svm_update_guest_cr3;
hvm_funcs.stts = svm_stts;
hvm_funcs.set_tsc_offset = svm_set_tsc_offset;
@@ -1608,7 +1614,6 @@ static int svm_set_cr0(unsigned long value)
HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx",
(unsigned long) (mfn << PAGE_SHIFT));
- vmcb->cr3 = v->arch.hvm_vcpu.hw_cr3;
set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
}
@@ -1630,7 +1635,6 @@ static int svm_set_cr0(unsigned long value)
return 0;
}
shadow_update_paging_modes(v);
- vmcb->cr3 = v->arch.hvm_vcpu.hw_cr3;
set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
}
else if ( (value & (X86_CR0_PE | X86_CR0_PG)) == X86_CR0_PE )
@@ -1642,7 +1646,6 @@ static int svm_set_cr0(unsigned long value)
}
/* we should take care of this kind of situation */
shadow_update_paging_modes(v);
- vmcb->cr3 = v->arch.hvm_vcpu.hw_cr3;
set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
}
@@ -1768,7 +1771,6 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
v->arch.hvm_svm.cpu_cr3 = value;
update_cr3(v);
- vmcb->cr3 = v->arch.hvm_vcpu.hw_cr3;
HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx", value);
}
break;
@@ -1804,8 +1806,6 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx",
(unsigned long) (mfn << PAGE_SHIFT));
- vmcb->cr3 = v->arch.hvm_vcpu.hw_cr3;
-
HVM_DBG_LOG(DBG_LEVEL_VMMU,
"Update CR3 value = %lx, mfn = %lx",
v->arch.hvm_svm.cpu_cr3, mfn);
diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c
index cee05bc552..8355c6e54d 100644
--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -430,11 +430,9 @@ static void construct_vmcs(struct vcpu *v)
__vmwrite(GUEST_TR_BASE, 0);
__vmwrite(GUEST_TR_LIMIT, 0xff);
- shadow_update_paging_modes(v);
- __vmwrite(GUEST_CR3, v->arch.hvm_vcpu.hw_cr3);
- __vmwrite(HOST_CR3, v->arch.cr3);
-
vmx_vmcs_exit(v);
+
+ shadow_update_paging_modes(v); /* will update HOST & GUEST_CR3 as reqd */
}
int vmx_create_vmcs(struct vcpu *v)
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index aa6e364f6b..c95afe5b83 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -708,13 +708,23 @@ static int vmx_pae_enabled(struct vcpu *v)
return (vmx_paging_enabled(v) && (cr4 & X86_CR4_PAE));
}
-/* Works only for vcpu == current */
static void vmx_update_host_cr3(struct vcpu *v)
{
- ASSERT(v == current);
+ ASSERT( (v == current) || !vcpu_runnable(v) );
+ vmx_vmcs_enter(v);
__vmwrite(HOST_CR3, v->arch.cr3);
+ vmx_vmcs_exit(v);
}
+static void vmx_update_guest_cr3(struct vcpu *v)
+{
+ ASSERT( (v == current) || !vcpu_runnable(v) );
+ vmx_vmcs_enter(v);
+ __vmwrite(GUEST_CR3, v->arch.hvm_vcpu.hw_cr3);
+ vmx_vmcs_exit(v);
+}
+
+
static void vmx_inject_exception(
unsigned int trapnr, int errcode, unsigned long cr2)
{
@@ -747,6 +757,7 @@ static void vmx_setup_hvm_funcs(void)
hvm_funcs.get_segment_register = vmx_get_segment_register;
hvm_funcs.update_host_cr3 = vmx_update_host_cr3;
+ hvm_funcs.update_guest_cr3 = vmx_update_guest_cr3;
hvm_funcs.stts = vmx_stts;
hvm_funcs.set_tsc_offset = vmx_set_tsc_offset;
@@ -1531,7 +1542,6 @@ static int vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c)
__vmwrite(GUEST_LDTR_AR_BYTES, c->ldtr_arbytes.bytes);
shadow_update_paging_modes(v);
- __vmwrite(GUEST_CR3, v->arch.hvm_vcpu.hw_cr3);
return 0;
bad_cr3:
@@ -1689,7 +1699,6 @@ static int vmx_set_cr0(unsigned long value)
HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx",
(unsigned long) (mfn << PAGE_SHIFT));
- __vmwrite(GUEST_CR3, v->arch.hvm_vcpu.hw_cr3);
/*
* arch->shadow_table should hold the next CR3 for shadow
*/
@@ -1761,7 +1770,6 @@ static int vmx_set_cr0(unsigned long value)
__vmwrite(VM_ENTRY_CONTROLS, vm_entry_value);
}
shadow_update_paging_modes(v);
- __vmwrite(GUEST_CR3, v->arch.hvm_vcpu.hw_cr3);
}
return 1;
@@ -1869,9 +1877,7 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
*/
v->arch.hvm_vmx.cpu_cr3 = value;
update_cr3(v);
- HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx",
- value);
- __vmwrite(GUEST_CR3, v->arch.hvm_vcpu.hw_cr3);
+ HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx", value);
}
break;
@@ -1902,13 +1908,11 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx",
(unsigned long) (mfn << PAGE_SHIFT));
- __vmwrite(GUEST_CR3, v->arch.hvm_vcpu.hw_cr3);
-
/*
* arch->shadow_table should hold the next CR3 for shadow
*/
-
- HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx",
+ HVM_DBG_LOG(DBG_LEVEL_VMMU,
+ "Update CR3 value = %lx, mfn = %lx",
v->arch.hvm_vmx.cpu_cr3, mfn);
#endif
}
diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c
index 554fc5b9e1..6dedae37a8 100644
--- a/xen/arch/x86/mm/shadow/common.c
+++ b/xen/arch/x86/mm/shadow/common.c
@@ -2495,7 +2495,9 @@ void sh_update_paging_modes(struct vcpu *v)
{
mfn_t mmfn = shadow_make_monitor_table(v);
v->arch.monitor_table = pagetable_from_mfn(mmfn);
- }
+ make_cr3(v, mfn_x(mmfn));
+ hvm_update_host_cr3(v);
+ }
if ( v->arch.shadow.mode != old_mode )
{
diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c
index 8a83d4de07..0b9ec5512d 100644
--- a/xen/arch/x86/mm/shadow/multi.c
+++ b/xen/arch/x86/mm/shadow/multi.c
@@ -2817,7 +2817,7 @@ static int sh_page_fault(struct vcpu *v,
if ( is_hvm_domain(d) )
hvm_store_cpu_guest_regs(v, regs, NULL);
- SHADOW_PRINTK("emulate: eip=%#lx\n", regs->eip);
+ SHADOW_PRINTK("emulate: eip=%#lx\n", (unsigned long)regs->eip);
emul_ops = shadow_init_emulation(&emul_ctxt, regs);
@@ -3561,10 +3561,10 @@ sh_update_cr3(struct vcpu *v)
ASSERT(is_hvm_domain(d));
#if SHADOW_PAGING_LEVELS == 3
/* 2-on-3 or 3-on-3: Use the PAE shadow l3 table we just fabricated */
- v->arch.hvm_vcpu.hw_cr3 = virt_to_maddr(&v->arch.shadow.l3table);
+ hvm_update_guest_cr3(v, virt_to_maddr(&v->arch.shadow.l3table));
#else
/* 2-on-2 or 4-on-4: Just use the shadow top-level directly */
- v->arch.hvm_vcpu.hw_cr3 = pagetable_get_paddr(v->arch.shadow_table[0]);
+ hvm_update_guest_cr3(v, pagetable_get_paddr(v->arch.shadow_table[0]));
#endif
}
diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
index 13ee040fdb..fb1dac3c46 100644
--- a/xen/include/asm-x86/hvm/hvm.h
+++ b/xen/include/asm-x86/hvm/hvm.h
@@ -103,6 +103,11 @@ struct hvm_function_table {
void (*update_host_cr3)(struct vcpu *v);
/*
+ * Called to inform HVM layer that a guest cr3 has changed
+ */
+ void (*update_guest_cr3)(struct vcpu *v);
+
+ /*
* Update specifics of the guest state:
* 1) TS bit in guest cr0
* 2) TSC offset in guest
@@ -188,6 +193,8 @@ hvm_update_host_cr3(struct vcpu *v)
hvm_funcs.update_host_cr3(v);
}
+void hvm_update_guest_cr3(struct vcpu *v, unsigned long guest_cr3);
+
void hvm_hypercall_page_initialise(struct domain *d,
void *hypercall_page);