Source file src/vendor/golang.org/x/sys/cpu/cpu_darwin_x86.go
1 // Copyright 2024 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build darwin && amd64 && gc 6 7 package cpu 8 9 // darwinSupportsAVX512 checks Darwin kernel for AVX512 support via sysctl 10 // call (see issue 43089). It also restricts AVX512 support for Darwin to 11 // kernel version 21.3.0 (MacOS 12.2.0) or later (see issue 49233). 12 // 13 // Background: 14 // Darwin implements a special mechanism to economize on thread state when 15 // AVX512 specific registers are not in use. This scheme minimizes state when 16 // preempting threads that haven't yet used any AVX512 instructions, but adds 17 // special requirements to check for AVX512 hardware support at runtime (e.g. 18 // via sysctl call or commpage inspection). See issue 43089 and link below for 19 // full background: 20 // https://github.com/apple-oss-distributions/xnu/blob/xnu-11215.1.10/osfmk/i386/fpu.c#L214-L240 21 // 22 // Additionally, all versions of the Darwin kernel from 19.6.0 through 21.2.0 23 // (corresponding to MacOS 10.15.6 - 12.1) have a bug that can cause corruption 24 // of the AVX512 mask registers (K0-K7) upon signal return. For this reason 25 // AVX512 is considered unsafe to use on Darwin for kernel versions prior to 26 // 21.3.0, where a fix has been confirmed. See issue 49233 for full background. 27 func darwinSupportsAVX512() bool { 28 return darwinSysctlEnabled([]byte("hw.optional.avx512f\x00")) && darwinKernelVersionCheck(21, 3, 0) 29 } 30 31 // Ensure Darwin kernel version is at least major.minor.patch, avoiding dependencies 32 func darwinKernelVersionCheck(major, minor, patch int) bool { 33 var release [256]byte 34 err := darwinOSRelease(&release) 35 if err != nil { 36 return false 37 } 38 39 var mmp [3]int 40 c := 0 41 Loop: 42 for _, b := range release[:] { 43 switch { 44 case b >= '0' && b <= '9': 45 mmp[c] = 10*mmp[c] + int(b-'0') 46 case b == '.': 47 c++ 48 if c > 2 { 49 return false 50 } 51 case b == 0: 52 break Loop 53 default: 54 return false 55 } 56 } 57 if c != 2 { 58 return false 59 } 60 return mmp[0] > major || mmp[0] == major && (mmp[1] > minor || mmp[1] == minor && mmp[2] >= patch) 61 } 62