]> xenbits.xensource.com Git - xen.git/commitdiff
x86/feature: Definitions for Indirect Branch Controls
authorAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 14 Feb 2018 11:43:37 +0000 (12:43 +0100)
committerJan Beulich <jbeulich@suse.com>
Wed, 14 Feb 2018 11:43:37 +0000 (12:43 +0100)
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>
master commit: 0d703a701cc4bc47773986b2796eebd28b1439b5
master date: 2018-01-16 17:45:50 +0000

tools/libxc/xc_cpufeature.h
tools/libxc/xc_cpuid_x86.c
tools/libxl/libxl_cpuid.c
xen/arch/x86/cpu/common.c
xen/arch/x86/spec_ctrl.c
xen/include/asm-x86/cpufeature.h
xen/include/asm-x86/msr-index.h

index c3ddc80ee6ab87ae7b38a65c19aef62782971597..8a3fac07dbb878e67f0a324a9836c93280dc4d3b 100644 (file)
 #define X86_FEATURE_ADX         19 /* ADCX, ADOX instructions */
 #define X86_FEATURE_SMAP        20 /* Supervisor Mode Access Protection */
 
+/* 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 */
index 11fecd5e478d52ce6955738a6dab558355b00fd3..454be0be7e585dd22d70b9290e451f49b4751348 100644 (file)
@@ -368,9 +368,11 @@ static void xc_cpuid_hvm_policy(
                         bitmaskof(X86_FEATURE_ADX)  |
                         bitmaskof(X86_FEATURE_SMAP) |
                         bitmaskof(X86_FEATURE_FSGSBASE));
+            regs[3] &= (bitmaskof(X86_FEATURE_IBRSB) |
+                        bitmaskof(X86_FEATURE_STIBP));
         } else
-            regs[1] = 0;
-        regs[0] = regs[2] = regs[3] = 0;
+            regs[1] = regs[3] = 0;
+        regs[0] = regs[2] = 0;
         break;
 
     case 0x0000000d:
@@ -403,7 +405,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) */
@@ -498,6 +501,7 @@ static void xc_cpuid_pv_policy(
 
     case 0x00000007:
         if ( input[1] == 0 )
+        {
             regs[1] &= (bitmaskof(X86_FEATURE_BMI1) |
                         bitmaskof(X86_FEATURE_HLE)  |
                         bitmaskof(X86_FEATURE_AVX2) |
@@ -507,9 +511,12 @@ static void xc_cpuid_pv_policy(
                         bitmaskof(X86_FEATURE_RDSEED)  |
                         bitmaskof(X86_FEATURE_ADX)  |
                         bitmaskof(X86_FEATURE_FSGSBASE));
+            regs[3] &= (bitmaskof(X86_FEATURE_IBRSB) |
+                        bitmaskof(X86_FEATURE_STIBP));
+        }
         else
-            regs[1] = 0;
-        regs[0] = regs[2] = regs[3] = 0;
+            regs[1] = regs[3] = 0;
+        regs[0] = regs[2] = 0;
         break;
 
     case 0x0000000d:
index c66e912d92e9be3c1a95d1a7c5c389863c2da989..17e9f0f54980251bc68f2d951d87a56456caf70b 100644 (file)
@@ -158,6 +158,8 @@ int libxl_cpuid_parse_config(libxl_cpuid_policy_list *cpuid, const char* str)
         {"de",           0x00000001, NA, CPUID_REG_EDX,  2,  1},
         {"vme",          0x00000001, NA, CPUID_REG_EDX,  1,  1},
         {"fpu",          0x00000001, NA, CPUID_REG_EDX,  0,  1},
+        {"ibrsb",        0x00000007,  0, CPUID_REG_EDX, 26,  1},
+        {"stibp",        0x00000007,  0, CPUID_REG_EDX, 27,  1},
         {"topoext",      0x80000001, NA, CPUID_REG_ECX, 22,  1},
         {"tbm",          0x80000001, NA, CPUID_REG_ECX, 21,  1},
         {"nodeid",       0x80000001, NA, CPUID_REG_ECX, 19,  1},
@@ -187,6 +189,7 @@ int libxl_cpuid_parse_config(libxl_cpuid_policy_list *cpuid, const char* str)
         {"nx",           0x80000001, NA, CPUID_REG_EDX, 20,  1},
         {"syscall",      0x80000001, NA, CPUID_REG_EDX, 11,  1},
         {"procpkg",      0x00000004,  0, CPUID_REG_EAX, 26,  6},
+        {"ibpb",         0x80000008, NA, CPUID_REG_EBX, 12,  1},
         {"apicidsize",   0x80000008, NA, CPUID_REG_ECX, 12,  4},
         {"nc",           0x80000008, NA, CPUID_REG_ECX,  0,  8},
         {"svm_npt",      0x8000000a, NA, CPUID_REG_EDX,  0,  1},
index 0c1eb5fcdf9d9f9680a042f32a2569a39ba08167..dc0bc7626ae844e204f78441e3b6f3670b4d3178 100644 (file)
@@ -212,7 +212,7 @@ static void __init early_cpu_detect(void)
 
 static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
 {
-       u32 tfms, capability, excap, ebx, eax;
+       u32 tfms, capability, excap, ebx, eax, edx, dummy;
 
        /* Get vendor name */
        cpuid(0x00000000, &c->cpuid_level,
@@ -250,9 +250,10 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
                if ( c->extended_cpuid_level >= 0x80000004 )
                        get_model_name(c); /* Default name */
                if ( c->extended_cpuid_level >= 0x80000008 ) {
-                       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;
                }
        }
 
@@ -261,9 +262,9 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c)
 
        /* Intel-defined flags: level 0x00000007 */
        if ( c->cpuid_level >= 0x00000007 ) {
-               u32 dummy;
-               cpuid_count(0x00000007, 0, &dummy, &ebx, &dummy, &dummy);
+               cpuid_count(0x00000007, 0, &dummy, &ebx, &dummy, &edx);
                c->x86_capability[X86_FEATURE_FSGSBASE / 32] = ebx;
+               c->x86_capability[X86_FEATURE_IBRSB / 32] = edx;
        }
 }
 
index 621f4e882b58f225e1e805a8b0f17acc8117a646..f66a2868fdecc58fbbde7e93a2e4ee334f3aee52 100644 (file)
@@ -67,8 +67,25 @@ custom_param("bti", parse_bti);
 
 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 ( boot_cpu_data.extended_cpuid_level >= 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");
index ec9933779f0b3254c79d472b71dc231f4e032528..633c4c5a0c8e5ba9a00e10457d6bb541d0edd11f 100644 (file)
@@ -9,7 +9,7 @@
 #define __ASM_I386_CPUFEATURE_H
 #endif
 
-#define NCAPINTS             /* 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 */
@@ -64,6 +64,9 @@
 #define X86_FEATURE_LFENCE_DISPATCH (3*32+ 0) /* lfence set as Dispatch Serialising */
 #define X86_FEATURE_IND_THUNK_LFENCE (3*32+ 1) /* Use IND_THUNK_LFENCE */
 #define X86_FEATURE_IND_THUNK_JMP   (3*32+ 2) /* Use IND_THUNK_JMP */
+#define X86_FEATURE_XEN_IBPB        (3*32+ 3) /* IBRSB || IBPB */
+#define X86_FEATURE_XEN_IBRS_SET    (3*32+ 4) /* IBRSB && IRBS set in Xen */
+#define X86_FEATURE_XEN_IBRS_CLEAR  (3*32+ 5) /* IBRSB && IBRS clear in Xen */
 #define X86_FEATURE_CONSTANT_TSC (3*32+ 8) /* TSC ticks at a constant rate */
 #define X86_FEATURE_NONSTOP_TSC        (3*32+ 9) /* TSC does not stop in C states */
 #define X86_FEATURE_ARAT       (3*32+ 10) /* Always running APIC timer */
 #define X86_FEATURE_ADX                (7*32+19) /* ADCX, ADOX instructions */
 #define X86_FEATURE_SMAP       (7*32+20) /* Supervisor Mode Access Prevention */
 
+/* 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 */
+
 /* An alias of a feature we know is always going to be present. */
 #define X86_FEATURE_ALWAYS      X86_FEATURE_LM
 
index 6fae144a67d2303432c14fc03b05a14852d54889..ec2be6a1c74a7fd25bcaa6f15acb450a597b9030 100644 (file)
 #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, ULL) << 0)
+#define SPEC_CTRL_STIBP                        (_AC(1, ULL) << 1)
+
+#define MSR_PRED_CMD                   0x00000049
+#define PRED_CMD_IBPB                  (_AC(1, ULL) << 0)
+
 /* Intel MSRs. Some also available on other CPUs */
 #define MSR_IA32_PERFCTR0              0x000000c1
 #define MSR_IA32_A_PERFCTR0            0x000004c1