cpuid_amd64.go

 1//go:build gc
 2
 3package platform
 4
 5// CpuFeatures exposes the capabilities for this CPU, queried via the Has, HasExtra methods.
 6var CpuFeatures = loadCpuFeatureFlags()
 7
 8// cpuFeatureFlags implements CpuFeatureFlags interface.
 9type cpuFeatureFlags struct {
10	flags      uint64
11	extraFlags uint64
12}
13
14// cpuid exposes the CPUID instruction to the Go layer (https://www.amd.com/system/files/TechDocs/25481.pdf)
15// implemented in cpuid_amd64.s
16func cpuid(arg1, arg2 uint32) (eax, ebx, ecx, edx uint32)
17
18// cpuidAsBitmap combines the result of invoking cpuid to uint64 bitmap.
19func cpuidAsBitmap(arg1, arg2 uint32) uint64 {
20	_ /* eax */, _ /* ebx */, ecx, edx := cpuid(arg1, arg2)
21	return (uint64(edx) << 32) | uint64(ecx)
22}
23
24// loadStandardRange load flags from the standard range, panics otherwise.
25func loadStandardRange(id uint32) uint64 {
26	// ensure that the id is in the valid range, returned by cpuid(0,0)
27	maxRange, _, _, _ := cpuid(0, 0)
28	if id > maxRange {
29		panic("cannot query standard CPU flags")
30	}
31	return cpuidAsBitmap(id, 0)
32}
33
34// loadStandardRange load flags from the extended range, panics otherwise.
35func loadExtendedRange(id uint32) uint64 {
36	// ensure that the id is in the valid range, returned by cpuid(0x80000000,0)
37	maxRange, _, _, _ := cpuid(0x80000000, 0)
38	if id > maxRange {
39		panic("cannot query extended CPU flags")
40	}
41	return cpuidAsBitmap(id, 0)
42}
43
44func loadCpuFeatureFlags() CpuFeatureFlags {
45	return &cpuFeatureFlags{
46		flags:      loadStandardRange(1),
47		extraFlags: loadExtendedRange(0x80000001),
48	}
49}
50
51// Has implements the same method on the CpuFeatureFlags interface.
52func (f *cpuFeatureFlags) Has(cpuFeature CpuFeature) bool {
53	return (f.flags & 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.extraFlags & 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	// CPUID instruction.
66	var ret uint64
67	if f.Has(CpuFeatureAmd64SSE3) {
68		ret = 1 << 0
69	}
70	if f.Has(CpuFeatureAmd64SSE4_1) {
71		ret |= 1 << 1
72	}
73	if f.Has(CpuFeatureAmd64SSE4_2) {
74		ret |= 1 << 2
75	}
76	if f.HasExtra(CpuExtraFeatureAmd64ABM) {
77		ret |= 1 << 3
78	}
79	return ret
80}