]> xenbits.xensource.com Git - xen.git/commitdiff
x86/cpuid: Handling of IBRS/IBPB, STIBP and IBRS for guests
authorAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 14 Feb 2018 10:36:48 +0000 (11:36 +0100)
committerJan Beulich <jbeulich@suse.com>
Wed, 14 Feb 2018 10:36:48 +0000 (11:36 +0100)
Intel specifies IBRS/IBPB (combined, in a single bit) and STIBP as a separate
bit.  AMD specifies IBPB alone in a 3rd bit.

AMD's IBPB is a subset of Intel's combined IBRS/IBPB.  For performance
reasons, administrators might wish to express "IBPB only" even on Intel
hardware, so we allow the AMD bit to be used for this purpose.

The behaviour of STIBP is more complicated.

It is our current understanding that STIBP will be advertised on HT-capable
hardware irrespective of whether HT is enabled, but not advertised on
HT-incapable hardware.  However, for ease of virtualisation, STIBP's
functionality is ignored rather than reserved by microcode/hardware on
HT-incapable hardware.

For guest safety, we treat STIBP as special, always override the toolstack
choice, and always advertise STIBP if IBRS is available.  This removes the
corner case where STIBP is not advertised, but the guest is running on
HT-capable hardware where it does matter.

Finally as a bugfix, update the libxc CPUID logic to understand the e8b
feature leaf, which has the side effect of also offering CLZERO to guests on
applicable hardware.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Wei Liu <wei.liu2@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
master commit: d297b56682e730d598e2529cc6998151d3b6f6f8
master date: 2018-01-26 14:10:21 +0000

tools/libxc/xc_cpuid_x86.c
xen/arch/x86/cpuid.c
xen/arch/x86/domctl.c
xen/include/public/arch-x86/cpufeatureset.h

index 4d30b476365425c24121a980d9b7d7d6e5426959..5c209e4c15670e2f87df1cb178daf0b9f6920cf7 100644 (file)
@@ -576,7 +576,9 @@ static void xc_cpuid_hvm_policy(xc_interface *xch,
 
     case 0x80000008:
         regs[0] &= 0x0000ffffu;
-        regs[1] = regs[3] = 0;
+        regs[1] = info->featureset[featureword_of(X86_FEATURE_CLZERO)];
+        /* regs[2] handled in the per-vendor logic. */
+        regs[3] = 0;
         break;
 
     case 0x00000002: /* Intel cache info (dumped by AMD policy) */
index 7a7c8de4899ad16d01388bbdf3e00fd84b73620b..451952cabe704b6cd1e9ad80122196c654f4b556 100644 (file)
@@ -154,6 +154,16 @@ static void __init calculate_pv_featureset(void)
     __set_bit(X86_FEATURE_X2APIC, pv_featureset);
     __set_bit(X86_FEATURE_CMP_LEGACY, pv_featureset);
 
+    /* On hardware with IBRS/IBPB support, there are further adjustments. */
+    if ( test_bit(X86_FEATURE_IBRSB, pv_featureset) )
+    {
+        /* Offer STIBP unconditionally.  It is a nop on non-HT hardware. */
+        __set_bit(X86_FEATURE_STIBP, pv_featureset);
+
+        /* AMD's IBPB is a subset of IBRS/IBPB. */
+        __set_bit(X86_FEATURE_IBPB, pv_featureset);
+    }
+
     sanitise_featureset(pv_featureset);
 }
 
@@ -210,6 +220,16 @@ static void __init calculate_hvm_featureset(void)
             __clear_bit(X86_FEATURE_XSAVES, hvm_featureset);
     }
 
+    /* On hardware with IBRS/IBPB support, there are further adjustments. */
+    if ( test_bit(X86_FEATURE_IBRSB, hvm_featureset) )
+    {
+        /* Offer STIBP unconditionally.  It is a nop on non-HT hardware. */
+        __set_bit(X86_FEATURE_STIBP, hvm_featureset);
+
+        /* AMD's IBPB is a subset of IBRS/IBPB. */
+        __set_bit(X86_FEATURE_IBPB, hvm_featureset);
+    }
+
     sanitise_featureset(hvm_featureset);
 }
 
index e0b11508cf9f847a2d1ca04c78cdd5e7dd11c13e..60286b594b6675b2715c18fe5242f8853e4392b3 100644 (file)
@@ -49,7 +49,7 @@ static int gdbsx_guest_mem_io(domid_t domid, struct xen_domctl_gdbsx_memio *iop)
 }
 
 static void update_domain_cpuid_info(struct domain *d,
-                                     const xen_domctl_cpuid_t *ctl)
+                                     cpuid_input_t *ctl)
 {
     bool_t call_policy_changed = 0; /* Avoid for_each_vcpu() unnecessarily */
 
@@ -169,6 +169,18 @@ static void update_domain_cpuid_info(struct domain *d,
 
             d->arch.pv_domain.cpuidmasks->_7ab0 = mask;
         }
+
+        /*
+         * Override STIBP to match IBRS.  Guests can safely use STIBP
+         * functionality on non-HT hardware, but can't necesserily protect
+         * themselves from SP2/Spectre/Branch Target Injection if STIBP is
+         * hidden on HT-capable hardware.
+         */
+        if ( ctl->edx & cpufeat_mask(X86_FEATURE_IBRSB) )
+            ctl->edx |= cpufeat_mask(X86_FEATURE_STIBP);
+        else
+            ctl->edx &= ~cpufeat_mask(X86_FEATURE_STIBP);
+
         break;
 
     case 0xd:
@@ -895,16 +907,18 @@ long arch_do_domctl(
         {
             if ( i < MAX_CPUID_INPUT )
                 cpuid->input[0] = XEN_CPUID_INPUT_UNUSED;
+            else
+                cpuid = NULL;
         }
         else if ( i < MAX_CPUID_INPUT )
             *cpuid = *ctl;
         else if ( unused )
-            *unused = *ctl;
+            *(cpuid = unused) = *ctl;
         else
             ret = -ENOENT;
 
-        if ( !ret )
-            update_domain_cpuid_info(d, ctl);
+        if ( !ret && cpuid )
+            update_domain_cpuid_info(d, cpuid);
 
         domain_unpause(d);
         break;
index 4f8cef28aa8cbcec7a714e4e359c0a8c7206c6f1..c5ae781928de0a7dcdefb24ccf2e57df0b8d6253 100644 (file)
@@ -228,7 +228,7 @@ XEN_CPUFEATURE(IBPB,          8*32+12) /*   IBPB support only (no IBRS, used by
 
 /* Intel-defined CPU features, CPUID level 0x00000007:0.edx, word 9 */
 XEN_CPUFEATURE(IBRSB,         9*32+26) /*   IBRS and IBPB support (used by Intel) */
-XEN_CPUFEATURE(STIBP,         9*32+27) /*   STIBP */
+XEN_CPUFEATURE(STIBP,         9*32+27) /*!  STIBP */
 
 #endif /* XEN_CPUFEATURE */