Ensure that AVX512 is not used on macOS

Change-Id: I8aa11f6c64d973ca33324687e8e61d35790cd331
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/74127
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/crypto/cpu_intel.cc b/crypto/cpu_intel.cc
index f8950fb..276610b 100644
--- a/crypto/cpu_intel.cc
+++ b/crypto/cpu_intel.cc
@@ -117,6 +117,22 @@
 #endif
 }
 
+static bool os_supports_avx512(uint64_t xcr0) {
+#if defined(__APPLE__)
+  // The Darwin kernel had a bug where it could corrupt the opmask registers.
+  // See
+  // https://community.intel.com/t5/Software-Tuning-Performance/MacOS-Darwin-kernel-bug-clobbers-AVX-512-opmask-register-state/m-p/1327259
+  // Darwin also does not initially set the XCR0 bits for AVX512, but they are
+  // set if the thread tries to use AVX512 anyway.  Thus, to safely and
+  // consistently use AVX512 on macOS we'd need to check the kernel version as
+  // well as detect AVX512 support using a macOS-specific method.  We don't
+  // bother with this, especially given Apple's transition to arm64.
+  return false;
+#else
+  return (xcr0 & 0xe6) == 0xe6;
+#endif
+}
+
 // handle_cpu_env applies the value from |in| to the CPUID values in |out[0]|
 // and |out[1]|. See the comment in |OPENSSL_cpuid_setup| about this.
 static void handle_cpu_env(uint32_t *out, const char *in) {
@@ -234,7 +250,7 @@
   // See Intel manual, volume 1, sections 15.2 ("Detection of AVX-512 Foundation
   // Instructions") through 15.4 ("Detection of Intel AVX-512 Instruction Groups
   // Operating at 256 and 128-bit Vector Lengths").
-  if ((xcr0 & 0xe6) != 0xe6) {
+  if (!os_supports_avx512(xcr0)) {
     // Without XCR0.111xx11x, no AVX512 feature can be used. This includes ZMM
     // registers, masking, SIMD registers 16-31 (even if accessed as YMM or
     // XMM), and EVEX-coded instructions (even on YMM or XMM). Even if only