From 2da141384657cd40a4b47c735ce72aa036354b51 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Sat, 4 Feb 2023 06:58:22 -0800 Subject: [PATCH] cpu: get hwcap/auxv from the Go 1.21+ runtime Depends on https://go.dev/cl/458256 This change only does Linux for now. Updates golang/go#57336 Change-Id: I0659697c1bdc6e2577c6251b964a0df32047ee12 Reviewed-on: https://go-review.googlesource.com/c/sys/+/465295 Reviewed-by: Ian Lance Taylor TryBot-Result: Gopher Robot Reviewed-by: Michael Pratt Run-TryBot: Brad Fitzpatrick --- cpu/hwcap_linux.go | 15 +++++++++++++++ cpu/runtime_auxv.go | 16 ++++++++++++++++ cpu/runtime_auxv_go121.go | 19 +++++++++++++++++++ cpu/runtime_auxv_go121_test.go | 21 +++++++++++++++++++++ 4 files changed, 71 insertions(+) create mode 100644 cpu/runtime_auxv.go create mode 100644 cpu/runtime_auxv_go121.go create mode 100644 cpu/runtime_auxv_go121_test.go diff --git a/cpu/hwcap_linux.go b/cpu/hwcap_linux.go index f3baa379..1d9d91f3 100644 --- a/cpu/hwcap_linux.go +++ b/cpu/hwcap_linux.go @@ -24,6 +24,21 @@ var hwCap uint var hwCap2 uint func readHWCAP() error { + // For Go 1.21+, get auxv from the Go runtime. + if a := getAuxv(); len(a) > 0 { + for len(a) >= 2 { + tag, val := a[0], uint(a[1]) + a = a[2:] + switch tag { + case _AT_HWCAP: + hwCap = val + case _AT_HWCAP2: + hwCap2 = val + } + } + return nil + } + buf, err := ioutil.ReadFile(procAuxv) if err != nil { // e.g. on android /proc/self/auxv is not accessible, so silently diff --git a/cpu/runtime_auxv.go b/cpu/runtime_auxv.go new file mode 100644 index 00000000..5f92ac9a --- /dev/null +++ b/cpu/runtime_auxv.go @@ -0,0 +1,16 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +// getAuxvFn is non-nil on Go 1.21+ (via runtime_auxv_go121.go init) +// on platforms that use auxv. +var getAuxvFn func() []uintptr + +func getAuxv() []uintptr { + if getAuxvFn == nil { + return nil + } + return getAuxvFn() +} diff --git a/cpu/runtime_auxv_go121.go b/cpu/runtime_auxv_go121.go new file mode 100644 index 00000000..b975ea2a --- /dev/null +++ b/cpu/runtime_auxv_go121.go @@ -0,0 +1,19 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.21 +// +build go1.21 + +package cpu + +import ( + _ "unsafe" // for linkname +) + +//go:linkname runtime_getAuxv runtime.getAuxv +func runtime_getAuxv() []uintptr + +func init() { + getAuxvFn = runtime_getAuxv +} diff --git a/cpu/runtime_auxv_go121_test.go b/cpu/runtime_auxv_go121_test.go new file mode 100644 index 00000000..ac806b4f --- /dev/null +++ b/cpu/runtime_auxv_go121_test.go @@ -0,0 +1,21 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.21 +// +build go1.21 + +package cpu + +import ( + "runtime" + "testing" +) + +func TestAuxvFromRuntime(t *testing.T) { + got := getAuxv() + t.Logf("got: %v", got) // notably: we didn't panic + if runtime.GOOS == "linux" && len(got) == 0 { + t.Errorf("expected auxv on linux; got zero entries") + } +}