mirror of
https://github.com/tailscale/tailscale.git
synced 2026-09-14 14:59:57 -04:00
Move the goamd64_capable/goamd64_compiled logic out of tsweb/varz into a new util/cpucaps package so that a future hostinfo extension can share it, and extend it to all supported platforms. The host GOAMD64 level is now computed from CPUID feature bits via x/sys/cpu rather than by parsing /proc/cpuinfo, which removes the linux/amd64 restriction and all file I/O. CPUID is also what the Go runtime checks at startup, so it directly answers the question the metric asks: could this machine run a binary built at a higher level. Four flags required by the runtime checks have no x/sys/cpu field: LAHF/SAHF (v2) and MOVBE, LZCNT and F16C (v3). We report a level when all of its other flags are present. That is exact on real hardware: LAHF/SAHF exists on every 64-bit CPU that also has SSE4.2, and MOVBE/LZCNT/F16C exist on every CPU that also has AVX2, BMI2 and FMA (Haswell and Zen onwards). A linux/amd64 test cross-checks the CPUID result against the exact /proc/cpuinfo flag lists, so a test run on any machine where the assumption fails, or where the kernel's view diverges from CPUID (e.g. clearcpuid=), reports the difference. Add a Caps bitmask of the CPU capabilities that Go's runtime and standard library dispatch on, normalized across amd64 and arm64: AES, CLMUL/PMULL, SHA2, SHA512, CRC32, ADX and LSE, plus the vector capabilities not implied by the GOAMD64 level: AVX, AVX2, AVX512 (the v4 F+BW+CD+DQ+VL subset), VAES, VPCLMULQDQ and GFNI. Detection is lazy and reads only x/sys/cpu globals and build info; there is no init-time work and no new dependency. Coverage includes all key client platforms: linux, windows, darwin, freebsd, android (via the linux auxv/MRS path in x/sys/cpu) and ios (via the darwin sysctl path). x/sys/cpu has no arm64 detection on FreeBSD, so read ID_AA64ISAR0_EL1 directly; the FreeBSD kernel emulates EL0 reads of the ID registers, and Go's runtime already depends on that emulation on this platform. The whole feature is behind a new cpucaps feature tag. Building with ts_omit_cpucaps removes the varz metrics and all detection code following the tka stub pattern: the detection functions compile to stubs returning zero inside the package itself, so future importers cannot reintroduce the code by forgetting a build tag, and the Caps type stays available for decoding recorded values. A tailscaled dependency test enforces the omission, and the generated buildfeatures.HasCPUCaps const is available for the later hostinfo extension. tsweb/varz metric names are unchanged. gauge_goamd64_capable values only change on machines where /proc/cpuinfo disagrees with CPUID. Updates #21002 Signed-off-by: James Tucker <james@tailscale.com>