+ bits |= kFastThreadLocalStorage; // we use %gs for TLS
+
+#define setif(_bits, _bit, _condition) \
+ if (_condition) _bits |= _bit
+
+ setif(bits, kUP, cpus == 1);
+ setif(bits, k64Bit, cpu_mode_is64bit());
+ setif(bits, kSlow, tscFreq <= SLOW_TSC_THRESHOLD);
+
+ setif(bits, kHasAES, cpuid_features() &
+ CPUID_FEATURE_AES);
+ setif(bits, kHasF16C, cpuid_features() &
+ CPUID_FEATURE_F16C);
+ setif(bits, kHasRDRAND, cpuid_features() &
+ CPUID_FEATURE_RDRAND);
+ setif(bits, kHasFMA, cpuid_features() &
+ CPUID_FEATURE_FMA);
+
+ setif(bits, kHasBMI1, cpuid_leaf7_features() &
+ CPUID_LEAF7_FEATURE_BMI1);
+ setif(bits, kHasBMI2, cpuid_leaf7_features() &
+ CPUID_LEAF7_FEATURE_BMI2);
+ /* Do not advertise RTM and HLE if the TSX FORCE ABORT WA is required */
+ if (cpuid_wa_required(CPU_INTEL_TSXFA) & CWA_OFF) {
+ setif(bits, kHasRTM, cpuid_leaf7_features() &
+ CPUID_LEAF7_FEATURE_RTM);
+ setif(bits, kHasHLE, cpuid_leaf7_features() &
+ CPUID_LEAF7_FEATURE_HLE);
+ }
+ setif(bits, kHasAVX2_0, cpuid_leaf7_features() &
+ CPUID_LEAF7_FEATURE_AVX2);
+ setif(bits, kHasRDSEED, cpuid_leaf7_features() &
+ CPUID_LEAF7_FEATURE_RDSEED);
+ setif(bits, kHasADX, cpuid_leaf7_features() &
+ CPUID_LEAF7_FEATURE_ADX);
+
+#if 0 /* The kernel doesn't support MPX or SGX */
+ setif(bits, kHasMPX, cpuid_leaf7_features() &
+ CPUID_LEAF7_FEATURE_MPX);
+ setif(bits, kHasSGX, cpuid_leaf7_features() &
+ CPUID_LEAF7_FEATURE_SGX);
+#endif
+
+ if (ml_fpu_avx512_enabled()) {
+ setif(bits, kHasAVX512F, cpuid_leaf7_features() &
+ CPUID_LEAF7_FEATURE_AVX512F);
+ setif(bits, kHasAVX512CD, cpuid_leaf7_features() &
+ CPUID_LEAF7_FEATURE_AVX512CD);
+ setif(bits, kHasAVX512DQ, cpuid_leaf7_features() &
+ CPUID_LEAF7_FEATURE_AVX512DQ);
+ setif(bits, kHasAVX512BW, cpuid_leaf7_features() &
+ CPUID_LEAF7_FEATURE_AVX512BW);
+ setif(bits, kHasAVX512VL, cpuid_leaf7_features() &
+ CPUID_LEAF7_FEATURE_AVX512VL);
+ setif(bits, kHasAVX512IFMA, cpuid_leaf7_features() &
+ CPUID_LEAF7_FEATURE_AVX512IFMA);
+ setif(bits, kHasAVX512VBMI, cpuid_leaf7_features() &
+ CPUID_LEAF7_FEATURE_AVX512VBMI);
+ setif(bits, kHasVAES, cpuid_leaf7_features() &
+ CPUID_LEAF7_FEATURE_VAES);
+ setif(bits, kHasVPCLMULQDQ, cpuid_leaf7_features() &
+ CPUID_LEAF7_FEATURE_VPCLMULQDQ);
+ setif(bits, kHasAVX512VNNI, cpuid_leaf7_features() &
+ CPUID_LEAF7_FEATURE_AVX512VNNI);
+ setif(bits, kHasAVX512BITALG, cpuid_leaf7_features() &
+ CPUID_LEAF7_FEATURE_AVX512BITALG);
+ setif(bits, kHasAVX512VPOPCNTDQ, cpuid_leaf7_features() &
+ CPUID_LEAF7_FEATURE_AVX512VPCDQ);
+ }
+
+ uint64_t misc_enable = rdmsr64(MSR_IA32_MISC_ENABLE);
+ setif(bits, kHasENFSTRG, (misc_enable & 1ULL) &&
+ (cpuid_leaf7_features() &
+ CPUID_LEAF7_FEATURE_ERMS));
+
+ _cpu_capabilities = bits; // set kernel version for use by drivers etc
+}
+
+/* initialize the approx_time_supported flag and set the approx time to 0.
+ * Called during initial commpage population.
+ */
+static void
+commpage_mach_approximate_time_init(void)
+{
+ char *cp = commPagePtr32;
+ uint8_t supported;