[HVM][SVM] Turn off long mode (EFER.LMA) when CR0.PG==0.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Tue, 7 Nov 2006 10:19:20 +0000 (10:19 +0000)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Tue, 7 Nov 2006 10:19:20 +0000 (10:19 +0000)
Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/hvm/svm/svm.c
xen/include/asm-x86/hvm/svm/vmcb.h

index 92b70c8f17be779fa077dfeb1595128f96b2967f..ef9a9f1aaa68271cc067ae0295dd6b203637f92f 100644 (file)
@@ -264,6 +264,11 @@ static int svm_pae_enabled(struct vcpu *v)
     return (cr4 & X86_CR4_PAE);
 }
 
+static int svm_long_mode_enabled(struct vcpu *v)
+{
+    return test_bit(SVM_CPU_STATE_LMA_ENABLED, &v->arch.hvm_svm.cpu_state);
+}
+
 #define IS_CANO_ADDRESS(add) 1
 
 static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
@@ -369,7 +374,7 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
 
     case MSR_FS_BASE:
     case MSR_GS_BASE:
-        if (!(SVM_LONG_GUEST(vc)))
+        if ( !svm_long_mode_enabled(vc) )
             domain_crash_synchronous();
 
         if (!IS_CANO_ADDRESS(msr_content))
@@ -682,11 +687,6 @@ static void svm_load_cpu_guest_regs(
     svm_load_cpu_user_regs(v, regs);
 }
 
-int svm_long_mode_enabled(struct vcpu *v)
-{
-    return SVM_LONG_GUEST(v);
-}
-
 static void arch_svm_do_launch(struct vcpu *v) 
 {
     svm_do_launch(v);
@@ -1487,9 +1487,8 @@ static int svm_set_cr0(unsigned long value)
         {
             /* Here the PAE is should to be opened */
             HVM_DBG_LOG(DBG_LEVEL_1, "Enable the Long mode\n");
-            set_bit(SVM_CPU_STATE_LMA_ENABLED,
-                    &v->arch.hvm_svm.cpu_state);
-            vmcb->efer |= (EFER_LMA | EFER_LME);
+            set_bit(SVM_CPU_STATE_LMA_ENABLED, &v->arch.hvm_svm.cpu_state);
+            vmcb->efer |= EFER_LMA;
         }
 #endif  /* __x86_64__ */
 
@@ -1530,6 +1529,11 @@ static int svm_set_cr0(unsigned long value)
     }
     else if ( (value & (X86_CR0_PE | X86_CR0_PG)) == X86_CR0_PE )
     {
+        if ( svm_long_mode_enabled(v) )
+        {
+            vmcb->efer &= ~EFER_LMA;
+            clear_bit(SVM_CPU_STATE_LMA_ENABLED, &v->arch.hvm_svm.cpu_state);
+        }
         /* we should take care of this kind of situation */
         shadow_update_paging_modes(v);
         vmcb->cr3 = v->arch.hvm_vcpu.hw_cr3;
index d44fbe33a550a9c081633b8d1111d4b7badf6bdb..2d6a4ed0f3ea643161944e4f6c68ba36c478cc77 100644 (file)
@@ -310,10 +310,6 @@ enum {
     SVM_CPU_STATE_LMA_ENABLED,
     SVM_CPU_STATE_ASSIST_ENABLED,
 };  
-    
-#define SVM_LONG_GUEST(ed)    \
-  (test_bit(SVM_CPU_STATE_LMA_ENABLED, &ed->arch.hvm_svm.cpu_state))
-
 
 /* 
  * Attribute for segment selector. This is a copy of bit 40:47 & 52:55 of the