mirror of
				https://github.com/google/cpu_features.git
				synced 2025-11-04 06:40:54 +01:00 
			
		
		
		
	Add FreeBSD Arm64 support (#295)
* Add FreeBSD Arm64 detection Getting all the features is handled by reading /var/run/dmesg.boot. Feature detections were taken from the freebsd kernel code sys/arm64/arm64/identcpu.c * Add FreeBSD Arm64 tests * Add flagm, flagm2 and rng detection * Add HWCAP FreeBSD AArch64 * Update include to use linux hwcaps for powerpc * Add FreeBSD aarch64 impl * Separate Hwacps to freebsd and linux implementation * Add aarch64 midr_el1 implementation * Add detection hwcap cpuid to hwcaps.h * Add MIDR_EL1 tests
This commit is contained in:
		
							
								
								
									
										29
									
								
								BUILD.bazel
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								BUILD.bazel
									
									
									
									
									
								
							@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
load("@bazel_skylib//lib:selects.bzl", "selects")
 | 
			
		||||
load("//:bazel/platforms.bzl", "PLATFORM_CPU_ARM", "PLATFORM_CPU_ARM64", "PLATFORM_CPU_MIPS", "PLATFORM_CPU_PPC", "PLATFORM_CPU_RISCV32", "PLATFORM_CPU_RISCV64", "PLATFORM_CPU_X86_64")
 | 
			
		||||
load("//:bazel/platforms.bzl", "PLATFORM_OS_MACOS")
 | 
			
		||||
load("//:bazel/platforms.bzl", "PLATFORM_OS_MACOS", "PLATFORM_OS_LINUX", "PLATFORM_OS_FREEBSD", "PLATFORM_OS_ANDROID")
 | 
			
		||||
 | 
			
		||||
package(
 | 
			
		||||
    default_visibility = ["//visibility:public"],
 | 
			
		||||
@@ -169,11 +169,18 @@ cc_library(
 | 
			
		||||
 | 
			
		||||
cc_library(
 | 
			
		||||
    name = "hwcaps",
 | 
			
		||||
    srcs = ["src/hwcaps.c"],
 | 
			
		||||
    srcs = [
 | 
			
		||||
        "src/hwcaps.c",
 | 
			
		||||
        "src/hwcaps_freebsd.c",
 | 
			
		||||
        "src/hwcaps_linux_or_android.c",
 | 
			
		||||
    ],
 | 
			
		||||
    copts = C99_FLAGS,
 | 
			
		||||
    defines = selects.with_or({
 | 
			
		||||
        PLATFORM_OS_MACOS: ["HAVE_DLFCN_H"],
 | 
			
		||||
        "//conditions:default": ["HAVE_STRONG_GETAUXVAL"],
 | 
			
		||||
        PLATFORM_OS_FREEBSD: ["HAVE_STRONG_ELF_AUX_INFO"],
 | 
			
		||||
        PLATFORM_OS_LINUX: ["HAVE_STRONG_GETAUXVAL"],
 | 
			
		||||
        PLATFORM_OS_ANDROID: ["HAVE_STRONG_GETAUXVAL"],
 | 
			
		||||
        "//conditions:default": [],
 | 
			
		||||
    }),
 | 
			
		||||
    includes = INCLUDES,
 | 
			
		||||
    textual_hdrs = ["include/internal/hwcaps.h"],
 | 
			
		||||
@@ -189,6 +196,8 @@ cc_library(
 | 
			
		||||
    testonly = 1,
 | 
			
		||||
    srcs = [
 | 
			
		||||
        "src/hwcaps.c",
 | 
			
		||||
        "src/hwcaps_freebsd.c",
 | 
			
		||||
        "src/hwcaps_linux_or_android.c",
 | 
			
		||||
        "test/hwcaps_for_testing.cc",
 | 
			
		||||
    ],
 | 
			
		||||
    hdrs = [
 | 
			
		||||
@@ -218,9 +227,11 @@ cc_library(
 | 
			
		||||
        ],
 | 
			
		||||
        PLATFORM_CPU_ARM: ["src/impl_arm_linux_or_android.c"],
 | 
			
		||||
        PLATFORM_CPU_ARM64: [
 | 
			
		||||
            "src/impl_aarch64_cpuid.c",
 | 
			
		||||
            "src/impl_aarch64_linux_or_android.c",
 | 
			
		||||
            "src/impl_aarch64_macos_or_iphone.c",
 | 
			
		||||
            "src/impl_aarch64_windows.c",
 | 
			
		||||
            "src/impl_aarch64_freebsd.c",
 | 
			
		||||
        ],
 | 
			
		||||
        PLATFORM_CPU_MIPS: ["src/impl_mips_linux_or_android.c"],
 | 
			
		||||
        PLATFORM_CPU_PPC: ["src/impl_ppc_linux.c"],
 | 
			
		||||
@@ -234,7 +245,10 @@ cc_library(
 | 
			
		||||
            "include/internal/windows_utils.h",
 | 
			
		||||
        ],
 | 
			
		||||
        PLATFORM_CPU_ARM: ["include/cpuinfo_arm.h"],
 | 
			
		||||
        PLATFORM_CPU_ARM64: ["include/cpuinfo_aarch64.h"],
 | 
			
		||||
        PLATFORM_CPU_ARM64: [
 | 
			
		||||
            "include/cpuinfo_aarch64.h",
 | 
			
		||||
            "include/internal/cpuid_aarch64.h",
 | 
			
		||||
        ],
 | 
			
		||||
        PLATFORM_CPU_MIPS: ["include/cpuinfo_mips.h"],
 | 
			
		||||
        PLATFORM_CPU_PPC: ["include/cpuinfo_ppc.h"],
 | 
			
		||||
        PLATFORM_CPU_RISCV32: ["include/cpuinfo_riscv.h"],
 | 
			
		||||
@@ -278,9 +292,11 @@ cc_library(
 | 
			
		||||
        ],
 | 
			
		||||
        PLATFORM_CPU_ARM: ["src/impl_arm_linux_or_android.c"],
 | 
			
		||||
        PLATFORM_CPU_ARM64: [
 | 
			
		||||
            "src/impl_aarch64_cpuid.c",
 | 
			
		||||
            "src/impl_aarch64_linux_or_android.c",
 | 
			
		||||
            "src/impl_aarch64_macos_or_iphone.c",
 | 
			
		||||
            "src/impl_aarch64_windows.c",
 | 
			
		||||
            "src/impl_aarch64_freebsd.c",
 | 
			
		||||
        ],
 | 
			
		||||
        PLATFORM_CPU_MIPS: ["src/impl_mips_linux_or_android.c"],
 | 
			
		||||
        PLATFORM_CPU_PPC: ["src/impl_ppc_linux.c"],
 | 
			
		||||
@@ -294,7 +310,10 @@ cc_library(
 | 
			
		||||
            "include/internal/windows_utils.h",
 | 
			
		||||
        ],
 | 
			
		||||
        PLATFORM_CPU_ARM: ["include/cpuinfo_arm.h"],
 | 
			
		||||
        PLATFORM_CPU_ARM64: ["include/cpuinfo_aarch64.h"],
 | 
			
		||||
        PLATFORM_CPU_ARM64: [
 | 
			
		||||
            "include/cpuinfo_aarch64.h",
 | 
			
		||||
            "include/internal/cpuid_aarch64.h"
 | 
			
		||||
        ],
 | 
			
		||||
        PLATFORM_CPU_MIPS: ["include/cpuinfo_mips.h"],
 | 
			
		||||
        PLATFORM_CPU_PPC: ["include/cpuinfo_ppc.h"],
 | 
			
		||||
        PLATFORM_CPU_RISCV32: ["include/cpuinfo_riscv.h"],
 | 
			
		||||
 
 | 
			
		||||
@@ -106,6 +106,7 @@ macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME)
 | 
			
		||||
      list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_arm.h)
 | 
			
		||||
  elseif(PROCESSOR_IS_AARCH64)
 | 
			
		||||
      list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_aarch64.h)
 | 
			
		||||
      list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/cpuid_aarch64.h)
 | 
			
		||||
      list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/windows_utils.h)
 | 
			
		||||
  elseif(PROCESSOR_IS_X86)
 | 
			
		||||
      list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_x86.h)
 | 
			
		||||
@@ -146,6 +147,8 @@ setup_include_and_definitions(utils)
 | 
			
		||||
if(UNIX)
 | 
			
		||||
  add_library(unix_based_hardware_detection OBJECT
 | 
			
		||||
    ${PROJECT_SOURCE_DIR}/include/internal/hwcaps.h
 | 
			
		||||
    ${PROJECT_SOURCE_DIR}/src/hwcaps_linux_or_android.c
 | 
			
		||||
    ${PROJECT_SOURCE_DIR}/src/hwcaps_freebsd.c
 | 
			
		||||
    ${PROJECT_SOURCE_DIR}/src/hwcaps.c
 | 
			
		||||
  )
 | 
			
		||||
  setup_include_and_definitions(unix_based_hardware_detection)
 | 
			
		||||
@@ -154,9 +157,13 @@ if(UNIX)
 | 
			
		||||
    target_compile_definitions(unix_based_hardware_detection PRIVATE HAVE_DLFCN_H)
 | 
			
		||||
  endif()
 | 
			
		||||
  check_symbol_exists(getauxval "sys/auxv.h" HAVE_STRONG_GETAUXVAL)
 | 
			
		||||
  check_symbol_exists(elf_aux_info "sys/auxv.h" HAVE_STRONG_ELF_AUX_INFO)
 | 
			
		||||
  if(HAVE_STRONG_GETAUXVAL)
 | 
			
		||||
    target_compile_definitions(unix_based_hardware_detection PRIVATE HAVE_STRONG_GETAUXVAL)
 | 
			
		||||
  endif()
 | 
			
		||||
  if(HAVE_STRONG_ELF_AUX_INFO)
 | 
			
		||||
    target_compile_definitions(unix_based_hardware_detection PUBLIC HAVE_STRONG_ELF_AUX_INFO)
 | 
			
		||||
  endif()
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
 
 | 
			
		||||
@@ -16,3 +16,9 @@ PLATFORM_CPU_RISCV64 = ("@platforms//cpu:riscv64")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PLATFORM_OS_MACOS = ("@platforms//os:macos")
 | 
			
		||||
 | 
			
		||||
PLATFORM_OS_LINUX = ("@platforms//os:linux")
 | 
			
		||||
 | 
			
		||||
PLATFORM_OS_ANDROID = ("@platforms//os:android")
 | 
			
		||||
 | 
			
		||||
PLATFORM_OS_FREEBSD = ("@platforms//os:freebsd")
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										28
									
								
								include/internal/cpuid_aarch64.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								include/internal/cpuid_aarch64.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
// Copyright 2023 Google LLC
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
// you may not use this file except in compliance with the License.
 | 
			
		||||
// You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
//    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef CPU_FEATURES_INCLUDE_CPUID_AARCH64_H_
 | 
			
		||||
#define CPU_FEATURES_INCLUDE_CPUID_AARCH64_H_
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include "cpu_features_macros.h"
 | 
			
		||||
 | 
			
		||||
CPU_FEATURES_START_CPP_NAMESPACE
 | 
			
		||||
 | 
			
		||||
uint64_t GetMidrEl1(void);
 | 
			
		||||
 | 
			
		||||
CPU_FEATURES_END_CPP_NAMESPACE
 | 
			
		||||
 | 
			
		||||
#endif  // CPU_FEATURES_INCLUDE_CPUID_AARCH64_H_
 | 
			
		||||
							
								
								
									
										143
									
								
								src/hwcaps.c
									
									
									
									
									
								
							
							
						
						
									
										143
									
								
								src/hwcaps.c
									
									
									
									
									
								
							@@ -14,12 +14,7 @@
 | 
			
		||||
 | 
			
		||||
#include "internal/hwcaps.h"
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "cpu_features_macros.h"
 | 
			
		||||
#include "internal/filesystem.h"
 | 
			
		||||
#include "internal/string_view.h"
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
static bool IsSet(const uint32_t mask, const uint32_t value) {
 | 
			
		||||
  if (mask == 0) return false;
 | 
			
		||||
@@ -31,139 +26,3 @@ bool CpuFeatures_IsHwCapsSet(const HardwareCapabilities hwcaps_mask,
 | 
			
		||||
  return IsSet(hwcaps_mask.hwcaps, hwcaps.hwcaps) ||
 | 
			
		||||
         IsSet(hwcaps_mask.hwcaps2, hwcaps.hwcaps2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef CPU_FEATURES_TEST
 | 
			
		||||
// In test mode, hwcaps_for_testing will define the following functions.
 | 
			
		||||
HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void);
 | 
			
		||||
const char* CpuFeatures_GetPlatformPointer(void);
 | 
			
		||||
const char* CpuFeatures_GetBasePlatformPointer(void);
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
// Debug facilities
 | 
			
		||||
#if defined(NDEBUG)
 | 
			
		||||
#define D(...)
 | 
			
		||||
#else
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#define D(...)           \
 | 
			
		||||
  do {                   \
 | 
			
		||||
    printf(__VA_ARGS__); \
 | 
			
		||||
    fflush(stdout);      \
 | 
			
		||||
  } while (0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Implementation of GetElfHwcapFromGetauxval
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
#define AT_HWCAP 16
 | 
			
		||||
#define AT_HWCAP2 26
 | 
			
		||||
#define AT_PLATFORM 15
 | 
			
		||||
#define AT_BASE_PLATFORM 24
 | 
			
		||||
 | 
			
		||||
#if defined(HAVE_STRONG_GETAUXVAL)
 | 
			
		||||
#include <sys/auxv.h>
 | 
			
		||||
static unsigned long GetElfHwcapFromGetauxval(uint32_t hwcap_type) {
 | 
			
		||||
  return getauxval(hwcap_type);
 | 
			
		||||
}
 | 
			
		||||
#elif defined(HAVE_DLFCN_H)
 | 
			
		||||
// On Android we probe the system's C library for a 'getauxval' function and
 | 
			
		||||
// call it if it exits, or return 0 for failure. This function is available
 | 
			
		||||
// since API level 18.
 | 
			
		||||
//
 | 
			
		||||
// Note that getauxval() can't really be re-implemented here, because its
 | 
			
		||||
// implementation does not parse /proc/self/auxv. Instead it depends on values
 | 
			
		||||
// that are passed by the kernel at process-init time to the C runtime
 | 
			
		||||
// initialization layer.
 | 
			
		||||
 | 
			
		||||
#include <dlfcn.h>
 | 
			
		||||
 | 
			
		||||
typedef unsigned long getauxval_func_t(unsigned long);
 | 
			
		||||
 | 
			
		||||
static uint32_t GetElfHwcapFromGetauxval(uint32_t hwcap_type) {
 | 
			
		||||
  uint32_t ret = 0;
 | 
			
		||||
  void *libc_handle = NULL;
 | 
			
		||||
  getauxval_func_t *func = NULL;
 | 
			
		||||
 | 
			
		||||
  dlerror();  // Cleaning error state before calling dlopen.
 | 
			
		||||
  libc_handle = dlopen("libc.so", RTLD_NOW);
 | 
			
		||||
  if (!libc_handle) {
 | 
			
		||||
    D("Could not dlopen() C library: %s\n", dlerror());
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
  func = (getauxval_func_t *)dlsym(libc_handle, "getauxval");
 | 
			
		||||
  if (!func) {
 | 
			
		||||
    D("Could not find getauxval() in C library\n");
 | 
			
		||||
  } else {
 | 
			
		||||
    // Note: getauxval() returns 0 on failure. Doesn't touch errno.
 | 
			
		||||
    ret = (uint32_t)(*func)(hwcap_type);
 | 
			
		||||
  }
 | 
			
		||||
  dlclose(libc_handle);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
#error "This platform does not provide hardware capabilities."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Implementation of GetHardwareCapabilities for OS that provide
 | 
			
		||||
// GetElfHwcapFromGetauxval().
 | 
			
		||||
 | 
			
		||||
// Fallback when getauxval is not available, retrieves hwcaps from
 | 
			
		||||
// "/proc/self/auxv".
 | 
			
		||||
static uint32_t GetElfHwcapFromProcSelfAuxv(uint32_t hwcap_type) {
 | 
			
		||||
  struct {
 | 
			
		||||
    uint32_t tag;
 | 
			
		||||
    uint32_t value;
 | 
			
		||||
  } entry;
 | 
			
		||||
  uint32_t result = 0;
 | 
			
		||||
  const char filepath[] = "/proc/self/auxv";
 | 
			
		||||
  const int fd = CpuFeatures_OpenFile(filepath);
 | 
			
		||||
  if (fd < 0) {
 | 
			
		||||
    D("Could not open %s\n", filepath);
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
  for (;;) {
 | 
			
		||||
    const int ret = CpuFeatures_ReadFile(fd, (char *)&entry, sizeof entry);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
      D("Error while reading %s\n", filepath);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    // Detect end of list.
 | 
			
		||||
    if (ret == 0 || (entry.tag == 0 && entry.value == 0)) {
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    if (entry.tag == hwcap_type) {
 | 
			
		||||
      result = entry.value;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  CpuFeatures_CloseFile(fd);
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Retrieves hardware capabilities by first trying to call getauxval, if not
 | 
			
		||||
// available falls back to reading "/proc/self/auxv".
 | 
			
		||||
static unsigned long GetHardwareCapabilitiesFor(uint32_t type) {
 | 
			
		||||
  unsigned long hwcaps = GetElfHwcapFromGetauxval(type);
 | 
			
		||||
  if (!hwcaps) {
 | 
			
		||||
    D("Parsing /proc/self/auxv to extract ELF hwcaps!\n");
 | 
			
		||||
    hwcaps = GetElfHwcapFromProcSelfAuxv(type);
 | 
			
		||||
  }
 | 
			
		||||
  return hwcaps;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) {
 | 
			
		||||
  HardwareCapabilities capabilities;
 | 
			
		||||
  capabilities.hwcaps = GetHardwareCapabilitiesFor(AT_HWCAP);
 | 
			
		||||
  capabilities.hwcaps2 = GetHardwareCapabilitiesFor(AT_HWCAP2);
 | 
			
		||||
  return capabilities;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *CpuFeatures_GetPlatformPointer(void) {
 | 
			
		||||
  return (const char *)GetHardwareCapabilitiesFor(AT_PLATFORM);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *CpuFeatures_GetBasePlatformPointer(void) {
 | 
			
		||||
  return (const char *)GetHardwareCapabilitiesFor(AT_BASE_PLATFORM);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif  // CPU_FEATURES_TEST
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										54
									
								
								src/hwcaps_freebsd.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/hwcaps_freebsd.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
// Copyright 2023 Google LLC
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
// you may not use this file except in compliance with the License.
 | 
			
		||||
// You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
//    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
#include "cpu_features_macros.h"
 | 
			
		||||
 | 
			
		||||
#ifdef CPU_FEATURES_OS_FREEBSD
 | 
			
		||||
 | 
			
		||||
#include "internal/hwcaps.h"
 | 
			
		||||
 | 
			
		||||
#ifdef CPU_FEATURES_TEST
 | 
			
		||||
// In test mode, hwcaps_for_testing will define the following functions.
 | 
			
		||||
HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void);
 | 
			
		||||
const char* CpuFeatures_GetPlatformPointer(void);
 | 
			
		||||
const char* CpuFeatures_GetBasePlatformPointer(void);
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_STRONG_ELF_AUX_INFO
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <sys/auxv.h>
 | 
			
		||||
 | 
			
		||||
static unsigned long GetElfHwcapFromElfAuxInfo(int hwcap_type) {
 | 
			
		||||
  unsigned long hwcap;
 | 
			
		||||
  elf_aux_info(hwcap_type, &hwcap, sizeof(hwcap));
 | 
			
		||||
  return hwcap;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) {
 | 
			
		||||
  HardwareCapabilities capabilities;
 | 
			
		||||
  capabilities.hwcaps = GetElfHwcapFromElfAuxInfo(AT_HWCAP);
 | 
			
		||||
  capabilities.hwcaps2 = GetElfHwcapFromElfAuxInfo(AT_HWCAP2);
 | 
			
		||||
  return capabilities;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *CpuFeatures_GetPlatformPointer(void) { return NULL; }
 | 
			
		||||
 | 
			
		||||
const char *CpuFeatures_GetBasePlatformPointer(void) { return NULL; }
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
#error "FreeBSD needs support for elf_aux_info"
 | 
			
		||||
#endif  // HAVE_STRONG_ELF_AUX_INFO
 | 
			
		||||
 | 
			
		||||
#endif  // CPU_FEATURES_TEST
 | 
			
		||||
#endif  // CPU_FEATURES_OS_FREEBSD
 | 
			
		||||
							
								
								
									
										161
									
								
								src/hwcaps_linux_or_android.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								src/hwcaps_linux_or_android.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,161 @@
 | 
			
		||||
// Copyright 2023 Google LLC
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
// you may not use this file except in compliance with the License.
 | 
			
		||||
// You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
//    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
#include "cpu_features_macros.h"
 | 
			
		||||
 | 
			
		||||
#if defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "cpu_features_macros.h"
 | 
			
		||||
#include "internal/filesystem.h"
 | 
			
		||||
#include "internal/hwcaps.h"
 | 
			
		||||
#include "internal/string_view.h"
 | 
			
		||||
 | 
			
		||||
#ifdef CPU_FEATURES_TEST
 | 
			
		||||
// In test mode, hwcaps_for_testing will define the following functions.
 | 
			
		||||
HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void);
 | 
			
		||||
const char* CpuFeatures_GetPlatformPointer(void);
 | 
			
		||||
const char* CpuFeatures_GetBasePlatformPointer(void);
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
// Debug facilities
 | 
			
		||||
#if defined(NDEBUG)
 | 
			
		||||
#define D(...)
 | 
			
		||||
#else
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#define D(...)           \
 | 
			
		||||
  do {                   \
 | 
			
		||||
    printf(__VA_ARGS__); \
 | 
			
		||||
    fflush(stdout);      \
 | 
			
		||||
  } while (0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Implementation of GetElfHwcapFromGetauxval
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
#if defined(HAVE_STRONG_GETAUXVAL)
 | 
			
		||||
#include <sys/auxv.h>
 | 
			
		||||
static unsigned long GetElfHwcapFromGetauxval(uint32_t hwcap_type) {
 | 
			
		||||
  return getauxval(hwcap_type);
 | 
			
		||||
}
 | 
			
		||||
#elif defined(HAVE_DLFCN_H)
 | 
			
		||||
// On Android we probe the system's C library for a 'getauxval' function and
 | 
			
		||||
// call it if it exits, or return 0 for failure. This function is available
 | 
			
		||||
// since API level 18.
 | 
			
		||||
//
 | 
			
		||||
// Note that getauxval() can't really be re-implemented here, because its
 | 
			
		||||
// implementation does not parse /proc/self/auxv. Instead it depends on values
 | 
			
		||||
// that are passed by the kernel at process-init time to the C runtime
 | 
			
		||||
// initialization layer.
 | 
			
		||||
 | 
			
		||||
#include <dlfcn.h>
 | 
			
		||||
 | 
			
		||||
typedef unsigned long getauxval_func_t(unsigned long);
 | 
			
		||||
 | 
			
		||||
static uint32_t GetElfHwcapFromGetauxval(uint32_t hwcap_type) {
 | 
			
		||||
  uint32_t ret = 0;
 | 
			
		||||
  void *libc_handle = NULL;
 | 
			
		||||
  getauxval_func_t *func = NULL;
 | 
			
		||||
 | 
			
		||||
  dlerror();  // Cleaning error state before calling dlopen.
 | 
			
		||||
  libc_handle = dlopen("libc.so", RTLD_NOW);
 | 
			
		||||
  if (!libc_handle) {
 | 
			
		||||
    D("Could not dlopen() C library: %s\n", dlerror());
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
  func = (getauxval_func_t *)dlsym(libc_handle, "getauxval");
 | 
			
		||||
  if (!func) {
 | 
			
		||||
    D("Could not find getauxval() in C library\n");
 | 
			
		||||
  } else {
 | 
			
		||||
    // Note: getauxval() returns 0 on failure. Doesn't touch errno.
 | 
			
		||||
    ret = (uint32_t)(*func)(hwcap_type);
 | 
			
		||||
  }
 | 
			
		||||
  dlclose(libc_handle);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
#error "This platform does not provide hardware capabilities."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Implementation of GetHardwareCapabilities for OS that provide
 | 
			
		||||
// GetElfHwcapFromGetauxval().
 | 
			
		||||
 | 
			
		||||
// Fallback when getauxval is not available, retrieves hwcaps from
 | 
			
		||||
// "/proc/self/auxv".
 | 
			
		||||
static uint32_t GetElfHwcapFromProcSelfAuxv(uint32_t hwcap_type) {
 | 
			
		||||
  struct {
 | 
			
		||||
    uint32_t tag;
 | 
			
		||||
    uint32_t value;
 | 
			
		||||
  } entry;
 | 
			
		||||
  uint32_t result = 0;
 | 
			
		||||
  const char filepath[] = "/proc/self/auxv";
 | 
			
		||||
  const int fd = CpuFeatures_OpenFile(filepath);
 | 
			
		||||
  if (fd < 0) {
 | 
			
		||||
    D("Could not open %s\n", filepath);
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
  for (;;) {
 | 
			
		||||
    const int ret = CpuFeatures_ReadFile(fd, (char *)&entry, sizeof entry);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
      D("Error while reading %s\n", filepath);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    // Detect end of list.
 | 
			
		||||
    if (ret == 0 || (entry.tag == 0 && entry.value == 0)) {
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    if (entry.tag == hwcap_type) {
 | 
			
		||||
      result = entry.value;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  CpuFeatures_CloseFile(fd);
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Retrieves hardware capabilities by first trying to call getauxval, if not
 | 
			
		||||
// available falls back to reading "/proc/self/auxv".
 | 
			
		||||
static unsigned long GetHardwareCapabilitiesFor(uint32_t type) {
 | 
			
		||||
  unsigned long hwcaps = GetElfHwcapFromGetauxval(type);
 | 
			
		||||
  if (!hwcaps) {
 | 
			
		||||
    D("Parsing /proc/self/auxv to extract ELF hwcaps!\n");
 | 
			
		||||
    hwcaps = GetElfHwcapFromProcSelfAuxv(type);
 | 
			
		||||
  }
 | 
			
		||||
  return hwcaps;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) {
 | 
			
		||||
  HardwareCapabilities capabilities;
 | 
			
		||||
  capabilities.hwcaps = GetHardwareCapabilitiesFor(AT_HWCAP);
 | 
			
		||||
  capabilities.hwcaps2 = GetHardwareCapabilitiesFor(AT_HWCAP2);
 | 
			
		||||
  return capabilities;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *CpuFeatures_GetPlatformPointer(void) {
 | 
			
		||||
  return (const char *)GetHardwareCapabilitiesFor(AT_PLATFORM);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *CpuFeatures_GetBasePlatformPointer(void) {
 | 
			
		||||
  return (const char *)GetHardwareCapabilitiesFor(AT_BASE_PLATFORM);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CpuFeatures_IsHwCapCpuidSupported() {
 | 
			
		||||
  return GetElfHwcapFromGetauxval(AARCH64_HWCAP_CPUID);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif  // CPU_FEATURES_TEST
 | 
			
		||||
#endif  // defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
 | 
			
		||||
							
								
								
									
										40
									
								
								src/impl_aarch64_cpuid.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/impl_aarch64_cpuid.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
// Copyright 2023 Google LLC
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
// you may not use this file except in compliance with the License.
 | 
			
		||||
// You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
//    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
#include "cpu_features_macros.h"
 | 
			
		||||
 | 
			
		||||
#ifdef CPU_FEATURES_ARCH_AARCH64
 | 
			
		||||
#if (defined(CPU_FEATURES_OS_FREEBSD) || defined(CPU_FEATURES_OS_LINUX) || \
 | 
			
		||||
     defined(CPU_FEATURES_OS_ANDROID))
 | 
			
		||||
#if (defined(CPU_FEATURES_COMPILER_GCC) || defined(CPU_FEATURES_COMPILER_CLANG))
 | 
			
		||||
 | 
			
		||||
#include "internal/cpuid_aarch64.h"
 | 
			
		||||
 | 
			
		||||
#ifdef CPU_FEATURES_MOCK_CPUID_AARCH64
 | 
			
		||||
// Implementation will be provided by test/cpuinfo_aarch64_test.cc.
 | 
			
		||||
#else
 | 
			
		||||
uint64_t GetMidrEl1(void) {
 | 
			
		||||
  uint64_t midr_el1;
 | 
			
		||||
  __asm("mrs %0, MIDR_EL1" : "=r"(midr_el1));
 | 
			
		||||
  return midr_el1;
 | 
			
		||||
}
 | 
			
		||||
#endif  // CPU_FEATURES_MOCK_CPUID_AARCH64
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
#error "Unsupported compiler, aarch64 cpuid requires either GCC or Clang."
 | 
			
		||||
#endif  // (defined(CPU_FEATURES_COMPILER_GCC) ||
 | 
			
		||||
        // defined(CPU_FEATURES_COMPILER_CLANG))
 | 
			
		||||
#endif  // (defined(CPU_FEATURES_OS_FREEBSD) || defined(CPU_FEATURES_OS_LINUX)
 | 
			
		||||
        // || defined(CPU_FEATURES_OS_ANDROID))
 | 
			
		||||
#endif  // CPU_FEATURES_ARCH_AARCH64
 | 
			
		||||
							
								
								
									
										46
									
								
								src/impl_aarch64_freebsd.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/impl_aarch64_freebsd.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
// Copyright 2023 Google LLC
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
// you may not use this file except in compliance with the License.
 | 
			
		||||
// You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
//    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
#include "cpu_features_macros.h"
 | 
			
		||||
 | 
			
		||||
#ifdef CPU_FEATURES_ARCH_AARCH64
 | 
			
		||||
#ifdef CPU_FEATURES_OS_FREEBSD
 | 
			
		||||
 | 
			
		||||
#include "cpuinfo_aarch64.h"
 | 
			
		||||
#include "impl_aarch64__base_implementation.inl"
 | 
			
		||||
#include "internal/cpuid_aarch64.h"
 | 
			
		||||
#include "internal/hwcaps.h"
 | 
			
		||||
 | 
			
		||||
static const Aarch64Info kEmptyAarch64Info;
 | 
			
		||||
 | 
			
		||||
Aarch64Info GetAarch64Info(void) {
 | 
			
		||||
  Aarch64Info info = kEmptyAarch64Info;
 | 
			
		||||
  const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
 | 
			
		||||
  for (size_t i = 0; i < AARCH64_LAST_; ++i) {
 | 
			
		||||
    if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) {
 | 
			
		||||
      kSetters[i](&info.features, true);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (info.features.cpuid) {
 | 
			
		||||
    const uint64_t midr_el1 = GetMidrEl1();
 | 
			
		||||
    info.implementer = (int)ExtractBitRange(midr_el1, 31, 24);
 | 
			
		||||
    info.variant = (int)ExtractBitRange(midr_el1, 23, 20);
 | 
			
		||||
    info.part = (int)ExtractBitRange(midr_el1, 15, 4);
 | 
			
		||||
    info.revision = (int)ExtractBitRange(midr_el1, 3, 0);
 | 
			
		||||
  }
 | 
			
		||||
  return info;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif  // CPU_FEATURES_OS_FREEBSD
 | 
			
		||||
#endif  // CPU_FEATURES_ARCH_AARCH64
 | 
			
		||||
@@ -22,7 +22,11 @@ add_library(stack_line_reader_for_test ../src/stack_line_reader.c)
 | 
			
		||||
target_compile_definitions(stack_line_reader_for_test PUBLIC STACK_LINE_READER_BUFFER_SIZE=16)
 | 
			
		||||
target_link_libraries(stack_line_reader_for_test string_view filesystem_for_testing)
 | 
			
		||||
##------------------------------------------------------------------------------
 | 
			
		||||
add_library(all_libraries ../src/hwcaps.c  ../src/stack_line_reader.c)
 | 
			
		||||
add_library(all_libraries
 | 
			
		||||
        ../src/hwcaps.c
 | 
			
		||||
        ../src/hwcaps_linux_or_android.c
 | 
			
		||||
        ../src/hwcaps_freebsd.c
 | 
			
		||||
        ../src/stack_line_reader.c)
 | 
			
		||||
target_link_libraries(all_libraries hwcaps_for_testing stack_line_reader string_view)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
@@ -73,9 +77,11 @@ endif()
 | 
			
		||||
if(PROCESSOR_IS_AARCH64)
 | 
			
		||||
  add_executable(cpuinfo_aarch64_test
 | 
			
		||||
    cpuinfo_aarch64_test.cc
 | 
			
		||||
    ../src/impl_aarch64_cpuid.c
 | 
			
		||||
    ../src/impl_aarch64_linux_or_android.c
 | 
			
		||||
    ../src/impl_aarch64_windows.c
 | 
			
		||||
    ../src/impl_aarch64_macos_or_iphone.c
 | 
			
		||||
    ../src/impl_aarch64_freebsd.c
 | 
			
		||||
  )
 | 
			
		||||
  if(APPLE)
 | 
			
		||||
    target_compile_definitions(cpuinfo_aarch64_test PUBLIC CPU_FEATURES_MOCK_SYSCTL_AARCH64)
 | 
			
		||||
 
 | 
			
		||||
@@ -22,11 +22,20 @@
 | 
			
		||||
#if defined(CPU_FEATURES_OS_WINDOWS)
 | 
			
		||||
#include "internal/windows_utils.h"
 | 
			
		||||
#endif  // CPU_FEATURES_OS_WINDOWS
 | 
			
		||||
#if defined(CPU_FEATURES_OS_FREEBSD) || defined(CPU_FEATURES_OS_LINUX)
 | 
			
		||||
#include "internal/cpuid_aarch64.h"
 | 
			
		||||
#endif  // defined(CPU_FEATURES_OS_FREEBSD) || defined(CPU_FEATURES_OS_LINUX)
 | 
			
		||||
 | 
			
		||||
namespace cpu_features {
 | 
			
		||||
class FakeCpuAarch64 {
 | 
			
		||||
#if defined(CPU_FEATURES_OS_LINUX)
 | 
			
		||||
  // No particular implementation for Linux as we use /proc/cpuinfo
 | 
			
		||||
#if defined(CPU_FEATURES_OS_FREEBSD) || defined(CPU_FEATURES_OS_LINUX)
 | 
			
		||||
 public:
 | 
			
		||||
  uint64_t GetMidrEl1() const { return _midr_el1; }
 | 
			
		||||
 | 
			
		||||
  void SetMidrEl1(uint64_t midr_el1) { _midr_el1 = midr_el1; }
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  uint64_t _midr_el1;
 | 
			
		||||
#elif defined(CPU_FEATURES_OS_MACOS)
 | 
			
		||||
  std::set<std::string> darwin_sysctlbyname_;
 | 
			
		||||
  std::map<std::string, int> darwin_sysctlbynamevalue_;
 | 
			
		||||
@@ -80,8 +89,8 @@ static FakeCpuAarch64& cpu() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Define OS dependent mock functions
 | 
			
		||||
#if defined(CPU_FEATURES_OS_LINUX)
 | 
			
		||||
// No particular functions to implement for Linux as we use /proc/cpuinfo
 | 
			
		||||
#if defined(CPU_FEATURES_OS_FREEBSD) || defined(CPU_FEATURES_OS_LINUX)
 | 
			
		||||
extern "C" uint64_t GetMidrEl1(void) { return cpu().GetMidrEl1(); }
 | 
			
		||||
#elif defined(CPU_FEATURES_OS_MACOS)
 | 
			
		||||
extern "C" bool GetDarwinSysCtlByName(const char* name) {
 | 
			
		||||
  return cpu().GetDarwinSysCtlByName(name);
 | 
			
		||||
@@ -127,8 +136,8 @@ TEST_F(CpuidAarch64Test, Aarch64FeaturesEnum) {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// OS dependent tests
 | 
			
		||||
#if defined(CPU_FEATURES_OS_LINUX)
 | 
			
		||||
// AT_HWCAP tests
 | 
			
		||||
#if defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_FREEBSD)
 | 
			
		||||
TEST_F(CpuidAarch64Test, FromHardwareCap) {
 | 
			
		||||
  ResetHwcaps();
 | 
			
		||||
  SetHardwareCapabilities(AARCH64_HWCAP_FP | AARCH64_HWCAP_AES, 0);
 | 
			
		||||
@@ -196,7 +205,10 @@ TEST_F(CpuidAarch64Test, FromHardwareCap2) {
 | 
			
		||||
  EXPECT_FALSE(info.features.dgh);
 | 
			
		||||
  EXPECT_FALSE(info.features.rng);
 | 
			
		||||
}
 | 
			
		||||
#endif  // defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_FREEBSD)
 | 
			
		||||
 | 
			
		||||
// OS dependent tests
 | 
			
		||||
#if defined(CPU_FEATURES_OS_LINUX)
 | 
			
		||||
TEST_F(CpuidAarch64Test, ARMCortexA53) {
 | 
			
		||||
  ResetHwcaps();
 | 
			
		||||
  auto& fs = GetEmptyFilesystem();
 | 
			
		||||
@@ -383,6 +395,37 @@ TEST_F(CpuidAarch64Test, WINDOWS_AARCH64_RPI4) {
 | 
			
		||||
  EXPECT_FALSE(info.features.jscvt);
 | 
			
		||||
  EXPECT_FALSE(info.features.lrcpc);
 | 
			
		||||
}
 | 
			
		||||
#endif  // CPU_FEATURES_OS_WINDOWS
 | 
			
		||||
#elif defined(CPU_FEATURES_OS_FREEBSD)
 | 
			
		||||
TEST_F(CpuidAarch64Test, MrsMidrEl1_RPI4) {
 | 
			
		||||
  ResetHwcaps();
 | 
			
		||||
  SetHardwareCapabilities(AARCH64_HWCAP_FP | AARCH64_HWCAP_CPUID, 0);
 | 
			
		||||
  cpu().SetMidrEl1(0x410FD083);
 | 
			
		||||
  const auto info = GetAarch64Info();
 | 
			
		||||
 | 
			
		||||
  EXPECT_EQ(info.implementer, 0x41);
 | 
			
		||||
  EXPECT_EQ(info.variant, 0);
 | 
			
		||||
  EXPECT_EQ(info.part, 0xD08);
 | 
			
		||||
  EXPECT_EQ(info.revision, 0x3);
 | 
			
		||||
 | 
			
		||||
  EXPECT_TRUE(info.features.fp);
 | 
			
		||||
 | 
			
		||||
  EXPECT_FALSE(info.features.dcpodp);
 | 
			
		||||
  EXPECT_FALSE(info.features.sveaes);
 | 
			
		||||
  EXPECT_FALSE(info.features.svepmull);
 | 
			
		||||
  EXPECT_FALSE(info.features.svebitperm);
 | 
			
		||||
  EXPECT_FALSE(info.features.svesha3);
 | 
			
		||||
  EXPECT_FALSE(info.features.svesm4);
 | 
			
		||||
  EXPECT_FALSE(info.features.flagm2);
 | 
			
		||||
  EXPECT_FALSE(info.features.frint);
 | 
			
		||||
  EXPECT_FALSE(info.features.svei8mm);
 | 
			
		||||
  EXPECT_FALSE(info.features.svef32mm);
 | 
			
		||||
  EXPECT_FALSE(info.features.svef64mm);
 | 
			
		||||
  EXPECT_FALSE(info.features.svebf16);
 | 
			
		||||
  EXPECT_FALSE(info.features.i8mm);
 | 
			
		||||
  EXPECT_FALSE(info.features.bf16);
 | 
			
		||||
  EXPECT_FALSE(info.features.dgh);
 | 
			
		||||
  EXPECT_FALSE(info.features.rng);
 | 
			
		||||
}
 | 
			
		||||
#endif  // CPU_FEATURES_OS_FREEBSD
 | 
			
		||||
}  // namespace
 | 
			
		||||
}  // namespace cpu_features
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user