Source file
src/internal/cpu/datacache_x86.go
1
2
3
4
5
6
7 package cpu
8
9
10
11
12
13
14
15 func DataCacheSizes() []uintptr {
16 maxFunctionInformation, ebx0, ecx0, edx0 := cpuid(0, 0)
17 if maxFunctionInformation < 1 {
18 return nil
19 }
20
21 switch {
22
23 case ebx0 == 0x756E6547 && ecx0 == 0x6C65746E && edx0 == 0x49656E69:
24 return getDataCacheSizesIntel(maxFunctionInformation)
25
26 case ebx0 == 0x68747541 && ecx0 == 0x444D4163 && edx0 == 0x69746E65:
27 return getDataCacheSizesAMD()
28 }
29 return nil
30 }
31
32 func extractBits(arg uint32, l int, r int) uint32 {
33 if l > r {
34 panic("bad bit range")
35 }
36 return (arg >> l) & ((1 << (r - l + 1)) - 1)
37 }
38
39 func getDataCacheSizesIntel(maxID uint32) []uintptr {
40
41 const (
42 noCache = 0
43 dataCache = 1
44 instructionCache = 2
45 unifiedCache = 3
46 )
47 if maxID < 4 {
48 return nil
49 }
50
51
52 var caches []uintptr
53 for i := uint32(0); i < 0xFFFF; i++ {
54 eax, ebx, ecx, _ := cpuid(4, i)
55
56 cacheType := eax & 0xF
57 if cacheType == 0 {
58 break
59 }
60
61
62 if !(cacheType == dataCache || cacheType == unifiedCache) {
63 continue
64 }
65
66
67 level := (eax >> 5) & 0x7
68
69 lineSize := extractBits(ebx, 0, 11) + 1
70 partitions := extractBits(ebx, 12, 21) + 1
71 ways := extractBits(ebx, 22, 31) + 1
72 sets := uint64(ecx) + 1
73 size := uint64(ways*partitions*lineSize) * sets
74
75 caches = append(caches, uintptr(size))
76
77
78
79
80
81
82 if level != uint32(len(caches)) {
83 panic("expected levels to be in order and for there to be one data/unified cache per level")
84 }
85 }
86 return caches
87 }
88
89 func getDataCacheSizesAMD() []uintptr {
90 maxExtendedFunctionInformation, _, _, _ := cpuid(0x80000000, 0)
91 if maxExtendedFunctionInformation < 0x80000006 {
92 return nil
93 }
94
95 var caches []uintptr
96
97 _, _, ecx5, _ := cpuid(0x80000005, 0)
98 _, _, ecx6, edx6 := cpuid(0x80000006, 0)
99
100
101 l1dSize := uintptr(extractBits(ecx5, 24, 31) << 10)
102 caches = append(caches, l1dSize)
103
104
105 if l2Assoc := extractBits(ecx6, 12, 15); l2Assoc == 0 {
106 return caches
107 }
108 l2Size := uintptr(extractBits(ecx6, 16, 31) << 10)
109 caches = append(caches, l2Size)
110
111
112 if l3Assoc := extractBits(edx6, 12, 15); l3Assoc == 0 {
113 return caches
114 }
115
116
117 l3Size := uintptr(extractBits(edx6, 18, 31) * (512 << 10))
118 caches = append(caches, l3Size)
119
120 return caches
121 }
122
View as plain text