]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: move arm hardware division support detection to internal/cpu
authorMartin Möhrmann <moehrmann@google.com>
Sun, 27 May 2018 06:49:36 +0000 (08:49 +0200)
committerMartin Möhrmann <moehrmann@google.com>
Fri, 24 Aug 2018 14:27:07 +0000 (14:27 +0000)
Assumes mandatory VFP and VFPv3 support to be present by default
but not IDIVA if AT_HWCAP is not available.

Adds GODEBUGCPU options to disable the use of code paths in the runtime
that use hardware support for division.

Change-Id: Ida02311bd9b9701de3fc120697e69445bf6c0853
Reviewed-on: https://go-review.googlesource.com/114826
Run-TryBot: Martin Möhrmann <moehrmann@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
13 files changed:
src/internal/cpu/cpu.go
src/internal/cpu/cpu_arm.go
src/internal/cpu/cpu_no_init.go
src/runtime/cpuflags.go
src/runtime/os_darwin_arm.go
src/runtime/os_freebsd.go
src/runtime/os_freebsd_arm.go
src/runtime/os_linux_arm.go
src/runtime/os_nacl_arm.go
src/runtime/os_netbsd_arm.go
src/runtime/os_openbsd_arm.go
src/runtime/os_plan9_arm.go
src/runtime/vlop_arm.s

index f2dfadbff839011f21b2ed017f69749d0118b3c5..2b5db91fe2b2257cd5672b7248e17916c61cd22d 100644 (file)
@@ -66,6 +66,16 @@ type ppc64 struct {
        _          CacheLinePad
 }
 
+var ARM arm
+
+// The booleans in arm contain the correspondingly named cpu feature bit.
+// The struct is padded to avoid false sharing.
+type arm struct {
+       _        CacheLinePad
+       HasIDIVA bool
+       _        CacheLinePad
+}
+
 var ARM64 arm64
 
 // The booleans in arm64 contain the correspondingly named cpu feature bit.
index 078a6c3b80a28d6049ad5dd50932d46413618918..b9baa44fea6f0aec61867e27ba3b346d8484f932 100644 (file)
@@ -5,3 +5,28 @@
 package cpu
 
 const CacheLineSize = 32
+
+// arm doesn't have a 'cpuid' equivalent, so we rely on HWCAP/HWCAP2.
+// These are linknamed in runtime/os_(linux|freebsd)_arm.go and are
+// initialized by archauxv().
+// These should not be changed after they are initialized.
+var HWCap uint
+var HWCap2 uint
+
+// HWCAP/HWCAP2 bits. These are exposed by Linux and FreeBSD.
+const (
+       hwcap_IDIVA = 1 << 17
+)
+
+func doinit() {
+       options = []option{
+               {"idiva", &ARM.HasIDIVA},
+       }
+
+       // HWCAP feature bits
+       ARM.HasIDIVA = isSet(HWCap, hwcap_IDIVA)
+}
+
+func isSet(hwc uint, value uint) bool {
+       return hwc&value != 0
+}
index 1be4f29dddd988e746190b3ae2d89a9e1d596ad4..777ea9de8bdbfe92ed70d2e8004d98d77cbbc525 100644 (file)
@@ -5,6 +5,7 @@
 // +build !386
 // +build !amd64
 // +build !amd64p32
+// +build !arm
 // +build !arm64
 // +build !ppc64
 // +build !ppc64le
index dee6116a90b4b068189688c4e29bac604c4bd197..050168c2d730330a74435f15df26d22aadc8813a 100644 (file)
@@ -14,4 +14,6 @@ const (
        offset_x86_HasAVX2 = unsafe.Offsetof(cpu.X86.HasAVX2)
        offset_x86_HasERMS = unsafe.Offsetof(cpu.X86.HasERMS)
        offset_x86_HasSSE2 = unsafe.Offsetof(cpu.X86.HasSSE2)
+
+       offset_arm_HasIDIVA = unsafe.Offsetof(cpu.ARM.HasIDIVA)
 )
index 8eb5655969c71d1fd80d7636ccdd6a36f8cf2dbb..ee1bd174f1be6d9c1518e910870b5e16b5775cbd 100644 (file)
@@ -4,8 +4,6 @@
 
 package runtime
 
-var hardDiv bool // TODO: set if a hardware divider is available
-
 func checkgoarm() {
        // TODO(minux): FP checks like in os_linux_arm.go.
 
index 631dc20ab46acdf8bc44b7fff90688bcc828c919..08f7b0ecf047f3b917923120ee5f64d6d0658ab7 100644 (file)
@@ -389,6 +389,7 @@ const (
        _AT_PAGESZ   = 6  // Page size in bytes
        _AT_TIMEKEEP = 22 // Pointer to timehands.
        _AT_HWCAP    = 25 // CPU feature flags
+       _AT_HWCAP2   = 26 // CPU feature flags 2
 )
 
 func sysauxv(auxv []uintptr) {
index d2dc26f0c4f40c37b2458869ba5009db1c83a936..eb4de9bc2123d4c2b0d70d8b39071865764681ca 100644 (file)
@@ -4,22 +4,29 @@
 
 package runtime
 
+import "internal/cpu"
+
 const (
        _HWCAP_VFP   = 1 << 6
        _HWCAP_VFPv3 = 1 << 13
-       _HWCAP_IDIVA = 1 << 17
 )
 
-var hwcap = ^uint32(0) // set by archauxv
-var hardDiv bool       // set if a hardware divider is available
+// AT_HWCAP is not available on FreeBSD-11.1-RELEASE or earlier.
+// Default to mandatory VFP hardware support for arm being available.
+// If AT_HWCAP is available goarmHWCap will be updated in archauxv.
+// TODO(moehrmann) remove once all go supported FreeBSD versions support _AT_HWCAP.
+var goarmHWCap uint = (_HWCAP_VFP | _HWCAP_VFPv3)
 
 func checkgoarm() {
-       if goarm > 5 && hwcap&_HWCAP_VFP == 0 {
+       // Update cpu.HWCap to match goarmHWCap in case they were not updated in archauxv.
+       cpu.HWCap = goarmHWCap
+
+       if goarm > 5 && cpu.HWCap&_HWCAP_VFP == 0 {
                print("runtime: this CPU has no floating point hardware, so it cannot run\n")
                print("this GOARM=", goarm, " binary. Recompile using GOARM=5.\n")
                exit(1)
        }
-       if goarm > 6 && hwcap&_HWCAP_VFPv3 == 0 {
+       if goarm > 6 && cpu.HWCap&_HWCAP_VFPv3 == 0 {
                print("runtime: this CPU has no VFPv3 floating point hardware, so it cannot run\n")
                print("this GOARM=", goarm, " binary. Recompile using GOARM=5 or GOARM=6.\n")
                exit(1)
@@ -35,9 +42,11 @@ func checkgoarm() {
 
 func archauxv(tag, val uintptr) {
        switch tag {
-       case _AT_HWCAP: // CPU capability bit flags
-               hwcap = uint32(val)
-               hardDiv = (hwcap & _HWCAP_IDIVA) != 0
+       case _AT_HWCAP:
+               cpu.HWCap = uint(val)
+               goarmHWCap = cpu.HWCap
+       case _AT_HWCAP2:
+               cpu.HWCap2 = uint(val)
        }
 }
 
index 14f1cfeaefb5d57c1510f17ff56b2994aebcf61e..8f082ba6a0ac4b93cb02aacd8ab7d7c501c081b7 100644 (file)
@@ -4,20 +4,20 @@
 
 package runtime
 
-import "unsafe"
+import (
+       "internal/cpu"
+       "unsafe"
+)
 
 const (
        _AT_PLATFORM = 15 //  introduced in at least 2.6.11
 
        _HWCAP_VFP   = 1 << 6  // introduced in at least 2.6.11
        _HWCAP_VFPv3 = 1 << 13 // introduced in 2.6.30
-       _HWCAP_IDIVA = 1 << 17
 )
 
 var randomNumber uint32
 var armArch uint8 = 6 // we default to ARMv6
-var hwcap uint32      // set by archauxv
-var hardDiv bool      // set if a hardware divider is available
 
 func checkgoarm() {
        // On Android, /proc/self/auxv might be unreadable and hwcap won't
@@ -26,12 +26,12 @@ func checkgoarm() {
        if GOOS == "android" {
                return
        }
-       if goarm > 5 && hwcap&_HWCAP_VFP == 0 {
+       if goarm > 5 && cpu.HWCap&_HWCAP_VFP == 0 {
                print("runtime: this CPU has no floating point hardware, so it cannot run\n")
                print("this GOARM=", goarm, " binary. Recompile using GOARM=5.\n")
                exit(1)
        }
-       if goarm > 6 && hwcap&_HWCAP_VFPv3 == 0 {
+       if goarm > 6 && cpu.HWCap&_HWCAP_VFPv3 == 0 {
                print("runtime: this CPU has no VFPv3 floating point hardware, so it cannot run\n")
                print("this GOARM=", goarm, " binary. Recompile using GOARM=5 or GOARM=6.\n")
                exit(1)
@@ -53,9 +53,10 @@ func archauxv(tag, val uintptr) {
                        armArch = t - '0'
                }
 
-       case _AT_HWCAP: // CPU capability bit flags
-               hwcap = uint32(val)
-               hardDiv = (hwcap & _HWCAP_IDIVA) != 0
+       case _AT_HWCAP:
+               cpu.HWCap = uint(val)
+       case _AT_HWCAP2:
+               cpu.HWCap2 = uint(val)
        }
 }
 
index c64ebf31d3562e5766f9eb4e9b8de99483af1941..8669ee75b46c9bff76a5b8b9f85596b4b9aee86e 100644 (file)
@@ -4,8 +4,6 @@
 
 package runtime
 
-var hardDiv bool // TODO: set if a hardware divider is available
-
 func checkgoarm() {
        // TODO(minux): FP checks like in os_linux_arm.go.
 
index b02e36a73ab461b973a789ee3fbb24c03850a48c..95603da64394b02bc3d48c9ce4a88f74f56e50f3 100644 (file)
@@ -6,8 +6,6 @@ package runtime
 
 import "unsafe"
 
-var hardDiv bool // TODO: set if a hardware divider is available
-
 func lwp_mcontext_init(mc *mcontextt, stk unsafe.Pointer, mp *m, gp *g, fn uintptr) {
        // Machine dependent mcontext initialisation for LWP.
        mc.__gregs[_REG_R15] = uint32(funcPC(lwp_tramp))
index c318578ab50e242dd783a5d60a468c1d9efb2e95..be2e1e9959da60f2074ed78b12c24944f81c9a6b 100644 (file)
@@ -4,8 +4,6 @@
 
 package runtime
 
-var hardDiv bool // TODO: set if a hardware divider is available
-
 func checkgoarm() {
        // TODO(minux): FP checks like in os_linux_arm.go.
 
index 1ce0141ce25b8e8cb60c05cb02d05e42b61345c2..fdce1e7a352d6122044e3dd0d06ca7c11a44f7e2 100644 (file)
@@ -4,8 +4,6 @@
 
 package runtime
 
-var hardDiv bool // TODO: set if a hardware divider is available
-
 func checkgoarm() {
        return // TODO(minux)
 }
index d48e515d32cb3ba48e4bd9df2da308b700783d20..8df13abd988202711fa158a5d566c18ff3d4b3df 100644 (file)
@@ -44,7 +44,7 @@
 // the RET instruction will clobber R12 on nacl, and the compiler's register
 // allocator needs to know.
 TEXT runtime·udiv(SB),NOSPLIT|NOFRAME,$0
-       MOVBU   runtime·hardDiv(SB), Ra
+       MOVBU   internal∕cpu·ARM+const_offset_arm_HasIDIVA(SB), Ra
        CMP     $0, Ra
        BNE     udiv_hardware