From e4216d54f58616b862013e2810436462db08b6ed Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Mon, 30 Sep 2024 16:52:50 +0200 Subject: [PATCH] internal/cpu: add ARM64.HasSHA3 For #69536 Change-Id: If237226ba03e282443b4fc90484968c903198cb1 Reviewed-on: https://go-review.googlesource.com/c/go/+/616715 Reviewed-by: Junyang Shao LUCI-TryBot-Result: Go LUCI Reviewed-by: Roland Shoemaker --- src/internal/cpu/cpu.go | 1 + src/internal/cpu/cpu_arm64.go | 7 +++++++ src/internal/cpu/cpu_arm64_darwin.go | 14 ++++++++++---- src/internal/cpu/cpu_arm64_hwcap.go | 4 ++++ 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/internal/cpu/cpu.go b/src/internal/cpu/cpu.go index e07463f870..760dc0b469 100644 --- a/src/internal/cpu/cpu.go +++ b/src/internal/cpu/cpu.go @@ -70,6 +70,7 @@ var ARM64 struct { HasSHA1 bool HasSHA2 bool HasSHA512 bool + HasSHA3 bool HasCRC32 bool HasATOMICS bool HasCPUID bool diff --git a/src/internal/cpu/cpu_arm64.go b/src/internal/cpu/cpu_arm64.go index 1365991e78..7709966d57 100644 --- a/src/internal/cpu/cpu_arm64.go +++ b/src/internal/cpu/cpu_arm64.go @@ -16,6 +16,7 @@ func doinit() { {Name: "sha1", Feature: &ARM64.HasSHA1}, {Name: "sha2", Feature: &ARM64.HasSHA2}, {Name: "sha512", Feature: &ARM64.HasSHA512}, + {Name: "sha3", Feature: &ARM64.HasSHA3}, {Name: "crc32", Feature: &ARM64.HasCRC32}, {Name: "atomics", Feature: &ARM64.HasATOMICS}, {Name: "cpuid", Feature: &ARM64.HasCPUID}, @@ -38,6 +39,7 @@ func extractBits(data uint64, start, end uint) uint { func parseARM64SystemRegisters(isar0, pfr0 uint64) { // ID_AA64ISAR0_EL1 + // https://developer.arm.com/documentation/ddi0601/2025-03/AArch64-Registers/ID-AA64ISAR0-EL1--AArch64-Instruction-Set-Attribute-Register-0 switch extractBits(isar0, 4, 7) { case 1: ARM64.HasAES = true @@ -69,6 +71,11 @@ func parseARM64SystemRegisters(isar0, pfr0 uint64) { ARM64.HasATOMICS = true } + switch extractBits(isar0, 32, 35) { + case 1: + ARM64.HasSHA3 = true + } + switch extractBits(pfr0, 48, 51) { case 1: ARM64.HasDIT = true diff --git a/src/internal/cpu/cpu_arm64_darwin.go b/src/internal/cpu/cpu_arm64_darwin.go index 57cf631e89..28b47d60e8 100644 --- a/src/internal/cpu/cpu_arm64_darwin.go +++ b/src/internal/cpu/cpu_arm64_darwin.go @@ -9,15 +9,21 @@ package cpu import _ "unsafe" // for linkname func osInit() { + // macOS 12 moved these to the hw.optional.arm tree, but as of Go 1.24 we + // still support macOS 11. See [Determine Encryption Capabilities]. + // + // [Determine Encryption Capabilities]: https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics#3918855 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.HasSHA3 = sysctlEnabled([]byte("hw.optional.armv8_2_sha3\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 - // Apple Silicon M1 supports to be available as a minimal set of features - // to all Go programs running on darwin/arm64. + // There are no hw.optional sysctl values for the below features on macOS 11 + // to detect their supported state dynamically (although they are available + // in the hw.optional.arm tree on macOS 12). Assume the CPU features that + // Apple Silicon M1 supports to be available on all future iterations. ARM64.HasAES = true ARM64.HasPMULL = true ARM64.HasSHA1 = true diff --git a/src/internal/cpu/cpu_arm64_hwcap.go b/src/internal/cpu/cpu_arm64_hwcap.go index e6711ae275..b6cc1f4d98 100644 --- a/src/internal/cpu/cpu_arm64_hwcap.go +++ b/src/internal/cpu/cpu_arm64_hwcap.go @@ -22,6 +22,7 @@ import _ "unsafe" // for linkname var HWCap uint // HWCAP bits. These are exposed by Linux. +// See arch/arm64/include/uapi/asm/hwcap.h. const ( hwcap_AES = 1 << 3 hwcap_PMULL = 1 << 4 @@ -30,18 +31,21 @@ const ( hwcap_CRC32 = 1 << 7 hwcap_ATOMICS = 1 << 8 hwcap_CPUID = 1 << 11 + hwcap_SHA3 = 1 << 17 hwcap_SHA512 = 1 << 21 hwcap_DIT = 1 << 24 ) func hwcapInit(os string) { // HWCap was populated by the runtime from the auxiliary vector. + // See https://docs.kernel.org/arch/arm64/elf_hwcaps.html. // Use HWCap information since reading aarch64 system registers // is not supported in user space on older linux kernels. ARM64.HasAES = isSet(HWCap, hwcap_AES) ARM64.HasPMULL = isSet(HWCap, hwcap_PMULL) ARM64.HasSHA1 = isSet(HWCap, hwcap_SHA1) ARM64.HasSHA2 = isSet(HWCap, hwcap_SHA2) + ARM64.HasSHA3 = isSet(HWCap, hwcap_SHA3) ARM64.HasCRC32 = isSet(HWCap, hwcap_CRC32) ARM64.HasCPUID = isSet(HWCap, hwcap_CPUID) ARM64.HasSHA512 = isSet(HWCap, hwcap_SHA512) -- 2.50.0