1
2
3
4
5 package cpu
6
7 import (
8 "syscall"
9 "unsafe"
10 )
11
12
13
14
15 const (
16 _CTL_QUERY = -2
17
18 _SYSCTL_VERS_1 = 0x1000000
19 )
20
21 var _zero uintptr
22
23 func sysctl(mib []int32, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
24 var _p0 unsafe.Pointer
25 if len(mib) > 0 {
26 _p0 = unsafe.Pointer(&mib[0])
27 } else {
28 _p0 = unsafe.Pointer(&_zero)
29 }
30 _, _, errno := syscall.Syscall6(
31 syscall.SYS___SYSCTL,
32 uintptr(_p0),
33 uintptr(len(mib)),
34 uintptr(unsafe.Pointer(old)),
35 uintptr(unsafe.Pointer(oldlen)),
36 uintptr(unsafe.Pointer(new)),
37 uintptr(newlen))
38 if errno != 0 {
39 return errno
40 }
41 return nil
42 }
43
44 type sysctlNode struct {
45 Flags uint32
46 Num int32
47 Name [32]int8
48 Ver uint32
49 __rsvd uint32
50 Un [16]byte
51 _sysctl_size [8]byte
52 _sysctl_func [8]byte
53 _sysctl_parent [8]byte
54 _sysctl_desc [8]byte
55 }
56
57 func sysctlNodes(mib []int32) ([]sysctlNode, error) {
58 var olen uintptr
59
60
61
62 mib = append(mib, _CTL_QUERY)
63 qnode := sysctlNode{Flags: _SYSCTL_VERS_1}
64 qp := (*byte)(unsafe.Pointer(&qnode))
65 sz := unsafe.Sizeof(qnode)
66 if err := sysctl(mib, nil, &olen, qp, sz); err != nil {
67 return nil, err
68 }
69
70
71 nodes := make([]sysctlNode, olen/sz)
72 np := (*byte)(unsafe.Pointer(&nodes[0]))
73 if err := sysctl(mib, np, &olen, qp, sz); err != nil {
74 return nil, err
75 }
76
77 return nodes, nil
78 }
79
80 func nametomib(name string) ([]int32, error) {
81
82 var parts []string
83 last := 0
84 for i := 0; i < len(name); i++ {
85 if name[i] == '.' {
86 parts = append(parts, name[last:i])
87 last = i + 1
88 }
89 }
90 parts = append(parts, name[last:])
91
92 mib := []int32{}
93
94 for partno, part := range parts {
95 nodes, err := sysctlNodes(mib)
96 if err != nil {
97 return nil, err
98 }
99 for _, node := range nodes {
100 n := make([]byte, 0)
101 for i := range node.Name {
102 if node.Name[i] != 0 {
103 n = append(n, byte(node.Name[i]))
104 }
105 }
106 if string(n) == part {
107 mib = append(mib, int32(node.Num))
108 break
109 }
110 }
111 if len(mib) != partno+1 {
112 return nil, err
113 }
114 }
115
116 return mib, nil
117 }
118
119
120 type aarch64SysctlCPUID struct {
121 midr uint64
122 revidr uint64
123 mpidr uint64
124 aa64dfr0 uint64
125 aa64dfr1 uint64
126 aa64isar0 uint64
127 aa64isar1 uint64
128 aa64mmfr0 uint64
129 aa64mmfr1 uint64
130 aa64mmfr2 uint64
131 aa64pfr0 uint64
132 aa64pfr1 uint64
133 aa64zfr0 uint64
134 mvfr0 uint32
135 mvfr1 uint32
136 mvfr2 uint32
137 pad uint32
138 clidr uint64
139 ctr uint64
140 }
141
142 func sysctlCPUID(name string) (*aarch64SysctlCPUID, error) {
143 mib, err := nametomib(name)
144 if err != nil {
145 return nil, err
146 }
147
148 out := aarch64SysctlCPUID{}
149 n := unsafe.Sizeof(out)
150 _, _, errno := syscall.Syscall6(
151 syscall.SYS___SYSCTL,
152 uintptr(unsafe.Pointer(&mib[0])),
153 uintptr(len(mib)),
154 uintptr(unsafe.Pointer(&out)),
155 uintptr(unsafe.Pointer(&n)),
156 uintptr(0),
157 uintptr(0))
158 if errno != 0 {
159 return nil, errno
160 }
161 return &out, nil
162 }
163
164 func doinit() {
165 cpuid, err := sysctlCPUID("machdep.cpu0.cpu_id")
166 if err != nil {
167 setMinimalFeatures()
168 return
169 }
170 parseARM64SystemRegisters(cpuid.aa64isar0, cpuid.aa64isar1, cpuid.aa64pfr0)
171
172 Initialized = true
173 }
174
View as plain text