Skip to content

Commit

Permalink
Random: Support runtime dispatch on AArch64 macOS
Browse files Browse the repository at this point in the history
This lets us dynamically determine if we should attempt to use HW
instructions for AES.

PiperOrigin-RevId: 716350656
Change-Id: I1ead17b7b44373850b3591307b7f6d3f9147d5f9
  • Loading branch information
majnemer authored and copybara-github committed Jan 16, 2025
1 parent 3ded0b6 commit b7af5e1
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 20 deletions.
1 change: 1 addition & 0 deletions absl/random/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -853,6 +853,7 @@ absl_cc_library(
absl::random_internal_platform
absl::random_internal_randen_hwaes_impl
absl::config
absl::optional
)

# Internal-only target, do not depend on directly.
Expand Down
1 change: 1 addition & 0 deletions absl/random/internal/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ cc_library(
":platform",
":randen_hwaes_impl",
"//absl/base:config",
"//absl/types:optional",
],
)

Expand Down
24 changes: 12 additions & 12 deletions absl/random/internal/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// SKIP_ABSL_INLINE_NAMESPACE_CHECK

#ifndef ABSL_RANDOM_INTERNAL_PLATFORM_H_
#define ABSL_RANDOM_INTERNAL_PLATFORM_H_

Expand Down Expand Up @@ -134,16 +136,23 @@
// accelerated Randen implementation.
#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0

#if defined(ABSL_ARCH_X86_64)
// iOS does not support dispatch, even on x86, since applications
// should be bundled as fat binaries, with a different build tailored for
// each specific supported platform/architecture.
#if (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || \
(defined(TARGET_OS_IPHONE_SIMULATOR) && TARGET_OS_IPHONE_SIMULATOR)
#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH
#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0
#elif defined(ABSL_ARCH_X86_64)
// Dispatch is available on x86_64
#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH
#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1
#elif defined(__linux__) && defined(ABSL_ARCH_PPC)
// Or when running linux PPC
#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH
#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1
#elif defined(__linux__) && defined(ABSL_ARCH_AARCH64)
// Or when running linux AArch64
#elif (defined(__linux__) || defined(__APPLE__)) && defined(ABSL_ARCH_AARCH64)
// Or when running linux or macOS AArch64
#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH
#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1
#elif defined(__linux__) && defined(ABSL_ARCH_ARM) && (__ARM_ARCH >= 8)
Expand All @@ -159,13 +168,4 @@
#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0
#endif

// iOS does not support dispatch, even on x86, since applications
// should be bundled as fat binaries, with a different build tailored for
// each specific supported platform/architecture.
#if (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || \
(defined(TARGET_OS_IPHONE_SIMULATOR) && TARGET_OS_IPHONE_SIMULATOR)
#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH
#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0
#endif

#endif // ABSL_RANDOM_INTERNAL_PLATFORM_H_
73 changes: 66 additions & 7 deletions absl/random/internal/randen_detect.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,21 @@

#include "absl/random/internal/randen_detect.h"

#if defined(__APPLE__) && defined(__aarch64__)
#if defined(__has_include)
#if __has_include(<arm/cpu_capabilities_public.h>)
#include <arm/cpu_capabilities_public.h>
#endif
#endif
#include <sys/sysctl.h>
#include <sys/types.h>
#endif

#include <cstdint>
#include <cstring>

#include "absl/random/internal/platform.h"
#include "absl/types/optional.h" // IWYU pragma: keep

#if !defined(__UCLIBC__) && defined(__GLIBC__) && \
(__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 16))
Expand Down Expand Up @@ -102,6 +113,19 @@ static uint32_t GetAuxval(uint32_t hwcap_type) {

#endif

#if defined(__APPLE__) && defined(ABSL_ARCH_AARCH64)
template <typename T>
static absl::optional<T> ReadSysctlByName(const char* name) {
T val;
size_t val_size = sizeof(T);
int ret = sysctlbyname(name, &val, &val_size, nullptr, 0);
if (ret == -1) {
return std::nullopt;
}
return val;
}
#endif

namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
Expand All @@ -122,14 +146,18 @@ namespace random_internal {
//
// Fon non-x86 it is much more complicated.
//
// 2. When ABSL_INTERNAL_USE_GETAUXVAL is defined, use getauxval() (either
// 2. Try to use __builtin_cpu_supports.
//
// 3. When ABSL_INTERNAL_USE_GETAUXVAL is defined, use getauxval() (either
// the direct c-library version, or the android probing version which loads
// libc), and read the hardware capability bits.
// This is based on the technique used by boringssl uses to detect
// cpu capabilities, and should allow us to enable crypto in the android
// builds where it is supported.
//
// 3. Use the default for the compiler architecture.
// 4. When __APPLE__ is defined on AARCH64, use sysctlbyname().
//
// 5. Use the default for the compiler architecture.
//

bool CPUSupportsRandenHwAes() {
Expand All @@ -139,8 +167,14 @@ bool CPUSupportsRandenHwAes() {
__cpuid(reinterpret_cast<int*>(regs), 1);
return regs[2] & (1 << 25); // AES

#elif defined(ABSL_ARCH_AARCH64) && ABSL_HAVE_BUILTIN(__builtin_cpu_supports)
// For AARCH64: Require crypto+neon
// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0500f/CIHBIBBA.html
//
// __builtin_cpu_supports spells "crypt" as "aes" and "neon" as "simd".
return __builtin_cpu_supports("aes+simd");
#elif defined(ABSL_INTERNAL_USE_GETAUXVAL)
// 2. Use getauxval() to read the hardware bits and determine
// 3. Use getauxval() to read the hardware bits and determine
// cpu capabilities.

#define AT_HWCAP 16
Expand Down Expand Up @@ -178,8 +212,36 @@ bool CPUSupportsRandenHwAes() {
return ((hwcap & kNEON) != 0) && ((hwcap & kAES) != 0);
#endif

#elif defined(__APPLE__) && defined(ABSL_ARCH_AARCH64)
// 4. Use sysctlbyname.

// Newer XNU kernels support querying all capabilities in a single
// sysctlbyname.
#if defined(CAP_BIT_AdvSIMD) && defined(CAP_BIT_FEAT_AES)
static const absl::optional<uint64_t> caps =
ReadSysctlByName<uint64_t>("hw.optional.arm.caps");
if (caps.has_value()) {
constexpr uint64_t kNeonAndAesCaps =
(uint64_t{1} << CAP_BIT_AdvSIMD) | (uint64_t{1} << CAP_BIT_FEAT_AES);
return (*caps & kNeonAndAesCaps) == kNeonAndAesCaps;
}
#endif

// https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics#overview
static const absl::optional<int> adv_simd =
ReadSysctlByName<int>("hw.optional.AdvSIMD");
if (adv_simd.value_or(0) == 0) {
return false;
}
// https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics#3918855
static const absl::optional<int> feat_aes =
ReadSysctlByName<int>("hw.optional.arm.FEAT_AES");
if (feat_aes.value_or(0) == 0) {
return false;
}
return true;
#else // ABSL_INTERNAL_USE_GETAUXVAL
// 3. By default, assume that the compiler default.
// 5. By default, assume that the compiler default.
return ABSL_HAVE_ACCELERATED_AES ? true : false;

#endif
Expand Down Expand Up @@ -215,9 +277,6 @@ bool CPUSupportsRandenHwAes() {
// __asm __volatile("mrs %0, id_aa64isar0_el1" :"=&r" (val));
//
// * Use a CPUID-style heuristic database.
//
// * On Apple (__APPLE__), AES is available on Arm v8.
// https://stackoverflow.com/questions/45637888/how-to-determine-armv8-features-at-runtime-on-ios
}

#if defined(__clang__)
Expand Down
2 changes: 1 addition & 1 deletion absl/random/internal/randen_hwaes_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ int main(int argc, char* argv[]) {
LOG(INFO) << "HasRandenHwAesImplementation = " << x;

int y = absl::random_internal::CPUSupportsRandenHwAes();
LOG(INFO) << "CPUSupportsRandenHwAes = " << x;
LOG(INFO) << "CPUSupportsRandenHwAes = " << y;

if (!x || !y) {
LOG(INFO) << "Skipping Randen HWAES tests.";
Expand Down

0 comments on commit b7af5e1

Please sign in to comment.