From 0826b9017254b8b3ba2b84799f4c0de6107a043f Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Mon, 15 Jul 2024 10:04:42 -0700 Subject: [PATCH] internal/cpu: add DIT detection on arm64 Add support for detecting the DIT feature on ARM64 processors. This mirrors https://go.dev/cl/597377, but using the platform specific semantics. Updates #66450 Change-Id: Ia107e3e3369de7825af70823b485afe2f587358e Reviewed-on: https://go-review.googlesource.com/c/go/+/598335 LUCI-TryBot-Result: Go LUCI Reviewed-by: Ian Lance Taylor --- src/internal/cpu/cpu.go | 1 + src/internal/cpu/cpu_arm64.go | 9 ++++++++- src/internal/cpu/cpu_arm64.s | 7 +++++++ src/internal/cpu/cpu_arm64_darwin.go | 1 + src/internal/cpu/cpu_arm64_freebsd.go | 3 ++- src/internal/cpu/cpu_arm64_hwcap.go | 2 ++ src/internal/cpu/cpu_arm64_openbsd.go | 9 ++++++++- 7 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/internal/cpu/cpu.go b/src/internal/cpu/cpu.go index 4ef43e3efc1..7174076c5e4 100644 --- a/src/internal/cpu/cpu.go +++ b/src/internal/cpu/cpu.go @@ -73,6 +73,7 @@ var ARM64 struct { HasCRC32 bool HasATOMICS bool HasCPUID bool + HasDIT bool IsNeoverse bool _ CacheLinePad } diff --git a/src/internal/cpu/cpu_arm64.go b/src/internal/cpu/cpu_arm64.go index 4a302f27d52..1365991e783 100644 --- a/src/internal/cpu/cpu_arm64.go +++ b/src/internal/cpu/cpu_arm64.go @@ -28,13 +28,15 @@ func doinit() { func getisar0() uint64 +func getpfr0() uint64 + func getMIDR() uint64 func extractBits(data uint64, start, end uint) uint { return (uint)(data>>start) & ((1 << (end - start + 1)) - 1) } -func parseARM64SystemRegisters(isar0 uint64) { +func parseARM64SystemRegisters(isar0, pfr0 uint64) { // ID_AA64ISAR0_EL1 switch extractBits(isar0, 4, 7) { case 1: @@ -66,4 +68,9 @@ func parseARM64SystemRegisters(isar0 uint64) { case 2: ARM64.HasATOMICS = true } + + switch extractBits(pfr0, 48, 51) { + case 1: + ARM64.HasDIT = true + } } diff --git a/src/internal/cpu/cpu_arm64.s b/src/internal/cpu/cpu_arm64.s index d6e7f443739..96075610640 100644 --- a/src/internal/cpu/cpu_arm64.s +++ b/src/internal/cpu/cpu_arm64.s @@ -11,6 +11,13 @@ TEXT ·getisar0(SB),NOSPLIT,$0 MOVD R0, ret+0(FP) RET +// func getpfr0() uint64 +TEXT ·getpfr0(SB),NOSPLIT,$0-8 + // get Processor Feature Register 0 into R0 + MRS ID_AA64PFR0_EL1, R0 + MOVD R0, ret+0(FP) + RET + // func getMIDR() uint64 TEXT ·getMIDR(SB), NOSPLIT, $0-8 MRS MIDR_EL1, R0 diff --git a/src/internal/cpu/cpu_arm64_darwin.go b/src/internal/cpu/cpu_arm64_darwin.go index 2507780e5f1..57cf631e891 100644 --- a/src/internal/cpu/cpu_arm64_darwin.go +++ b/src/internal/cpu/cpu_arm64_darwin.go @@ -12,6 +12,7 @@ func osInit() { ARM64.HasATOMICS = sysctlEnabled([]byte("hw.optional.armv8_1_atomics\x00")) ARM64.HasCRC32 = sysctlEnabled([]byte("hw.optional.armv8_crc32\x00")) ARM64.HasSHA512 = sysctlEnabled([]byte("hw.optional.armv8_2_sha512\x00")) + ARM64.HasDIT = sysctlEnabled([]byte("hw.optional.arm.FEAT_DIT\x00")) // There are no hw.optional sysctl values for the below features on Mac OS 11.0 // to detect their supported state dynamically. Assume the CPU features that diff --git a/src/internal/cpu/cpu_arm64_freebsd.go b/src/internal/cpu/cpu_arm64_freebsd.go index 96ed359ca0b..c339e6f22c2 100644 --- a/src/internal/cpu/cpu_arm64_freebsd.go +++ b/src/internal/cpu/cpu_arm64_freebsd.go @@ -9,6 +9,7 @@ package cpu func osInit() { // Retrieve info from system register ID_AA64ISAR0_EL1. isar0 := getisar0() + prf0 := getpfr0() - parseARM64SystemRegisters(isar0) + parseARM64SystemRegisters(isar0, prf0) } diff --git a/src/internal/cpu/cpu_arm64_hwcap.go b/src/internal/cpu/cpu_arm64_hwcap.go index 34edf3eeb2a..cdc1d89c9e4 100644 --- a/src/internal/cpu/cpu_arm64_hwcap.go +++ b/src/internal/cpu/cpu_arm64_hwcap.go @@ -31,6 +31,7 @@ const ( hwcap_ATOMICS = 1 << 8 hwcap_CPUID = 1 << 11 hwcap_SHA512 = 1 << 21 + hwcap_DIT = 1 << 24 ) func hwcapInit(os string) { @@ -44,6 +45,7 @@ func hwcapInit(os string) { ARM64.HasCRC32 = isSet(HWCap, hwcap_CRC32) ARM64.HasCPUID = isSet(HWCap, hwcap_CPUID) ARM64.HasSHA512 = isSet(HWCap, hwcap_SHA512) + ARM64.HasDIT = isSet(HWCap, hwcap_DIT) // The Samsung S9+ kernel reports support for atomics, but not all cores // actually support them, resulting in SIGILL. See issue #28431. diff --git a/src/internal/cpu/cpu_arm64_openbsd.go b/src/internal/cpu/cpu_arm64_openbsd.go index 12593098eb1..6cc69c95e36 100644 --- a/src/internal/cpu/cpu_arm64_openbsd.go +++ b/src/internal/cpu/cpu_arm64_openbsd.go @@ -13,6 +13,7 @@ const ( // From OpenBSD's machine/cpu.h. _CPU_ID_AA64ISAR0 = 2 _CPU_ID_AA64ISAR1 = 3 + _CPU_ID_AA64PFR0 = 8 ) //go:noescape @@ -24,5 +25,11 @@ func osInit() { if !ok { return } - parseARM64SystemRegisters(isar0) + // Get ID_AA64PFR0 from sysctl. + pfr0, ok := sysctlUint64([]uint32{_CTL_MACHDEP, _CPU_ID_AA64PFR0}) + if !ok { + return + } + + parseARM64SystemRegisters(isar0, pfr0) }