Skip to content

Commit 3eb5d56

Browse files
committed
replace internal/cpu
1 parent a5511b3 commit 3eb5d56

34 files changed

+1604
-3
lines changed

cipher_suites.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import (
1919
_ "unsafe" // for linkname
2020

2121
"github.com/refraction-networking/utls/internal/boring"
22-
"golang.org/x/sys/cpu"
22+
"github.com/refraction-networking/utls/internal/cpu"
2323

2424
"golang.org/x/crypto/chacha20poly1305"
2525
)

go.mod

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ require (
1212
github.com/klauspost/compress v1.17.4
1313
golang.org/x/crypto v0.36.0
1414
golang.org/x/net v0.38.0
15-
golang.org/x/sys v0.31.0
1615
)
1716

18-
require golang.org/x/text v0.23.0 // indirect
17+
require (
18+
golang.org/x/sys v0.31.0 // indirect
19+
golang.org/x/text v0.23.0 // indirect
20+
)

internal/cpu/cpu.go

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
// Copyright 2017 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+
// Package cpu implements processor feature detection
6+
// used by the Go standard library.
7+
package cpu
8+
9+
import _ "unsafe" // for linkname
10+
11+
// DebugOptions is set to true by the runtime if the OS supports reading
12+
// GODEBUG early in runtime startup.
13+
// This should not be changed after it is initialized.
14+
var DebugOptions bool
15+
16+
// CacheLinePad is used to pad structs to avoid false sharing.
17+
type CacheLinePad struct{ _ [CacheLinePadSize]byte }
18+
19+
// CacheLineSize is the CPU's assumed cache line size.
20+
// There is currently no runtime detection of the real cache line size
21+
// so we use the constant per GOARCH CacheLinePadSize as an approximation.
22+
var CacheLineSize uintptr = CacheLinePadSize
23+
24+
// The booleans in X86 contain the correspondingly named cpuid feature bit.
25+
// HasAVX and HasAVX2 are only set if the OS does support XMM and YMM registers
26+
// in addition to the cpuid feature bit being set.
27+
// The struct is padded to avoid false sharing.
28+
var X86 struct {
29+
_ CacheLinePad
30+
HasAES bool
31+
HasADX bool
32+
HasAVX bool
33+
HasAVX2 bool
34+
HasAVX512F bool
35+
HasAVX512BW bool
36+
HasAVX512VL bool
37+
HasBMI1 bool
38+
HasBMI2 bool
39+
HasERMS bool
40+
HasFSRM bool
41+
HasFMA bool
42+
HasOSXSAVE bool
43+
HasPCLMULQDQ bool
44+
HasPOPCNT bool
45+
HasRDTSCP bool
46+
HasSHA bool
47+
HasSSE3 bool
48+
HasSSSE3 bool
49+
HasSSE41 bool
50+
HasSSE42 bool
51+
_ CacheLinePad
52+
}
53+
54+
// The booleans in ARM contain the correspondingly named cpu feature bit.
55+
// The struct is padded to avoid false sharing.
56+
var ARM struct {
57+
_ CacheLinePad
58+
HasVFPv4 bool
59+
HasIDIVA bool
60+
HasV7Atomics bool
61+
_ CacheLinePad
62+
}
63+
64+
// The booleans in ARM64 contain the correspondingly named cpu feature bit.
65+
// The struct is padded to avoid false sharing.
66+
var ARM64 struct {
67+
_ CacheLinePad
68+
HasAES bool
69+
HasPMULL bool
70+
HasSHA1 bool
71+
HasSHA2 bool
72+
HasSHA512 bool
73+
HasSHA3 bool
74+
HasCRC32 bool
75+
HasATOMICS bool
76+
HasCPUID bool
77+
HasDIT bool
78+
IsNeoverse bool
79+
_ CacheLinePad
80+
}
81+
82+
// The booleans in Loong64 contain the correspondingly named cpu feature bit.
83+
// The struct is padded to avoid false sharing.
84+
var Loong64 struct {
85+
_ CacheLinePad
86+
HasLSX bool // support 128-bit vector extension
87+
HasLASX bool // support 256-bit vector extension
88+
HasCRC32 bool // support CRC instruction
89+
HasLAMCAS bool // support AMCAS[_DB].{B/H/W/D}
90+
HasLAM_BH bool // support AM{SWAP/ADD}[_DB].{B/H} instruction
91+
_ CacheLinePad
92+
}
93+
94+
var MIPS64X struct {
95+
_ CacheLinePad
96+
HasMSA bool // MIPS SIMD architecture
97+
_ CacheLinePad
98+
}
99+
100+
// For ppc64(le), it is safe to check only for ISA level starting on ISA v3.00,
101+
// since there are no optional categories. There are some exceptions that also
102+
// require kernel support to work (darn, scv), so there are feature bits for
103+
// those as well. The minimum processor requirement is POWER8 (ISA 2.07).
104+
// The struct is padded to avoid false sharing.
105+
var PPC64 struct {
106+
_ CacheLinePad
107+
HasDARN bool // Hardware random number generator (requires kernel enablement)
108+
HasSCV bool // Syscall vectored (requires kernel enablement)
109+
IsPOWER8 bool // ISA v2.07 (POWER8)
110+
IsPOWER9 bool // ISA v3.00 (POWER9)
111+
IsPOWER10 bool // ISA v3.1 (POWER10)
112+
_ CacheLinePad
113+
}
114+
115+
var S390X struct {
116+
_ CacheLinePad
117+
HasZARCH bool // z architecture mode is active [mandatory]
118+
HasSTFLE bool // store facility list extended [mandatory]
119+
HasLDISP bool // long (20-bit) displacements [mandatory]
120+
HasEIMM bool // 32-bit immediates [mandatory]
121+
HasDFP bool // decimal floating point
122+
HasETF3EH bool // ETF-3 enhanced
123+
HasMSA bool // message security assist (CPACF)
124+
HasAES bool // KM-AES{128,192,256} functions
125+
HasAESCBC bool // KMC-AES{128,192,256} functions
126+
HasAESCTR bool // KMCTR-AES{128,192,256} functions
127+
HasAESGCM bool // KMA-GCM-AES{128,192,256} functions
128+
HasGHASH bool // KIMD-GHASH function
129+
HasSHA1 bool // K{I,L}MD-SHA-1 functions
130+
HasSHA256 bool // K{I,L}MD-SHA-256 functions
131+
HasSHA512 bool // K{I,L}MD-SHA-512 functions
132+
HasSHA3 bool // K{I,L}MD-SHA3-{224,256,384,512} and K{I,L}MD-SHAKE-{128,256} functions
133+
HasVX bool // vector facility. Note: the runtime sets this when it processes auxv records.
134+
HasVXE bool // vector-enhancements facility 1
135+
HasKDSA bool // elliptic curve functions
136+
HasECDSA bool // NIST curves
137+
HasEDDSA bool // Edwards curves
138+
_ CacheLinePad
139+
}
140+
141+
// RISCV64 contains the supported CPU features and performance characteristics for riscv64
142+
// platforms. The booleans in RISCV64, with the exception of HasFastMisaligned, indicate
143+
// the presence of RISC-V extensions.
144+
// The struct is padded to avoid false sharing.
145+
var RISCV64 struct {
146+
_ CacheLinePad
147+
HasFastMisaligned bool // Fast misaligned accesses
148+
HasV bool // Vector extension compatible with RVV 1.0
149+
HasZbb bool // Basic bit-manipulation extension
150+
_ CacheLinePad
151+
}
152+
153+
// CPU feature variables are accessed by assembly code in various packages.
154+
//go:linkname X86
155+
//go:linkname ARM
156+
//go:linkname ARM64
157+
//go:linkname Loong64
158+
//go:linkname MIPS64X
159+
//go:linkname PPC64
160+
//go:linkname S390X
161+
//go:linkname RISCV64
162+
163+
// Initialize examines the processor and sets the relevant variables above.
164+
// This is called by the runtime package early in program initialization,
165+
// before normal init functions are run. env is set by runtime if the OS supports
166+
// cpu feature options in GODEBUG.
167+
func Initialize(env string) {
168+
doinit()
169+
processOptions(env)
170+
}
171+
172+
// options contains the cpu debug options that can be used in GODEBUG.
173+
// Options are arch dependent and are added by the arch specific doinit functions.
174+
// Features that are mandatory for the specific GOARCH should not be added to options
175+
// (e.g. SSE2 on amd64).
176+
var options []option
177+
178+
// Option names should be lower case. e.g. avx instead of AVX.
179+
type option struct {
180+
Name string
181+
Feature *bool
182+
Specified bool // whether feature value was specified in GODEBUG
183+
Enable bool // whether feature should be enabled
184+
}
185+
186+
// processOptions enables or disables CPU feature values based on the parsed env string.
187+
// The env string is expected to be of the form cpu.feature1=value1,cpu.feature2=value2...
188+
// where feature names is one of the architecture specific list stored in the
189+
// cpu packages options variable and values are either 'on' or 'off'.
190+
// If env contains cpu.all=off then all cpu features referenced through the options
191+
// variable are disabled. Other feature names and values result in warning messages.
192+
func processOptions(env string) {
193+
field:
194+
for env != "" {
195+
field := ""
196+
i := indexByte(env, ',')
197+
if i < 0 {
198+
field, env = env, ""
199+
} else {
200+
field, env = env[:i], env[i+1:]
201+
}
202+
if len(field) < 4 || field[:4] != "cpu." {
203+
continue
204+
}
205+
i = indexByte(field, '=')
206+
if i < 0 {
207+
print("GODEBUG: no value specified for \"", field, "\"\n")
208+
continue
209+
}
210+
key, value := field[4:i], field[i+1:] // e.g. "SSE2", "on"
211+
212+
var enable bool
213+
switch value {
214+
case "on":
215+
enable = true
216+
case "off":
217+
enable = false
218+
default:
219+
print("GODEBUG: value \"", value, "\" not supported for cpu option \"", key, "\"\n")
220+
continue field
221+
}
222+
223+
if key == "all" {
224+
for i := range options {
225+
options[i].Specified = true
226+
options[i].Enable = enable
227+
}
228+
continue field
229+
}
230+
231+
for i := range options {
232+
if options[i].Name == key {
233+
options[i].Specified = true
234+
options[i].Enable = enable
235+
continue field
236+
}
237+
}
238+
239+
print("GODEBUG: unknown cpu feature \"", key, "\"\n")
240+
}
241+
242+
for _, o := range options {
243+
if !o.Specified {
244+
continue
245+
}
246+
247+
if o.Enable && !*o.Feature {
248+
print("GODEBUG: can not enable \"", o.Name, "\", missing CPU support\n")
249+
continue
250+
}
251+
252+
*o.Feature = o.Enable
253+
}
254+
}
255+
256+
// indexByte returns the index of the first instance of c in s,
257+
// or -1 if c is not present in s.
258+
// indexByte is semantically the same as [strings.IndexByte].
259+
// We copy this function because "internal/cpu" should not have external dependencies.
260+
func indexByte(s string, c byte) int {
261+
for i := 0; i < len(s); i++ {
262+
if s[i] == c {
263+
return i
264+
}
265+
}
266+
return -1
267+
}

internal/cpu/cpu.s

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Copyright 2020 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+
// This assembly file exists to allow internal/cpu to call
6+
// non-exported runtime functions that use "go:linkname".

internal/cpu/cpu_arm.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2017 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+
package cpu
6+
7+
const CacheLinePadSize = 32
8+
9+
// arm doesn't have a 'cpuid' equivalent, so we rely on HWCAP/HWCAP2.
10+
// These are initialized by archauxv() and should not be changed after they are
11+
// initialized.
12+
var HWCap uint
13+
var HWCap2 uint
14+
var Platform string
15+
16+
// HWCAP/HWCAP2 bits. These are exposed by Linux and FreeBSD.
17+
const (
18+
hwcap_VFPv4 = 1 << 16
19+
hwcap_IDIVA = 1 << 17
20+
hwcap_LPAE = 1 << 20
21+
)
22+
23+
func doinit() {
24+
options = []option{
25+
{Name: "vfpv4", Feature: &ARM.HasVFPv4},
26+
{Name: "idiva", Feature: &ARM.HasIDIVA},
27+
{Name: "v7atomics", Feature: &ARM.HasV7Atomics},
28+
}
29+
30+
// HWCAP feature bits
31+
ARM.HasVFPv4 = isSet(HWCap, hwcap_VFPv4)
32+
ARM.HasIDIVA = isSet(HWCap, hwcap_IDIVA)
33+
// lpae is required to make the 64-bit instructions LDRD and STRD (and variants) atomic.
34+
// See ARMv7 manual section B1.6.
35+
// We also need at least a v7 chip, for the DMB instruction.
36+
ARM.HasV7Atomics = isSet(HWCap, hwcap_LPAE) && isV7(Platform)
37+
}
38+
39+
func isSet(hwc uint, value uint) bool {
40+
return hwc&value != 0
41+
}
42+
43+
func isV7(s string) bool {
44+
if s == "aarch64" {
45+
return true
46+
}
47+
return s >= "v7" // will be something like v5, v7, v8, v8l
48+
}

0 commit comments

Comments
 (0)