# Commit 0d703a701cc4bc47773986b2796eebd28b1439b5
# Date 2018-01-16 17:45:50 +0000
# Author Andrew Cooper <andrew.cooper3@citrix.com>
# Committer Andrew Cooper <andrew.cooper3@citrix.com>
x86/feature: Definitions for Indirect Branch Controls

Contemporary processors are gaining Indirect Branch Controls via microcode
updates.  Intel are introducing one bit to indicate IBRS and IBPB support, and
a second bit for STIBP.  AMD are introducing IBPB only, so enumerate it with a
separate bit.

Furthermore, depending on compiler and microcode availability, we may want to
run Xen with IBRS set, or clear.

To use these facilities, we synthesise separate IBRS and IBPB bits for
internal use.  A lot of infrastructure is required before these features are
safe to offer to guests.

This is part of XSA-254.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Wei Liu <wei.liu2@citrix.com>

--- a/tools/libxc/xc_cpufeature.h
+++ b/tools/libxc/xc_cpufeature.h
@@ -121,4 +121,11 @@
 #define X86_FEATURE_TBM         (6*32+21) /* trailing bit manipulations */
 #define X86_FEATURE_TOPOEXT     (6*32+22) /* topology extensions CPUID leafs */
 
+/* AMD-defined CPU features, CPUID level 0x80000008, ebx */
+#define X86_FEATURE_IBPB        12 /* IBPB support only (no IBRS, used by AMD) */
+
+/* Intel-defined CPU features, CPUID level 0x00000007:0 (edx) */
+#define X86_FEATURE_IBRSB       26 /* IBRS and IBPB support (used by Intel) */
+#define X86_FEATURE_STIBP       27 /* STIBP */
+
 #endif /* __LIBXC_CPUFEATURE_H */
--- a/tools/libxc/xc_cpuid_x86.c
+++ b/tools/libxc/xc_cpuid_x86.c
@@ -225,6 +225,15 @@ static void xc_cpuid_hvm_policy(
             clear_bit(X86_FEATURE_PAE, regs[3]);
         break;
 
+    case 7:
+        if ( input[1] == 0 )
+            regs[3] &= (bitmaskof(X86_FEATURE_IBRSB) |
+                        bitmaskof(X86_FEATURE_STIBP));
+        else
+            regs[3] = 0;
+        regs[0] = regs[1] = regs[2] = 0;
+        break;
+
     case 0x80000000:
         if ( regs[0] > DEF_MAX_EXT )
             regs[0] = DEF_MAX_EXT;
@@ -246,7 +255,8 @@ static void xc_cpuid_hvm_policy(
 
     case 0x80000008:
         regs[0] &= 0x0000ffffu;
-        regs[1] = regs[3] = 0;
+        regs[3] &= bitmaskof(X86_FEATURE_IBPB);
+        regs[1] = 0;
         break;
 
     case 0x00000002: /* Intel cache info (dumped by AMD policy) */
@@ -322,6 +332,16 @@ static void xc_cpuid_pv_policy(
         clear_bit(X86_FEATURE_XSAVE, regs[2]);
         set_bit(X86_FEATURE_HYPERVISOR, regs[2]);
         break;
+
+    case 7:
+        if ( input[1] == 0 )
+            regs[3] &= (bitmaskof(X86_FEATURE_IBRSB) |
+                        bitmaskof(X86_FEATURE_STIBP));
+        else
+            regs[3] = 0;
+        regs[0] = regs[1] = regs[2] = 0;
+        break;
+
     case 0x80000001:
         if ( !guest_64bit )
         {
@@ -346,7 +366,7 @@ static void xc_cpuid_pv_policy(
         clear_bit(X86_FEATURE_NODEID_MSR, regs[2]);
         clear_bit(X86_FEATURE_TOPOEXT, regs[2]);
         break;
-    case 7:
+
     case 0xd: /* XSAVE */
     case 5: /* MONITOR/MWAIT */
     case 0xa: /* Architectural Performance Monitor Features */
@@ -454,10 +474,13 @@ int xc_cpuid_apply_policy(int xc, domid_
         }
 
         input[0]++;
-        input[1] = (input[0] == 4) ? 0 : XEN_CPUID_INPUT_UNUSED;
         if ( !(input[0] & 0x80000000u) && (input[0] > base_max ) )
             input[0] = 0x80000000u;
 
+        input[1] = XEN_CPUID_INPUT_UNUSED;
+        if ( (input[0] == 4) || (input[0] == 7) )
+            input[1] = 0;
+
         if ( (input[0] & 0x80000000u) && (input[0] > ext_max) )
             break;
     }
--- a/xen/arch/x86/cpu/common.c
+++ b/xen/arch/x86/cpu/common.c
@@ -276,7 +276,7 @@ static void __init early_cpu_detect(void
 
 void __cpuinit generic_identify(struct cpuinfo_x86 * c)
 {
-	u32 tfms, xlvl;
+	u32 tfms, xlvl, eax, ebx, edx, dummy;
 
 	if (have_cpuid_p()) {
 		/* Get vendor name */
@@ -319,16 +319,23 @@ void __cpuinit generic_identify(struct c
 			if ( xlvl >= 0x80000004 )
 				get_model_name(c); /* Default name */
 			if ( xlvl >= 0x80000008 ) {
-				u32 eax = cpuid_eax(0x80000008);
-
+				cpuid(0x80000008, &eax, &ebx, &dummy, &dummy);
 				paddr_bits = eax & 0xff;
 				hap_paddr_bits = ((eax >> 16) & 0xff) ?: paddr_bits;
+				c->x86_capability[X86_FEATURE_IBPB / 32] = ebx;
 			}
 		}
 	}
 
 	early_intel_workaround(c);
 
+	/* Intel-defined flags: level 0x00000007 */
+	if ( c->cpuid_level >= 0x00000007 ) {
+		cpuid_count(0x00000007, 0, &dummy, &ebx, &dummy, &edx);
+		c->x86_capability[X86_FEATURE_FSGSBASE / 32] = ebx;
+		c->x86_capability[X86_FEATURE_IBRSB / 32] = edx;
+	}
+
 #ifdef CONFIG_X86_HT
 	phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
 #endif
--- a/xen/arch/x86/spec_ctrl.c
+++ b/xen/arch/x86/spec_ctrl.c
@@ -31,8 +31,25 @@ enum ind_thunk {
 
 static void __init print_details(enum ind_thunk thunk)
 {
+    unsigned int _7d0 = 0, e8b = 0, tmp;
+
+    /* Collect diagnostics about available mitigations. */
+    if ( boot_cpu_data.cpuid_level >= 7 )
+        cpuid_count(7, 0, &tmp, &tmp, &tmp, &_7d0);
+    if ( cpuid_eax(0x80000000) >= 0x80000008 )
+        cpuid(0x80000008, &tmp, &e8b, &tmp, &tmp);
+
     printk(XENLOG_DEBUG "Speculative mitigation facilities:\n");
 
+    /* Hardware features which pertain to speculative mitigations. */
+    if ( (_7d0 & (cpufeat_mask(X86_FEATURE_IBRSB) |
+                  cpufeat_mask(X86_FEATURE_STIBP))) ||
+         (e8b & cpufeat_mask(X86_FEATURE_IBPB)) )
+        printk(XENLOG_DEBUG "  Hardware features:%s%s%s\n",
+               (_7d0 & cpufeat_mask(X86_FEATURE_IBRSB)) ? " IBRS/IBPB" : "",
+               (_7d0 & cpufeat_mask(X86_FEATURE_STIBP)) ? " STIBP"     : "",
+               (e8b  & cpufeat_mask(X86_FEATURE_IBPB))  ? " IBPB"      : "");
+
     /* Compiled-in support which pertains to BTI mitigations. */
 #ifdef CONFIG_INDIRECT_THUNK
     printk(XENLOG_DEBUG "  Compiled-in support: INDIRECT_THUNK\n");
--- a/xen/arch/x86/sysctl.c
+++ b/xen/arch/x86/sysctl.c
@@ -68,7 +68,8 @@ long arch_do_sysctl(
         pi->free_pages = avail_domheap_pages();
         pi->scrub_pages = 0;
         pi->cpu_khz = cpu_khz;
-        memcpy(pi->hw_cap, boot_cpu_data.x86_capability, NCAPINTS*4);
+        memcpy(pi->hw_cap, boot_cpu_data.x86_capability,
+               min(sizeof(pi->hw_cap), sizeof(boot_cpu_data.x86_capability)));
         if ( hvm_enabled )
             pi->capabilities |= XEN_SYSCTL_PHYSCAP_hvm;
         if ( iommu_enabled )
--- a/xen/include/asm-x86/cpufeature.h
+++ b/xen/include/asm-x86/cpufeature.h
@@ -9,7 +9,7 @@
 
 #include <xen/bitops.h>
 
-#define NCAPINTS	7	/* N 32-bit words worth of info */
+#define NCAPINTS	10	/* N 32-bit words worth of info */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */
 #define X86_FEATURE_FPU		(0*32+ 0) /* Onboard FPU */
@@ -135,8 +135,19 @@
 #define X86_FEATURE_TBM         (6*32+21) /* trailing bit manipulations */
 #define X86_FEATURE_TOPOEXT     (6*32+22) /* topology extensions CPUID leafs */
 
+/* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 7 */
+#define X86_FEATURE_FSGSBASE	(7*32+ 0) /* {RD,WR}{FS,GS}BASE instructions */
+
+/* AMD-defined CPU features, CPUID level 0x80000008.ebx, word 8 */
+#define X86_FEATURE_IBPB	(8*32+12) /* IBPB support only (no IBRS, used by AMD) */
+
+/* Intel-defined CPU features, CPUID level 0x00000007:0.edx, word 9 */
+#define X86_FEATURE_IBRSB	(9*32+26) /* IBRS and IBPB support (used by Intel) */
+#define X86_FEATURE_STIBP	(9*32+27) /* STIBP */
+
 #define cpu_has(c, bit)		test_bit(bit, (c)->x86_capability)
 #define boot_cpu_has(bit)	test_bit(bit, boot_cpu_data.x86_capability)
+#define cpufeat_mask(idx)	(1u << ((idx) & 31))
 
 #define CPUID_MWAIT_LEAF                5
 #define CPUID5_ECX_EXTENSIONS_SUPPORTED 0x1
--- a/xen/include/asm-x86/msr-index.h
+++ b/xen/include/asm-x86/msr-index.h
@@ -31,6 +31,14 @@
 #define EFER_LMSLE		(1<<_EFER_LMSLE)
 #define EFER_FFXSE		(1<<_EFER_FFXSE)
 
+/* Speculation Controls. */
+#define MSR_SPEC_CTRL			0x00000048
+#define SPEC_CTRL_IBRS			(_AC(1, UL) << 0)
+#define SPEC_CTRL_STIBP			(_AC(1, UL) << 1)
+
+#define MSR_PRED_CMD			0x00000049
+#define PRED_CMD_IBPB			(_AC(1, UL) << 0)
+
 /* Intel MSRs. Some also available on other CPUs */
 #define MSR_IA32_PERFCTR0		0x000000c1
 #define MSR_IA32_PERFCTR1		0x000000c2
