# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1185525787 -3600
# Node ID f42ca20a1bb31942a5ea25d704be4025bfbe6d44
# Parent 5682f899c7ae7fa945085aaded75cd1220fd8d17
hvm: Clean up CR0 handling.
Upper 32 bits should #GP if set. Lower 32 bits should have reserved
bits silently cleared.
Check Intel VMX MSRs to check for compatibility with our CR0
requirements.
Signed-off-by: Eric E Liu <eric.e.liu@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
xen/arch/x86/hvm/svm/svm.c | 11 +++++++++++
xen/arch/x86/hvm/vmx/vmcs.c | 15 +++++++++++++++
xen/arch/x86/hvm/vmx/vmx.c | 11 +++++++++++
xen/include/asm-x86/hvm/hvm.h | 7 +++++++
4 files changed, 44 insertions(+)
diff -r 5682f899c7ae -r f42ca20a1bb3 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c Fri Jul 27 09:06:58 2007 +0100
+++ b/xen/arch/x86/hvm/svm/svm.c Fri Jul 27 09:43:07 2007 +0100
@@ -1667,6 +1667,17 @@ static int svm_set_cr0(unsigned long val
unsigned long old_base_mfn;
HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx", value);
+
+ if ( (u32)value != value )
+ {
+ HVM_DBG_LOG(DBG_LEVEL_1,
+ "Guest attempts to set upper 32 bits in CR0: %lx",
+ value);
+ svm_inject_exception(v, TRAP_gp_fault, 1, 0);
+ return 0;
+ }
+
+ value &= HVM_CR0_GUEST_RESERVED_BITS;
/* ET is reserved and should be always be 1. */
value |= X86_CR0_ET;
diff -r 5682f899c7ae -r f42ca20a1bb3 xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c Fri Jul 27 09:06:58 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/vmcs.c Fri Jul 27 09:43:07 2007 +0100
@@ -240,8 +240,23 @@ int vmx_cpu_up(void)
{
u32 eax, edx;
int cpu = smp_processor_id();
+ u64 cr0, vmx_cr0_fixed0, vmx_cr0_fixed1;
BUG_ON(!(read_cr4() & X86_CR4_VMXE));
+
+ /*
+ * Ensure the current processor operating mode meets
+ * the requred CRO fixed bits in VMX operation.
+ */
+ cr0 = read_cr0();
+ rdmsrl(MSR_IA32_VMX_CR0_FIXED0, vmx_cr0_fixed0);
+ rdmsrl(MSR_IA32_VMX_CR0_FIXED1, vmx_cr0_fixed1);
+ if ( (~cr0 & vmx_cr0_fixed0) || (cr0 & ~vmx_cr0_fixed1) )
+ {
+ printk("CPU%d: some settings of host CR0 are "
+ "not allowed in VMX operation.\n", cpu);
+ return 0;
+ }
rdmsr(IA32_FEATURE_CONTROL_MSR, eax, edx);
diff -r 5682f899c7ae -r f42ca20a1bb3 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c Fri Jul 27 09:06:58 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c Fri Jul 27 09:43:07 2007 +0100
@@ -2200,6 +2200,17 @@ static int vmx_set_cr0(unsigned long val
HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx", value);
+ if ( (u32)value != value )
+ {
+ HVM_DBG_LOG(DBG_LEVEL_1,
+ "Guest attempts to set upper 32 bits in CR0: %lx",
+ value);
+ vmx_inject_hw_exception(v, TRAP_gp_fault, 0);
+ return 0;
+ }
+
+ value &= HVM_CR0_GUEST_RESERVED_BITS;
+
/* ET is reserved and should be always be 1. */
value |= X86_CR0_ET;
diff -r 5682f899c7ae -r f42ca20a1bb3 xen/include/asm-x86/hvm/hvm.h
--- a/xen/include/asm-x86/hvm/hvm.h Fri Jul 27 09:06:58 2007 +0100
+++ b/xen/include/asm-x86/hvm/hvm.h Fri Jul 27 09:43:07 2007 +0100
@@ -300,6 +300,13 @@ static inline int hvm_event_injection_fa
return hvm_funcs.event_injection_faulted(v);
}
+/* These reserved bits in lower 32 remain 0 after any load of CR0 */
+#define HVM_CR0_GUEST_RESERVED_BITS \
+ ~(X86_CR0_PE | X86_CR0_MP | X86_CR0_EM | \
+ X86_CR0_TS | X86_CR0_ET | X86_CR0_NE | \
+ X86_CR0_WP | X86_CR0_AM | X86_CR0_NW | \
+ X86_CR0_CD | X86_CR0_PG)
+
/* These bits in CR4 are owned by the host. */
#define HVM_CR4_HOST_MASK (mmu_cr4_features & \
(X86_CR4_VMXE | X86_CR4_PAE | X86_CR4_MCE))
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|