1//go:build gc
2
3package platform
4
5import "runtime"
6
7// CpuFeatures exposes the capabilities for this CPU, queried via the Has, HasExtra methods.
8var CpuFeatures = loadCpuFeatureFlags()
9
10// cpuFeatureFlags implements CpuFeatureFlags interface.
11type cpuFeatureFlags struct {
12 isar0 uint64
13 isar1 uint64
14}
15
16// implemented in cpuid_arm64.s
17func getisar0() uint64
18
19// implemented in cpuid_arm64.s
20func getisar1() uint64
21
22func loadCpuFeatureFlags() CpuFeatureFlags {
23 switch runtime.GOOS {
24 case "darwin", "windows":
25 // These OSes do not allow userland to read the instruction set attribute registers,
26 // but basically require atomic instructions:
27 // - "darwin" is the desktop version (mobile version is "ios"),
28 // and the M1 is a ARMv8.4.
29 // - "windows" requires them from Windows 11, see page 12
30 // https://download.microsoft.com/download/7/8/8/788bf5ab-0751-4928-a22c-dffdc23c27f2/Minimum%20Hardware%20Requirements%20for%20Windows%2011.pdf
31 return &cpuFeatureFlags{
32 isar0: uint64(CpuFeatureArm64Atomic),
33 isar1: 0,
34 }
35 case "linux", "freebsd":
36 // These OSes allow userland to read the instruction set attribute registers,
37 // which is otherwise restricted to EL0:
38 // https://kernel.org/doc/Documentation/arm64/cpu-feature-registers.txt
39 // See these for contents of the registers:
40 // https://developer.arm.com/documentation/ddi0601/latest/AArch64-Registers/ID-AA64ISAR0-EL1--AArch64-Instruction-Set-Attribute-Register-0
41 // https://developer.arm.com/documentation/ddi0601/latest/AArch64-Registers/ID-AA64ISAR1-EL1--AArch64-Instruction-Set-Attribute-Register-1
42 return &cpuFeatureFlags{
43 isar0: getisar0(),
44 isar1: getisar1(),
45 }
46 default:
47 return &cpuFeatureFlags{}
48 }
49}
50
51// Has implements the same method on the CpuFeatureFlags interface.
52func (f *cpuFeatureFlags) Has(cpuFeature CpuFeature) bool {
53 return (f.isar0 & uint64(cpuFeature)) != 0
54}
55
56// HasExtra implements the same method on the CpuFeatureFlags interface.
57func (f *cpuFeatureFlags) HasExtra(cpuFeature CpuFeature) bool {
58 return (f.isar1 & uint64(cpuFeature)) != 0
59}
60
61// Raw implements the same method on the CpuFeatureFlags interface.
62func (f *cpuFeatureFlags) Raw() uint64 {
63 // Below, we only set bits for the features we care about,
64 // instead of setting all the unnecessary bits obtained from the
65 // instruction set attribute registers.
66 var ret uint64
67 if f.Has(CpuFeatureArm64Atomic) {
68 ret = 1 << 0
69 }
70 return ret
71}