x86/hvm: Conditionally leave CPUID Faulting active in HVM context
authorAndrew Cooper <andrew.cooper3@citrix.com>
Mon, 9 Jan 2017 13:42:02 +0000 (13:42 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Tue, 24 Jan 2017 10:38:35 +0000 (10:38 +0000)
If the hardware supports faulting, and the guest has chosen to use it, leave
faulting active in HVM context.

It is more efficient to have hardware convert CPUID to a #GP fault (which we
don't intercept), than to take a VMExit and have Xen re-inject a #GP fault.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
xen/arch/x86/cpu/intel.c
xen/arch/x86/hvm/vmx/vmx.c

index 2e11662f7a72ff86530b8f1cdacd48307c26c202..d0e380c3c612347dfc54b1105bee4f0a83073fc5 100644 (file)
@@ -175,8 +175,9 @@ static void intel_ctxt_switch_levelling(const struct vcpu *next)
                 * generating the maximum full cpuid policy into Xen, at which
                 * this problem will disappear.
                 */
-               set_cpuid_faulting(nextd && is_pv_domain(nextd) &&
-                                  !is_control_domain(nextd));
+               set_cpuid_faulting(nextd && !is_control_domain(nextd) &&
+                                  (is_pv_domain(nextd) ||
+                                   next->arch.cpuid_faulting));
                return;
        }
 
index a5e5ffdcac793cebf933d642a752b2fc743733f1..dcb308cdf7c6a714966f579fa3ead89593cb58c3 100644 (file)
@@ -2866,11 +2866,19 @@ static int vmx_msr_write_intercept(unsigned int msr, uint64_t msr_content)
         break;
 
     case MSR_INTEL_MISC_FEATURES_ENABLES:
+    {
+        bool old_cpuid_faulting = v->arch.cpuid_faulting;
+
         if ( msr_content & ~MSR_MISC_FEATURES_CPUID_FAULTING )
             goto gp_fault;
-        v->arch.cpuid_faulting =
-            !!(msr_content & MSR_MISC_FEATURES_CPUID_FAULTING);
+
+        v->arch.cpuid_faulting = msr_content & MSR_MISC_FEATURES_CPUID_FAULTING;
+
+        if ( cpu_has_cpuid_faulting &&
+             (old_cpuid_faulting ^ v->arch.cpuid_faulting) )
+            ctxt_switch_levelling(v);
         break;
+    }
 
     default:
         if ( passive_domain_do_wrmsr(msr, msr_content) )