diff options
author | Roland Levillain <rpl@google.com> | 2023-09-21 19:00:55 +0100 |
---|---|---|
committer | Roland Levillain <rpl@google.com> | 2023-09-21 19:03:34 +0100 |
commit | 3de70d00295d58f2039cd5589603bf3285ace7e0 (patch) | |
tree | 6024c46d82d3a8d8bd952ffdca5f23cb37d9072d | |
parent | 925e059f65798dab125ec08bea999308cf00c86e (diff) | |
parent | ba4bffa86cbb5456bdb34426ad22b9551278e2c0 (diff) | |
download | cpu_features-3de70d00295d58f2039cd5589603bf3285ace7e0.tar.gz |
Merge v0.9.0 into `main`.
Test: Run `atest -a --test-mapping external/cpu_features:all` (on
x86-64 and Arm64 devices)
Change-Id: Idaadcf33b0da35104ff68eaf7941d1e7123c31b8
31 files changed, 1366 insertions, 240 deletions
diff --git a/.dockerignore b/.dockerignore index 65950ea..5169bae 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,8 +1,4 @@ # Project Files unneeded by docker -cmake/ci/Makefile -cmake/ci/docker -cmake/ci/doc -cmake/ci/cache .git .gitignore .github @@ -16,6 +12,15 @@ CONTRIBUTORS LICENSE README.md +bazel/ci/Makefile +bazel/ci/docker +bazel/ci/doc + +cmake/ci/Makefile +cmake/ci/docker +cmake/ci/doc +cmake/ci/cache + build/ cmake_build/ build_cross/ diff --git a/.github/workflows/Dockerfile b/.github/workflows/Dockerfile index 8d6f3dc..28371cb 100644 --- a/.github/workflows/Dockerfile +++ b/.github/workflows/Dockerfile @@ -3,3 +3,4 @@ FROM alpine:edge # Install system build dependencies RUN apk add --no-cache git clang-extra-tools +RUN git config --global --add safe.directory /repo diff --git a/.github/workflows/aarch64_linux_bazel.yml b/.github/workflows/aarch64_linux_bazel.yml new file mode 100644 index 0000000..72dbfff --- /dev/null +++ b/.github/workflows/aarch64_linux_bazel.yml @@ -0,0 +1,26 @@ +name: AArch64 Linux Bazel + +on: + push: + pull_request: + schedule: + # min hours day(month) month day(week) + - cron: '0 0 7,22 * *' + +jobs: + # Building using the github runner environement directly. + bazel: + runs-on: ubuntu-latest + steps: + - name: Check out repository code + uses: actions/checkout@v3 + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + - name: Check docker + run: | + docker info + docker buildx ls + - name: Build + run: make --directory=bazel/ci arm64_build + - name: Test + run: make --directory=bazel/ci arm64_test diff --git a/.github/workflows/amd64_freebsd_cmake.yml b/.github/workflows/amd64_freebsd_cmake.yml index 8bad4f8..37c95d7 100644 --- a/.github/workflows/amd64_freebsd_cmake.yml +++ b/.github/workflows/amd64_freebsd_cmake.yml @@ -11,7 +11,7 @@ jobs: # Only MacOS hosted runner provides virtualisation with vagrant/virtualbox installed. # see: https://github.com/actions/virtual-environments/tree/main/images/macos make: - runs-on: macos-10.15 + runs-on: macos-latest steps: - uses: actions/checkout@v2 - name: vagrant version diff --git a/.github/workflows/amd64_linux_bazel.yml b/.github/workflows/amd64_linux_bazel.yml index 599faf5..fcb0ce4 100644 --- a/.github/workflows/amd64_linux_bazel.yml +++ b/.github/workflows/amd64_linux_bazel.yml @@ -13,14 +13,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out repository code - uses: actions/checkout@v2 - - name: Install Bazel + uses: actions/checkout@v3 + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + - name: Check docker run: | - curl -fsSL https://bazel.build/bazel-release.pub.gpg | gpg --dearmor > bazel.gpg - sudo mv bazel.gpg /etc/apt/trusted.gpg.d/ - echo "deb [arch=amd64] https://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list - sudo apt-get update - sudo apt-get install bazel - bazel --version + docker info + docker buildx ls + - name: Build + run: make --directory=bazel/ci amd64_build - name: Test - run: bazel test -s --verbose_failures //... + run: make --directory=bazel/ci amd64_test diff --git a/.github/workflows/amd64_macos_bazel.yml b/.github/workflows/amd64_macos_bazel.yml new file mode 100644 index 0000000..fd1bc5a --- /dev/null +++ b/.github/workflows/amd64_macos_bazel.yml @@ -0,0 +1,35 @@ +name: amd64 MacOS Bazel + +on: + push: + pull_request: + schedule: + # min hours day(month) month day(week) + - cron: '0 0 7,22 * *' + +jobs: + # Building using the github runner environement directly. + bazel: + runs-on: macos-latest + steps: + - name: Check out repository code + uses: actions/checkout@v3 + - name: Install Bazel + run: | + brew update + brew unlink bazelisk + brew install bazel + - name: Check Bazel + run: bazel version + - name: Build + run: > + bazel build + -c opt + --subcommands=true + ... + - name: Test + run: > + bazel test + -c opt + --test_output=errors + ... diff --git a/.github/workflows/clang_format.yml b/.github/workflows/clang_format.yml index 1afd391..2ab0de0 100644 --- a/.github/workflows/clang_format.yml +++ b/.github/workflows/clang_format.yml @@ -7,7 +7,7 @@ jobs: clang-format: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Fetch origin/main run: git fetch origin main - name: List of changed file(s) diff --git a/BUILD.bazel b/BUILD.bazel index 116ef6a..6925944 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -1,7 +1,8 @@ # cpu_features, a cross platform C99 library to get cpu features at runtime. 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_X86_64") +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") package( default_visibility = ["//visibility:public"], @@ -170,7 +171,10 @@ cc_library( name = "hwcaps", srcs = ["src/hwcaps.c"], copts = C99_FLAGS, - defines = ["HAVE_STRONG_GETAUXVAL"], + defines = selects.with_or({ + PLATFORM_OS_MACOS: ["HAVE_DLFCN_H"], + "//conditions:default": ["HAVE_STRONG_GETAUXVAL"], + }), includes = INCLUDES, textual_hdrs = ["include/internal/hwcaps.h"], deps = [ @@ -213,15 +217,18 @@ cc_library( "src/impl_x86_windows.c", ], PLATFORM_CPU_ARM: ["src/impl_arm_linux_or_android.c"], - PLATFORM_CPU_ARM64: ["src/impl_aarch64_linux_or_android.c"], + PLATFORM_CPU_ARM64: [ + "src/impl_aarch64_linux_or_android.c", + "src/impl_aarch64_macos_or_iphone.c", + "src/impl_aarch64_windows.c", + ], PLATFORM_CPU_MIPS: ["src/impl_mips_linux_or_android.c"], PLATFORM_CPU_PPC: ["src/impl_ppc_linux.c"], + PLATFORM_CPU_RISCV32: ["src/impl_riscv_linux.c"], + PLATFORM_CPU_RISCV64: ["src/impl_riscv_linux.c"], }), - copts = C99_FLAGS, - includes = INCLUDES, - textual_hdrs = selects.with_or({ + hdrs = selects.with_or({ PLATFORM_CPU_X86_64: [ - "src/impl_x86__base_implementation.inl", "include/cpuinfo_x86.h", "include/internal/cpuid_x86.h", "include/internal/windows_utils.h", @@ -230,6 +237,19 @@ cc_library( PLATFORM_CPU_ARM64: ["include/cpuinfo_aarch64.h"], PLATFORM_CPU_MIPS: ["include/cpuinfo_mips.h"], PLATFORM_CPU_PPC: ["include/cpuinfo_ppc.h"], + PLATFORM_CPU_RISCV32: ["include/cpuinfo_riscv.h"], + PLATFORM_CPU_RISCV64: ["include/cpuinfo_riscv.h"], + }), + copts = C99_FLAGS, + defines = selects.with_or({ + PLATFORM_OS_MACOS: ["HAVE_SYSCTLBYNAME"], + "//conditions:default": [], + }), + includes = INCLUDES, + textual_hdrs = selects.with_or({ + PLATFORM_CPU_X86_64: ["src/impl_x86__base_implementation.inl"], + PLATFORM_CPU_ARM64: ["src/impl_aarch64__base_implementation.inl"], + "//conditions:default": [], }) + [ "src/define_introspection.inl", "src/define_introspection_and_hwcaps.inl", @@ -257,9 +277,15 @@ cc_library( "src/impl_x86_windows.c", ], PLATFORM_CPU_ARM: ["src/impl_arm_linux_or_android.c"], - PLATFORM_CPU_ARM64: ["src/impl_aarch64_linux_or_android.c"], + PLATFORM_CPU_ARM64: [ + "src/impl_aarch64_linux_or_android.c", + "src/impl_aarch64_macos_or_iphone.c", + "src/impl_aarch64_windows.c", + ], PLATFORM_CPU_MIPS: ["src/impl_mips_linux_or_android.c"], PLATFORM_CPU_PPC: ["src/impl_ppc_linux.c"], + PLATFORM_CPU_RISCV32: ["src/impl_riscv_linux.c"], + PLATFORM_CPU_RISCV64: ["src/impl_riscv_linux.c"], }), hdrs = selects.with_or({ PLATFORM_CPU_X86_64: [ @@ -271,15 +297,21 @@ cc_library( PLATFORM_CPU_ARM64: ["include/cpuinfo_aarch64.h"], PLATFORM_CPU_MIPS: ["include/cpuinfo_mips.h"], PLATFORM_CPU_PPC: ["include/cpuinfo_ppc.h"], + PLATFORM_CPU_RISCV32: ["include/cpuinfo_riscv.h"], + PLATFORM_CPU_RISCV64: ["include/cpuinfo_riscv.h"], }), copts = C99_FLAGS, defines = selects.with_or({ PLATFORM_CPU_X86_64: ["CPU_FEATURES_MOCK_CPUID_X86"], "//conditions:default": [], + }) + selects.with_or({ + PLATFORM_OS_MACOS: ["HAVE_SYSCTLBYNAME"], + "//conditions:default": [], }), includes = INCLUDES, textual_hdrs = selects.with_or({ PLATFORM_CPU_X86_64: ["src/impl_x86__base_implementation.inl"], + PLATFORM_CPU_ARM64: ["src/impl_aarch64__base_implementation.inl"], "//conditions:default": [], }) + [ "src/define_introspection.inl", @@ -304,6 +336,8 @@ cc_test( PLATFORM_CPU_ARM: ["test/cpuinfo_arm_test.cc"], PLATFORM_CPU_MIPS: ["test/cpuinfo_mips_test.cc"], PLATFORM_CPU_PPC: ["test/cpuinfo_ppc_test.cc"], + PLATFORM_CPU_RISCV32: ["test/cpuinfo_riscv_test.cc"], + PLATFORM_CPU_RISCV64: ["test/cpuinfo_riscv_test.cc"], PLATFORM_CPU_X86_64: ["test/cpuinfo_x86_test.cc"], }), includes = INCLUDES, @@ -327,3 +361,18 @@ cc_binary( ":cpuinfo", ], ) + +cc_library( + name = "ndk_compat", + srcs = ["ndk_compat/cpu-features.c"], + copts = C99_FLAGS, + includes = INCLUDES + ["ndk_compat"], + textual_hdrs = ["ndk_compat/cpu-features.h"], + deps = [ + ":cpu_features_macros", + ":cpuinfo", + ":filesystem", + ":stack_line_reader", + ":string_view", + ], +) diff --git a/CMakeLists.txt b/CMakeLists.txt index bcc9bb0..0454967 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.13) # option() honors normal variables. # see: https://cmake.org/cmake/help/git-stage/policy/CMP0077.html @@ -6,10 +6,18 @@ if(POLICY CMP0077) cmake_policy(SET CMP0077 NEW) endif() -project(CpuFeatures VERSION 0.8.0 LANGUAGES C) +project(CpuFeatures VERSION 0.9.0 LANGUAGES C) set(CMAKE_C_STANDARD 99) +# when cpu_features is included as subproject (i.e. using add_subdirectory(cpu_features)) +# in the source tree of a project that uses it, test rules are disabled. +if(NOT CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) + option(BUILD_TESTING "Enable test rule" OFF) +else() + option(BUILD_TESTING "Enable test rule" ON) +endif() + # Default Build Type to be Release if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release" CACHE STRING @@ -17,6 +25,22 @@ if(NOT CMAKE_BUILD_TYPE) FORCE) endif(NOT CMAKE_BUILD_TYPE) +# An option to enable/disable the executable target list_cpu_features. +# Disable it by default if the project is included as a subproject. +if(NOT CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) + option(BUILD_EXECUTABLE "Build list_cpu_features executable." OFF) +else() + option(BUILD_EXECUTABLE "Build list_cpu_features executable." ON) +endif() + +# An option which allows to switch off install steps. Useful for embedding. +# Disable it by default if the project is included as a subproject. +if(NOT CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) + option(ENABLE_INSTALL "Enable install targets" OFF) +else() + option(ENABLE_INSTALL "Enable install targets" ON) +endif() + # BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to make # it prominent in the GUI. # cpu_features uses bit-fields which are - to some extends - implementation-defined (see https://en.cppreference.com/w/c/language/bit_field). @@ -51,14 +75,15 @@ set(PROCESSOR_IS_X86 FALSE) set(PROCESSOR_IS_POWER FALSE) set(PROCESSOR_IS_S390X FALSE) set(PROCESSOR_IS_RISCV FALSE) +set(PROCESSOR_IS_LOONGARCH FALSE) if(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips") set(PROCESSOR_IS_MIPS TRUE) -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64)") +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "(^aarch64)|(^arm64)|(^ARM64)") set(PROCESSOR_IS_AARCH64 TRUE) elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm") set(PROCESSOR_IS_ARM TRUE) -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64)|(AMD64|amd64)|(^i.86$)") +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(x86_64)|(AMD64|amd64)|(^i.86$)") set(PROCESSOR_IS_X86 TRUE) elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)") set(PROCESSOR_IS_POWER TRUE) @@ -66,6 +91,8 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(s390x)") set(PROCESSOR_IS_S390X TRUE) elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^riscv") set(PROCESSOR_IS_RISCV TRUE) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^loongarch") + set(PROCESSOR_IS_LOONGARCH TRUE) endif() macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME) @@ -90,6 +117,8 @@ macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME) list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_s390x.h) elseif(PROCESSOR_IS_RISCV) list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_riscv.h) + elseif(PROCESSOR_IS_LOONGARCH) + list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_loongarch.h) else() message(FATAL_ERROR "Unsupported architectures ${CMAKE_SYSTEM_PROCESSOR}") endif() @@ -147,20 +176,21 @@ target_link_libraries(cpu_features PUBLIC ${CMAKE_DL_LIBS}) target_include_directories(cpu_features PUBLIC $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/cpu_features> ) -if(PROCESSOR_IS_X86) - if(APPLE) - target_compile_definitions(cpu_features PRIVATE HAVE_SYSCTLBYNAME) - endif() + +if(APPLE) + target_compile_definitions(cpu_features PRIVATE HAVE_SYSCTLBYNAME) endif() -add_library(CpuFeature::cpu_features ALIAS cpu_features) +add_library(CpuFeatures::cpu_features ALIAS cpu_features) # # program : list_cpu_features # -add_executable(list_cpu_features ${PROJECT_SOURCE_DIR}/src/utils/list_cpu_features.c) -target_link_libraries(list_cpu_features PRIVATE cpu_features) -add_executable(CpuFeature::list_cpu_features ALIAS list_cpu_features) +if(BUILD_EXECUTABLE) + add_executable(list_cpu_features ${PROJECT_SOURCE_DIR}/src/utils/list_cpu_features.c) + target_link_libraries(list_cpu_features PRIVATE cpu_features) + add_executable(CpuFeatures::list_cpu_features ALIAS list_cpu_features) +endif() # # ndk_compat @@ -226,36 +256,47 @@ endif() # # Install cpu_features and list_cpu_features # - -include(GNUInstallDirs) -install(TARGETS cpu_features list_cpu_features - EXPORT CpuFeaturesTargets - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cpu_features - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} -) -install(EXPORT CpuFeaturesTargets - NAMESPACE CpuFeatures:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeatures - COMPONENT Devel -) -include(CMakePackageConfigHelpers) -configure_package_config_file(cmake/CpuFeaturesConfig.cmake.in - "${PROJECT_BINARY_DIR}/CpuFeaturesConfig.cmake" - INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeatures" - NO_SET_AND_CHECK_MACRO - NO_CHECK_REQUIRED_COMPONENTS_MACRO -) -write_basic_package_version_file( - "${PROJECT_BINARY_DIR}/CpuFeaturesConfigVersion.cmake" - COMPATIBILITY SameMajorVersion -) -install( - FILES +if(ENABLE_INSTALL) + include(GNUInstallDirs) + install(TARGETS cpu_features + EXPORT CpuFeaturesTargets + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cpu_features + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} + ) + if(BUILD_EXECUTABLE) + install(TARGETS list_cpu_features + EXPORT CpuFeaturesTargets + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cpu_features + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} + ) + endif() + install(EXPORT CpuFeaturesTargets + NAMESPACE CpuFeatures:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeatures + COMPONENT Devel + ) + include(CMakePackageConfigHelpers) + configure_package_config_file(cmake/CpuFeaturesConfig.cmake.in "${PROJECT_BINARY_DIR}/CpuFeaturesConfig.cmake" + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeatures" + NO_SET_AND_CHECK_MACRO + NO_CHECK_REQUIRED_COMPONENTS_MACRO + ) + write_basic_package_version_file( "${PROJECT_BINARY_DIR}/CpuFeaturesConfigVersion.cmake" - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeatures" - COMPONENT Devel -) + COMPATIBILITY SameMajorVersion + ) + install( + FILES + "${PROJECT_BINARY_DIR}/CpuFeaturesConfig.cmake" + "${PROJECT_BINARY_DIR}/CpuFeaturesConfigVersion.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeatures" + COMPONENT Devel + ) +endif() @@ -9,11 +9,11 @@ third_party { type: GIT value: "https://github.com/google/cpu_features.git" } - version: "v0.8.0" + version: "v0.9.0" license_type: NOTICE last_upgrade_date { year: 2023 - month: 4 - day: 27 + month: 9 + day: 14 } } @@ -7,36 +7,44 @@ instructions) at runtime. [comment]: <> (The following lines are generated by "scripts/generate_badges.d" that you can run online https://run.dlang.io/) -| Os | amd64 | AArch64 | ARM | MIPS | POWER | RISCV | s390x | -| :-- | --: | --: | --: | --: | --: | --: | --: | -| Linux | [![][i1a0]][l1a0]<br/>[![][i1a1]][l1a1] | [![][i1b0]][l1b0]<br/>![][d1] | [![][i1c0]][l1c0]<br/>![][d1] | [![][i1d0]][l1d0]<br/>![][d1] | [![][i1e0]][l1e0]<br/>![][d1] | [![][i1f0]][l1f0]<br/>![][d1] | [![][i1g0]][l1g0]<br/>![][d1] | -| FreeBSD | [![][i2a0]][l2a0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | -| MacOS | [![][i3a0]][l3a0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | -| Windows | [![][i4a0]][l4a0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | - -[d0]: https://img.shields.io/badge/CMake-N%2FA-lightgrey -[d1]: https://img.shields.io/badge/Bazel-N%2FA-lightgrey -[i1a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_linux_cmake.yml?branch=main&label=CMake -[i1a1]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_linux_bazel.yml?branch=main&label=Bazel -[i1b0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/aarch64_linux_cmake.yml?branch=main&label=CMake -[i1c0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/arm_linux_cmake.yml?branch=main&label=CMake -[i1d0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/mips_linux_cmake.yml?branch=main&label=CMake -[i1e0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/power_linux_cmake.yml?branch=main&label=CMake -[i1f0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/riscv_linux_cmake.yml?branch=main&label=CMake -[i1g0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/s390x_linux_cmake.yml?branch=main&label=CMake -[i2a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_freebsd_cmake.yml?branch=main&label=CMake -[i3a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_macos_cmake.yml?branch=main&label=CMake -[i4a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_windows_cmake.yml?branch=main&label=CMake +| | Linux | FreeBSD | MacOS | Windows | +| :-- | --: | --: | --: | --: | +| amd64 | [![CMake][i1a0]][l1a0]<br/>[![Bazel][i1a1]][l1a1] | [![CMake][i2a0]][l2a0]<br/>![Bazel][d1] | [![CMake][i3a0]][l3a0]<br/>[![Bazel][i3a1]][l3a1] | [![CMake][i4a0]][l4a0]<br/>![Bazel][d1] | +| AArch64 | [![CMake][i1b0]][l1b0]<br/>[![Bazel][i1b1]][l1b1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | +| ARM | [![CMake][i1c0]][l1c0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | +| MIPS | [![CMake][i1d0]][l1d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | +| POWER | [![CMake][i1e0]][l1e0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | +| RISCV | [![CMake][i1f0]][l1f0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | +| LOONGARCH | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | +| s390x | [![CMake][i1h0]][l1h0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | + +[d0]: https://img.shields.io/badge/n%2Fa-lightgrey?&logo=cmake +[d1]: https://img.shields.io/badge/n%2Fa-lightgrey?&logo=data:image/svg%2bxml;base64,PHN2ZyByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNiAuMTZsNS43ODYgNS43ODZMNiAxMS43MzIuMjE0IDUuOTQ2IDYgLjE2MXpNMCA2LjIxNFYxMmw1Ljc4NiA1Ljc4NlYxMkwwIDYuMjE0ek0xOCAuMTZsNS43ODYgNS43ODZMMTggMTEuNzMybC01Ljc4Ni01Ljc4NkwxOCAuMTYxek0yNCA2LjIxNFYxMmwtNS43ODYgNS43ODZWMTJMMjQgNi4yMTR6TTEyIDYuMTZsNS43ODYgNS43ODZMMTIgMTcuNzMybC01Ljc4Ni01Ljc4NkwxMiA2LjE2MXpNMTEuODQgMTguMDU0djUuNzg1bC01Ljc4Ni01Ljc4NXYtNS43ODZsNS43ODUgNS43ODZ6TTEyLjE2IDE4LjA1NGw1Ljc4Ni01Ljc4NnY1Ljc4NmwtNS43ODUgNS43ODV2LTUuNzg1eiIgc3Ryb2tlPSJ0cmFuc3BhcmVudCIgZmlsbD0id2hpdGUiLz48L3N2Zz4= +[i1a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_linux_cmake.yml?branch=main&event=push&label=&logo=cmake +[i1a1]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_linux_bazel.yml?branch=main&event=push&label=&logo=data:image/svg%2bxml;base64,PHN2ZyByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNiAuMTZsNS43ODYgNS43ODZMNiAxMS43MzIuMjE0IDUuOTQ2IDYgLjE2MXpNMCA2LjIxNFYxMmw1Ljc4NiA1Ljc4NlYxMkwwIDYuMjE0ek0xOCAuMTZsNS43ODYgNS43ODZMMTggMTEuNzMybC01Ljc4Ni01Ljc4NkwxOCAuMTYxek0yNCA2LjIxNFYxMmwtNS43ODYgNS43ODZWMTJMMjQgNi4yMTR6TTEyIDYuMTZsNS43ODYgNS43ODZMMTIgMTcuNzMybC01Ljc4Ni01Ljc4NkwxMiA2LjE2MXpNMTEuODQgMTguMDU0djUuNzg1bC01Ljc4Ni01Ljc4NXYtNS43ODZsNS43ODUgNS43ODZ6TTEyLjE2IDE4LjA1NGw1Ljc4Ni01Ljc4NnY1Ljc4NmwtNS43ODUgNS43ODV2LTUuNzg1eiIgc3Ryb2tlPSJ0cmFuc3BhcmVudCIgZmlsbD0id2hpdGUiLz48L3N2Zz4= +[i1b0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/aarch64_linux_cmake.yml?branch=main&event=push&label=&logo=cmake +[i1b1]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/aarch64_linux_bazel.yml?branch=main&event=push&label=&logo=data:image/svg%2bxml;base64,PHN2ZyByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNiAuMTZsNS43ODYgNS43ODZMNiAxMS43MzIuMjE0IDUuOTQ2IDYgLjE2MXpNMCA2LjIxNFYxMmw1Ljc4NiA1Ljc4NlYxMkwwIDYuMjE0ek0xOCAuMTZsNS43ODYgNS43ODZMMTggMTEuNzMybC01Ljc4Ni01Ljc4NkwxOCAuMTYxek0yNCA2LjIxNFYxMmwtNS43ODYgNS43ODZWMTJMMjQgNi4yMTR6TTEyIDYuMTZsNS43ODYgNS43ODZMMTIgMTcuNzMybC01Ljc4Ni01Ljc4NkwxMiA2LjE2MXpNMTEuODQgMTguMDU0djUuNzg1bC01Ljc4Ni01Ljc4NXYtNS43ODZsNS43ODUgNS43ODZ6TTEyLjE2IDE4LjA1NGw1Ljc4Ni01Ljc4NnY1Ljc4NmwtNS43ODUgNS43ODV2LTUuNzg1eiIgc3Ryb2tlPSJ0cmFuc3BhcmVudCIgZmlsbD0id2hpdGUiLz48L3N2Zz4= +[i1c0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/arm_linux_cmake.yml?branch=main&event=push&label=&logo=cmake +[i1d0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/mips_linux_cmake.yml?branch=main&event=push&label=&logo=cmake +[i1e0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/power_linux_cmake.yml?branch=main&event=push&label=&logo=cmake +[i1f0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/riscv_linux_cmake.yml?branch=main&event=push&label=&logo=cmake +[i1h0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/s390x_linux_cmake.yml?branch=main&event=push&label=&logo=cmake +[i2a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_freebsd_cmake.yml?branch=main&event=push&label=&logo=cmake +[i3a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_macos_cmake.yml?branch=main&event=push&label=&logo=cmake +[i3a1]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_macos_bazel.yml?branch=main&event=push&label=&logo=data:image/svg%2bxml;base64,PHN2ZyByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNiAuMTZsNS43ODYgNS43ODZMNiAxMS43MzIuMjE0IDUuOTQ2IDYgLjE2MXpNMCA2LjIxNFYxMmw1Ljc4NiA1Ljc4NlYxMkwwIDYuMjE0ek0xOCAuMTZsNS43ODYgNS43ODZMMTggMTEuNzMybC01Ljc4Ni01Ljc4NkwxOCAuMTYxek0yNCA2LjIxNFYxMmwtNS43ODYgNS43ODZWMTJMMjQgNi4yMTR6TTEyIDYuMTZsNS43ODYgNS43ODZMMTIgMTcuNzMybC01Ljc4Ni01Ljc4NkwxMiA2LjE2MXpNMTEuODQgMTguMDU0djUuNzg1bC01Ljc4Ni01Ljc4NXYtNS43ODZsNS43ODUgNS43ODZ6TTEyLjE2IDE4LjA1NGw1Ljc4Ni01Ljc4NnY1Ljc4NmwtNS43ODUgNS43ODV2LTUuNzg1eiIgc3Ryb2tlPSJ0cmFuc3BhcmVudCIgZmlsbD0id2hpdGUiLz48L3N2Zz4= +[i4a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_windows_cmake.yml?branch=main&event=push&label=&logo=cmake [l1a0]: https://github.com/google/cpu_features/actions/workflows/amd64_linux_cmake.yml [l1a1]: https://github.com/google/cpu_features/actions/workflows/amd64_linux_bazel.yml [l1b0]: https://github.com/google/cpu_features/actions/workflows/aarch64_linux_cmake.yml +[l1b1]: https://github.com/google/cpu_features/actions/workflows/aarch64_linux_bazel.yml [l1c0]: https://github.com/google/cpu_features/actions/workflows/arm_linux_cmake.yml [l1d0]: https://github.com/google/cpu_features/actions/workflows/mips_linux_cmake.yml [l1e0]: https://github.com/google/cpu_features/actions/workflows/power_linux_cmake.yml [l1f0]: https://github.com/google/cpu_features/actions/workflows/riscv_linux_cmake.yml -[l1g0]: https://github.com/google/cpu_features/actions/workflows/s390x_linux_cmake.yml +[l1h0]: https://github.com/google/cpu_features/actions/workflows/s390x_linux_cmake.yml [l2a0]: https://github.com/google/cpu_features/actions/workflows/amd64_freebsd_cmake.yml [l3a0]: https://github.com/google/cpu_features/actions/workflows/amd64_macos_cmake.yml +[l3a1]: https://github.com/google/cpu_features/actions/workflows/amd64_macos_bazel.yml [l4a0]: https://github.com/google/cpu_features/actions/workflows/amd64_windows_cmake.yml ## Table of Contents @@ -178,14 +186,14 @@ flags : aes,avx,cx16,smx,sse4_1,sse4_2,ssse3 <a name="support"></a> ## What's supported -| | x86³ | AArch64 | ARM | MIPS⁴ | POWER | RISCV | s390x | -|---------|:----:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:| -| Linux | yes² | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ | -| FreeBSD | yes² | not yet | not yet | not yet | not yet | N/A | not yet | -| MacOs | yes² | not yet | N/A | N/A | no | N/A | no | -| Windows | yes² | not yet | not yet | N/A | N/A | N/A | N/A | -| Android | yes² | yes¹ | yes¹ | yes¹ | N/A | N/A | N/A | -| iOS | N/A | not yet | not yet | N/A | N/A | N/A | N/A | +| | x86³ | AArch64 | ARM | MIPS⁴ | POWER | RISCV | Loongarch | s390x | +|---------|:----:|:-------:|:-------:|:-------:|:-------:|:-------:|:---------:|:-------:| +| Linux | yes² | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ | +| FreeBSD | yes² | not yet | not yet | not yet | not yet | N/A | not yet | not yet | +| MacOs | yes² | yes⁵ | N/A | N/A | N/A | N/A | N/A | N/A | +| Windows | yes² | not yet | not yet | N/A | N/A | N/A | N/A | N/A | +| Android | yes² | yes¹ | yes¹ | yes¹ | N/A | N/A | N/A | N/A | +| iOS | N/A | not yet | not yet | N/A | N/A | N/A | N/A | N/A | 1. **Features revealed from Linux.** We gather data from several sources depending on availability: @@ -200,6 +208,8 @@ flags : aes,avx,cx16,smx,sse4_1,sse4_2,ssse3 microarchitecture allows the client to reject particular microarchitectures. 4. All flavors of Mips are supported, little and big endian as well as 32/64 bits. +5. **Features revealed from sysctl.** features are retrieved by the `sysctl` + instruction. <a name="ndk"></a> ## Android NDK's drop in replacement diff --git a/bazel/ci/Makefile b/bazel/ci/Makefile new file mode 100644 index 0000000..1967213 --- /dev/null +++ b/bazel/ci/Makefile @@ -0,0 +1,122 @@ +PROJECT := cpu_features +BRANCH := $(shell git rev-parse --abbrev-ref HEAD) +SHA1 := $(shell git rev-parse --verify HEAD) + +# General commands +.PHONY: help +BOLD=\e[1m +RESET=\e[0m + +help: + @echo -e "${BOLD}SYNOPSIS${RESET}" + @echo -e "\tmake <target> [NOCACHE=1]" + @echo + @echo -e "${BOLD}DESCRIPTION${RESET}" + @echo -e "\ttest build inside docker container to have a reproductible build." + @echo + @echo -e "${BOLD}MAKE TARGETS${RESET}" + @echo -e "\t${BOLD}help${RESET}: display this help and exit." + @echo + @echo -e "\t${BOLD}<platform>_<stage>${RESET}: build <stage> docker image using an Ubuntu:latest x86_64 base image." + @echo -e "\t${BOLD}save_<platform>_<stage>${RESET}: Save the <stage> docker image." + @echo -e "\t${BOLD}sh_<platform>_<stage>${RESET}: run a container using the <stage> docker image (debug purpose)." + @echo -e "\t${BOLD}clean_<platform>_<stage>${RESET}: Remove cache and docker image." + @echo + @echo -e "\tWith ${BOLD}<platform>${RESET}:" + @echo -e "\t\t${BOLD}amd64${RESET} (linux/amd64)" + @echo -e "\t\t${BOLD}arm64${RESET} (linux/arm64)" + @echo + @echo -e "\tWith ${BOLD}<stage>${RESET}:" + @echo -e "\t\t${BOLD}env${RESET}" + @echo -e "\t\t${BOLD}devel${RESET}" + @echo -e "\t\t${BOLD}build${RESET}" + @echo -e "\t\t${BOLD}test${RESET}" + @echo -e "\te.g. 'make amd64_build'" + @echo + @echo -e "\t${BOLD}clean${RESET}: Remove cache and ALL docker images." + @echo + @echo -e "\t${BOLD}NOCACHE=1${RESET}: use 'docker build --no-cache' when building container (default use cache)." + @echo -e "\t${BOLD}VERBOSE=1${RESET}: use 'docker build --progress=plain' when building container." + @echo + @echo -e "branch: $(BRANCH)" + @echo -e "sha1: $(SHA1)" + +# Need to add cmd_platform to PHONY otherwise target are ignored since they do not +# contain recipe (using FORCE do not work here) +.PHONY: all +all: build + +# Delete all implicit rules to speed up makefile +MAKEFLAGS += --no-builtin-rules +.SUFFIXES: +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = +# Keep all intermediate files +# ToDo: try to remove it later +.SECONDARY: + +# Docker image name prefix. +IMAGE := ${PROJECT} + +DOCKER_BUILDX_CMD := docker buildx build +ifdef NOCACHE +DOCKER_BUILDX_CMD := ${DOCKER_BUILDX_CMD} --no-cache +endif +ifdef VERBOSE +DOCKER_BUILDX_CMD := ${DOCKER_BUILDX_CMD} --progress=plain +endif +DOCKER_RUN_CMD := docker run --rm --init --net=host + +############ +## NATIVE ## +############ +# ref: https://go.dev/doc/install/source#environment +# ref: https://github.com/containerd/containerd/blob/269548fa27e0089a8b8278fc4fc781d7f65a939b/platforms/platforms.go#L80-L94 +PLATFORMS := amd64 arm64 +STAGES := env devel build test + +define make-platform-stage-target = +$1_$2: docker/Dockerfile + ${DOCKER_BUILDX_CMD} \ + --platform linux/$1 \ + --build-arg PLATFORM="$1" \ + --target=$2 \ + --tag ${IMAGE}:$1_$2 \ + -f $$< ../.. + +save_$1_$2: cache/$1/docker_$2.tar +cache/$1/docker_$2.tar: $1_$2 + @rm -f $$@ + mkdir -p cache/$1 + docker save ${IMAGE}:$1_$2 -o $$@ + +sh_$1_$2: $1_$2 + ${DOCKER_RUN_CMD} --platform linux/$1 -it --name ${IMAGE}_$1_$2 ${IMAGE}:$1_$2 + +clean_$1_$2: + docker image rm -f ${IMAGE}:$1_$2 2>/dev/null + rm -f cache/$1/docker_$2.tar +endef + +define make-platform-target = +$(foreach stage,$(STAGES),$(eval $(call make-platform-stage-target,$1,$(stage)))) + +# merge +.PHONY: clean_$1 +clean_$1: $(addprefix clean_$1_, $(STAGES)) + -rmdir cache/$1 +endef + +$(foreach platform,$(PLATFORMS),$(eval $(call make-platform-target,$(platform)))) + +## MERGE ## +.PHONY: clean +clean: $(addprefix clean_, $(PLATFORMS)) + docker container prune -f + docker image prune -f + -rmdir cache + +.PHONY: distclean +distclean: clean + -docker container rm -f $$(docker container ls -aq) + -docker image rm -f $$(docker image ls -aq) diff --git a/bazel/ci/docker/Dockerfile b/bazel/ci/docker/Dockerfile new file mode 100644 index 0000000..a46b493 --- /dev/null +++ b/bazel/ci/docker/Dockerfile @@ -0,0 +1,37 @@ +# Create a virtual environment with all tools installed +# ref: https://hub.docker.com/_/ubuntu +FROM ubuntu:latest AS env + +# Install system build dependencies +ENV PATH=/usr/local/bin:$PATH +RUN apt-get update -qq \ +&& DEBIAN_FRONTEND=noninteractive apt-get install -yq \ + git wget build-essential \ +&& apt-get clean \ +&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* +ENTRYPOINT ["/usr/bin/bash", "-c"] +CMD ["/usr/bin/bash"] + +# Install Bazelisk +ARG PLATFORM +RUN wget \ + "https://github.com/bazelbuild/bazelisk/releases/download/v1.18.0/bazelisk-linux-${PLATFORM}" \ +&& chmod +x "bazelisk-linux-${PLATFORM}" \ +&& mv "bazelisk-linux-${PLATFORM}" /usr/local/bin/bazel + +FROM env AS devel +WORKDIR /home/project +COPY . . + +FROM devel AS build +RUN bazel version +RUN bazel build \ + -c opt \ + --subcommands=true \ + ... + +FROM build AS test +RUN bazel test \ + -c opt \ + --test_output=errors \ + ... diff --git a/bazel/platforms.bzl b/bazel/platforms.bzl index 5671add..eb025ce 100644 --- a/bazel/platforms.bzl +++ b/bazel/platforms.bzl @@ -9,3 +9,10 @@ PLATFORM_CPU_ARM64 = ("@platforms//cpu:arm64") PLATFORM_CPU_MIPS = ("@platforms//cpu:mips64") PLATFORM_CPU_PPC = ("@platforms//cpu:ppc") + +PLATFORM_CPU_RISCV32 = ("@platforms//cpu:riscv32") + +PLATFORM_CPU_RISCV64 = ("@platforms//cpu:riscv64") + + +PLATFORM_OS_MACOS = ("@platforms//os:macos") diff --git a/cmake/README.md b/cmake/README.md index de33b23..feaa2fb 100644 --- a/cmake/README.md +++ b/cmake/README.md @@ -17,7 +17,7 @@ or add cpu_features as a git-submodule in your project 2- You can then use the cmake command `add_subdirectory()` to include cpu_features directly and use the `cpu_features` target in your project. -3- Add the `CpuFeature::cpu_features` target to the `target_link_libraries()` section of +3- Add the `CpuFeatures::cpu_features` target to the `target_link_libraries()` section of your executable or of your library. ## Disabling tests diff --git a/include/cpu_features_macros.h b/include/cpu_features_macros.h index 215b567..4fe7c3d 100644 --- a/include/cpu_features_macros.h +++ b/include/cpu_features_macros.h @@ -83,6 +83,10 @@ #define CPU_FEATURES_ARCH_RISCV128 #endif +#if defined(__loongarch64) +#define CPU_FEATURES_ARCH_LOONGARCH +#endif + //////////////////////////////////////////////////////////////////////////////// // Os //////////////////////////////////////////////////////////////////////////////// diff --git a/include/cpuinfo_aarch64.h b/include/cpuinfo_aarch64.h index d124b5f..18a3313 100644 --- a/include/cpuinfo_aarch64.h +++ b/include/cpuinfo_aarch64.h @@ -169,6 +169,27 @@ typedef struct { int ecv : 1; // Enhanced counter virtualization. int afp : 1; // Alternate floating-point behaviour. int rpres : 1; // 12-bit reciprocal (square root) estimate precision. + int mte3 : 1; // MTE asymmetric fault handling. + int sme : 1; // Scalable Matrix Extension. + int smei16i64 : 1; // 16-bit to 64-bit integer widening outer product. + int smef64f64 : 1; // FP64 to FP64 outer product. + int smei8i32 : 1; // 8-bit to 32-bit integer widening outer product. + int smef16f32 : 1; // FP16 to FP32 outer product. + int smeb16f32 : 1; // BFloat16 to FP32 outper product. + int smef32f32 : 1; // FP32 to FP32 outer product. + int smefa64 : 1; // Full A64 support for SME in streaming mode. + int wfxt : 1; // WFE and WFI with timeout. + int ebf16 : 1; // Extended BFloat16 instructions. + int sveebf16 : 1; // SVE BFloat16 instructions. + int cssc : 1; // Common short sequence compression instructions. + int rprfm : 1; // Range Prefetch Memory hint instruction. + int sve2p1 : 1; // Scalable Vector Extension (version 2.1). + int sme2 : 1; // Scalable Matrix Extension (version 2). + int sme2p1 : 1; // Scalable Matrix Extension (version 2.1). + int smei16i32 : 1; // 16-bit to 64-bit integer widening outer product. + int smebi32i32 : 1; // 1-bit binary to 32-bit integer outer product. + int smeb16b16 : 1; // SME2.1 BFloat16 instructions. + int smef16f16 : 1; // FP16 to FP16 outer product. // Make sure to update Aarch64FeaturesEnum below if you add a field here. } Aarch64Features; @@ -242,6 +263,27 @@ typedef enum { AARCH64_ECV, AARCH64_AFP, AARCH64_RPRES, + AARCH64_MTE3, + AARCH64_SME, + AARCH64_SME_I16I64, + AARCH64_SME_F64F64, + AARCH64_SME_I8I32, + AARCH64_SME_F16F32, + AARCH64_SME_B16F32, + AARCH64_SME_F32F32, + AARCH64_SME_FA64, + AARCH64_WFXT, + AARCH64_EBF16, + AARCH64_SVE_EBF16, + AARCH64_CSSC, + AARCH64_RPRFM, + AARCH64_SVE2P1, + AARCH64_SME2, + AARCH64_SME2P1, + AARCH64_SME_I16I32, + AARCH64_SME_BI32I32, + AARCH64_SME_B16B16, + AARCH64_SME_F16F16, AARCH64_LAST_, } Aarch64FeaturesEnum; diff --git a/include/cpuinfo_loongarch.h b/include/cpuinfo_loongarch.h new file mode 100644 index 0000000..d166223 --- /dev/null +++ b/include/cpuinfo_loongarch.h @@ -0,0 +1,77 @@ +// 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_CPUINFO_LOONGARCH_H_ +#define CPU_FEATURES_INCLUDE_CPUINFO_LOONGARCH_H_ + +#include "cpu_features_cache_info.h" +#include "cpu_features_macros.h" + +#if !defined(CPU_FEATURES_ARCH_LOONGARCH) +#error "Including cpuinfo_loongarch.h from a non-loongarch target." +#endif + +CPU_FEATURES_START_CPP_NAMESPACE + +typedef struct { + // Base + int CPUCFG : 1; // Instruction for Identify CPU Features + + // Extension + int LAM : 1; // Extension for Atomic Memory Access Instructions + int UAL : 1; // Extension for Non-Aligned Memory Access + int FPU : 1; // Extension for Basic Floating-Point Instructions + int LSX : 1; // Extension for Loongson SIMD eXtension + int LASX : 1; // Extension for Loongson Advanced SIMD eXtension + int CRC32 : 1; // Extension for Cyclic Redundancy Check Instructions + int COMPLEX : 1; // Extension for Complex Vector Operation Instructions + int CRYPTO : 1; // Extension for Encryption And Decryption Vector Instructions + int LVZ : 1; // Extension for Virtualization + int LBT_X86 : 1; // Extension for X86 Binary Translation Extension + int LBT_ARM : 1; // Extension for ARM Binary Translation Extension + int LBT_MIPS : 1; // Extension for MIPS Binary Translation Extension + int PTW : 1; // Extension for Page Table Walker + +} LoongArchFeatures; + +typedef struct { + LoongArchFeatures features; +} LoongArchInfo; + +typedef enum { + LOONGARCH_CPUCFG, + LOONGARCH_LAM, + LOONGARCH_UAL, + LOONGARCH_FPU, + LOONGARCH_LSX, + LOONGARCH_LASX, + LOONGARCH_CRC32, + LOONGARCH_COMPLEX, + LOONGARCH_CRYPTO, + LOONGARCH_LVZ, + LOONGARCH_LBT_X86, + LOONGARCH_LBT_ARM, + LOONGARCH_LBT_MIPS, + LOONGARCH_PTW, + LOONGARCH_LAST_, +} LoongArchFeaturesEnum; + +LoongArchInfo GetLoongArchInfo(void); +int GetLoongArchFeaturesEnumValue(const LoongArchFeatures* features, + LoongArchFeaturesEnum value); +const char* GetLoongArchFeaturesEnumName(LoongArchFeaturesEnum); + +CPU_FEATURES_END_CPP_NAMESPACE + +#endif // CPU_FEATURES_INCLUDE_CPUINFO_LOONGARCH_H_ diff --git a/include/cpuinfo_x86.h b/include/cpuinfo_x86.h index e897500..796d3f3 100644 --- a/include/cpuinfo_x86.h +++ b/include/cpuinfo_x86.h @@ -86,6 +86,7 @@ typedef struct { int amx_bf16 : 1; int amx_tile : 1; int amx_int8 : 1; + int amx_fp16 : 1; int pclmulqdq : 1; int smx : 1; @@ -107,6 +108,9 @@ typedef struct { int fz_rep_movsb : 1; // Fast zero-length REP MOVSB int fs_rep_stosb : 1; // Fast short REP STOSB int fs_rep_cmpsb_scasb : 1; // Fast short REP CMPSB/SCASB + + int lam: 1; // Intel Linear Address Mask + int uai: 1; // AMD Upper Address Ignore // Make sure to update X86FeaturesEnum below if you add a field here. } X86Features; @@ -251,6 +255,7 @@ typedef enum { X86_AMX_BF16, X86_AMX_TILE, X86_AMX_INT8, + X86_AMX_FP16, X86_PCLMULQDQ, X86_SMX, X86_SGX, @@ -270,6 +275,8 @@ typedef enum { X86_FZ_REP_MOVSB, X86_FS_REP_STOSB, X86_FS_REP_CMPSB_SCASB, + X86_LAM, + X86_UAI, X86_LAST_, } X86FeaturesEnum; diff --git a/include/internal/hwcaps.h b/include/internal/hwcaps.h index 3290cc9..59e1657 100644 --- a/include/internal/hwcaps.h +++ b/include/internal/hwcaps.h @@ -83,6 +83,27 @@ CPU_FEATURES_START_CPP_NAMESPACE #define AARCH64_HWCAP2_ECV (1UL << 19) #define AARCH64_HWCAP2_AFP (1UL << 20) #define AARCH64_HWCAP2_RPRES (1UL << 21) +#define AARCH64_HWCAP2_MTE3 (1UL << 22) +#define AARCH64_HWCAP2_SME (1UL << 23) +#define AARCH64_HWCAP2_SME_I16I64 (1UL << 24) +#define AARCH64_HWCAP2_SME_F64F64 (1UL << 25) +#define AARCH64_HWCAP2_SME_I8I32 (1UL << 26) +#define AARCH64_HWCAP2_SME_F16F32 (1UL << 27) +#define AARCH64_HWCAP2_SME_B16F32 (1UL << 28) +#define AARCH64_HWCAP2_SME_F32F32 (1UL << 29) +#define AARCH64_HWCAP2_SME_FA64 (1UL << 30) +#define AARCH64_HWCAP2_WFXT (1UL << 31) +#define AARCH64_HWCAP2_EBF16 (1UL << 32) +#define AARCH64_HWCAP2_SVE_EBF16 (1UL << 33) +#define AARCH64_HWCAP2_CSSC (1UL << 34) +#define AARCH64_HWCAP2_RPRFM (1UL << 35) +#define AARCH64_HWCAP2_SVE2P1 (1UL << 36) +#define AARCH64_HWCAP2_SME2 (1UL << 37) +#define AARCH64_HWCAP2_SME2P1 (1UL << 38) +#define AARCH64_HWCAP2_SME_I16I32 (1UL << 39) +#define AARCH64_HWCAP2_SME_BI32I32 (1UL << 40) +#define AARCH64_HWCAP2_SME_B16B16 (1UL << 41) +#define AARCH64_HWCAP2_SME_F16F16 (1UL << 42) // http://elixir.free-electrons.com/linux/latest/source/arch/arm/include/uapi/asm/hwcap.h #define ARM_HWCAP_SWP (1UL << 0) @@ -216,6 +237,22 @@ CPU_FEATURES_START_CPP_NAMESPACE #define RISCV_HWCAP_C (1UL << ('C' - 'A')) #define RISCV_HWCAP_V (1UL << ('V' - 'A')) +// https://github.com/torvalds/linux/blob/master/arch/loongarch/include/uapi/asm/hwcap.h +#define HWCAP_LOONGARCH_CPUCFG (1 << 0) +#define HWCAP_LOONGARCH_LAM (1 << 1) +#define HWCAP_LOONGARCH_UAL (1 << 2) +#define HWCAP_LOONGARCH_FPU (1 << 3) +#define HWCAP_LOONGARCH_LSX (1 << 4) +#define HWCAP_LOONGARCH_LASX (1 << 5) +#define HWCAP_LOONGARCH_CRC32 (1 << 6) +#define HWCAP_LOONGARCH_COMPLEX (1 << 7) +#define HWCAP_LOONGARCH_CRYPTO (1 << 8) +#define HWCAP_LOONGARCH_LVZ (1 << 9) +#define HWCAP_LOONGARCH_LBT_X86 (1 << 10) +#define HWCAP_LOONGARCH_LBT_ARM (1 << 11) +#define HWCAP_LOONGARCH_LBT_MIPS (1 << 12) +#define HWCAP_LOONGARCH_PTW (1 << 13) + typedef struct { unsigned long hwcaps; unsigned long hwcaps2; diff --git a/scripts/generate_badges.d b/scripts/generate_badges.d index bf5aa54..e5037ef 100644..100755 --- a/scripts/generate_badges.d +++ b/scripts/generate_badges.d @@ -1,11 +1,23 @@ +#!/usr/bin/env -S docker run --rm -v ${PWD}/scripts:/scripts -v ${PWD}/.github/workflows:/.github/workflows dlanguage/dmd dmd -run /scripts/generate_badges.d + +// To run this script: +// cd /path/to/cpu_features +// ./scripts/generate_badges.d + import std.algorithm : each, map, cartesianProduct, filter, joiner, sort, uniq; -import std.array : array; +import std.array; +import std.base64 : Base64; import std.conv : to; +import std.file : exists; import std.format; import std.range : chain, only; import std.stdio; +import std.string : representation; import std.traits : EnumMembers; +immutable string bazel_svg = `<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M6 .16l5.786 5.786L6 11.732.214 5.946 6 .161zM0 6.214V12l5.786 5.786V12L0 6.214zM18 .16l5.786 5.786L18 11.732l-5.786-5.786L18 .161zM24 6.214V12l-5.786 5.786V12L24 6.214zM12 6.16l5.786 5.786L12 17.732l-5.786-5.786L12 6.161zM11.84 18.054v5.785l-5.786-5.785v-5.786l5.785 5.786zM12.16 18.054l5.786-5.786v5.786l-5.785 5.785v-5.785z" stroke="transparent" fill="white"/></svg>`; +const string bazel_svg_base64 = Base64.encode(representation(bazel_svg)); + enum BuildSystem { CMake, @@ -20,6 +32,7 @@ enum Cpu MIPS, POWER, RISCV, + LOONGARCH, s390x, } @@ -39,14 +52,11 @@ const: Os os; BuildSystem build_system; +private: string id() { - return format("%d%c%d", cast(uint)(os) + 1, cast(char)('a' + cpu), cast(uint)(build_system)); - } - - string disabled_image_ref() - { - return format("[d%d]", cast(uint)(build_system)); + return format("%d%c%d", cast(uint)(os) + 1, cast(char)('a' + cpu), + cast(uint)(build_system)); } string link_ref() @@ -59,80 +69,94 @@ const: return format("[i%s]", id()); } + string filename() + { + import std.uni : toLower; + + return toLower(format("%s_%s_%s.yml", cpu, os, build_system)); + } + bool enabled() { + return exists("../.github/workflows/" ~ filename()); + } + + string append_logo(string url) + { final switch (build_system) { case BuildSystem.CMake: - return os == Os.Linux || cpu == Cpu.amd64; + return url ~ "&logo=cmake"; case BuildSystem.Bazel: - return os == Os.Linux && cpu == Cpu.amd64; + return url ~ "&logo=data:image/svg%2bxml;base64," ~ bazel_svg_base64; } } - string text() +public: + + string disabled_image_ref() { - if (enabled()) - return format("[![]%s]%s", image_ref, link_ref); - return format("![]%s", disabled_image_ref); + return format("[d%d]", cast(uint)(build_system)); } - string disabled_image_link() + string text() { - return format("%s: https://img.shields.io/badge/%s-N%%2FA-lightgrey", disabled_image_ref, build_system); + if (enabled()) + return format("[![%s]%s]%s", build_system, image_ref, link_ref); + return format("![%s]%s", build_system, disabled_image_ref); } - string filename() + string disabled_image_link() { - import std.uni : toLower; - - return toLower(format("%s_%s_%s.yml", cpu, os, build_system)); + return append_logo(format("%s: https://img.shields.io/badge/n%%2Fa-lightgrey?", + disabled_image_ref)); } string link_decl() { - return format("%s: https://github.com/google/cpu_features/actions/workflows/%s", link_ref, filename()); + return format("%s: https://github.com/google/cpu_features/actions/workflows/%s", + link_ref, filename()); } string image_decl() { - return format( - "%s: https://img.shields.io/github/actions/workflow/status/google/cpu_features/%s?branch=main&label=%s", image_ref, filename(), build_system); + return append_logo(format("%s: https://img.shields.io/github/actions/workflow/status/google/cpu_features/%s?branch=main&event=push&label=", + image_ref, filename())); } + } -auto tableHeader(in Cpu[] cpus) +auto tableHeader(in Os[] oses) { - return chain(only("Os"), cpus.map!(to!string)).array; + return chain(only(""), oses.map!(to!string)).array; } -auto tableAlignment(in Cpu[] cpus) +auto tableAlignment(in Os[] oses) { - return chain(only(":--"), cpus.map!(v => "--:")).array; + return chain(only(":--"), oses.map!(v => "--:")).array; } auto tableCell(Range)(in Os os, in Cpu cpu, Range badges) { - return badges - .filter!(b => b.cpu == cpu && b.os == os) + return badges.filter!(b => b.cpu == cpu && b.os == os) .map!(b => b.text()) - .joiner("<br/>") - .to!string; + .joiner("<br/>").to!string; } -auto tableRow(Range)(in Os os, in Cpu[] cpus, Range badges) +auto tableRow(Range)(in Cpu cpu, in Os[] oses, Range badges) { - return chain(only(os.to!string), cpus.map!(cpu => tableCell(os, cpu, badges))).array; + return chain(only(cpu.to!string), oses.map!(os => tableCell(os, cpu, badges))).array; } auto tableRows(Range)(in Os[] oses, in Cpu[] cpus, Range badges) { - return oses.map!(os => tableRow(os, cpus, badges)).array; + return cpus.map!(cpu => tableRow(cpu, oses, badges)).array; } auto table(Range)(in Os[] oses, in Cpu[] cpus, Range badges) { - return chain(only(tableHeader(cpus)), only(tableAlignment(cpus)), tableRows(oses, cpus, badges)); + return chain(only(tableHeader(oses)), only(tableAlignment(oses)), + tableRows(oses, cpus, badges)); } void main() @@ -140,26 +164,17 @@ void main() immutable allCpus = [EnumMembers!Cpu]; immutable allOses = [EnumMembers!Os]; immutable allBuildSystems = [EnumMembers!BuildSystem]; - auto badges = cartesianProduct(allCpus, allOses, allBuildSystems).map!( t => Badge(t[0], t[1], t[2])); - writefln("%(|%-( %s |%) |\n%) |", table(allOses, allCpus, badges)); writeln(); - badges - .filter!(b => !b.enabled) + badges.filter!(b => !b.enabled) .map!(b => b.disabled_image_link()) .array .sort .uniq .each!writeln; - - badges - .filter!(b => b.enabled) + badges.filter!(b => b.enabled) .map!(b => [b.link_decl(), b.image_decl()]) - .joiner() - .array - .sort - .uniq - .each!writeln; + .joiner().array.sort.uniq.each!writeln; } diff --git a/src/impl_aarch64__base_implementation.inl b/src/impl_aarch64__base_implementation.inl new file mode 100644 index 0000000..ccc6c11 --- /dev/null +++ b/src/impl_aarch64__base_implementation.inl @@ -0,0 +1,118 @@ +// Copyright 2021 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 <stdbool.h> + +#include "cpu_features_macros.h" +#include "cpuinfo_aarch64.h" +#include "internal/bit_utils.h" +#include "internal/filesystem.h" +#include "internal/stack_line_reader.h" +#include "internal/string_view.h" + +#if !defined(CPU_FEATURES_ARCH_AARCH64) +#error "Cannot compile aarch64_base on a non aarch64 platform." +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Definitions for introspection. +//////////////////////////////////////////////////////////////////////////////// +#define INTROSPECTION_TABLE \ + LINE(AARCH64_FP, fp, "fp", AARCH64_HWCAP_FP, 0) \ + LINE(AARCH64_ASIMD, asimd, "asimd", AARCH64_HWCAP_ASIMD, 0) \ + LINE(AARCH64_EVTSTRM, evtstrm, "evtstrm", AARCH64_HWCAP_EVTSTRM, 0) \ + LINE(AARCH64_AES, aes, "aes", AARCH64_HWCAP_AES, 0) \ + LINE(AARCH64_PMULL, pmull, "pmull", AARCH64_HWCAP_PMULL, 0) \ + LINE(AARCH64_SHA1, sha1, "sha1", AARCH64_HWCAP_SHA1, 0) \ + LINE(AARCH64_SHA2, sha2, "sha2", AARCH64_HWCAP_SHA2, 0) \ + LINE(AARCH64_CRC32, crc32, "crc32", AARCH64_HWCAP_CRC32, 0) \ + LINE(AARCH64_ATOMICS, atomics, "atomics", AARCH64_HWCAP_ATOMICS, 0) \ + LINE(AARCH64_FPHP, fphp, "fphp", AARCH64_HWCAP_FPHP, 0) \ + LINE(AARCH64_ASIMDHP, asimdhp, "asimdhp", AARCH64_HWCAP_ASIMDHP, 0) \ + LINE(AARCH64_CPUID, cpuid, "cpuid", AARCH64_HWCAP_CPUID, 0) \ + LINE(AARCH64_ASIMDRDM, asimdrdm, "asimdrdm", AARCH64_HWCAP_ASIMDRDM, 0) \ + LINE(AARCH64_JSCVT, jscvt, "jscvt", AARCH64_HWCAP_JSCVT, 0) \ + LINE(AARCH64_FCMA, fcma, "fcma", AARCH64_HWCAP_FCMA, 0) \ + LINE(AARCH64_LRCPC, lrcpc, "lrcpc", AARCH64_HWCAP_LRCPC, 0) \ + LINE(AARCH64_DCPOP, dcpop, "dcpop", AARCH64_HWCAP_DCPOP, 0) \ + LINE(AARCH64_SHA3, sha3, "sha3", AARCH64_HWCAP_SHA3, 0) \ + LINE(AARCH64_SM3, sm3, "sm3", AARCH64_HWCAP_SM3, 0) \ + LINE(AARCH64_SM4, sm4, "sm4", AARCH64_HWCAP_SM4, 0) \ + LINE(AARCH64_ASIMDDP, asimddp, "asimddp", AARCH64_HWCAP_ASIMDDP, 0) \ + LINE(AARCH64_SHA512, sha512, "sha512", AARCH64_HWCAP_SHA512, 0) \ + LINE(AARCH64_SVE, sve, "sve", AARCH64_HWCAP_SVE, 0) \ + LINE(AARCH64_ASIMDFHM, asimdfhm, "asimdfhm", AARCH64_HWCAP_ASIMDFHM, 0) \ + LINE(AARCH64_DIT, dit, "dit", AARCH64_HWCAP_DIT, 0) \ + LINE(AARCH64_USCAT, uscat, "uscat", AARCH64_HWCAP_USCAT, 0) \ + LINE(AARCH64_ILRCPC, ilrcpc, "ilrcpc", AARCH64_HWCAP_ILRCPC, 0) \ + LINE(AARCH64_FLAGM, flagm, "flagm", AARCH64_HWCAP_FLAGM, 0) \ + LINE(AARCH64_SSBS, ssbs, "ssbs", AARCH64_HWCAP_SSBS, 0) \ + LINE(AARCH64_SB, sb, "sb", AARCH64_HWCAP_SB, 0) \ + LINE(AARCH64_PACA, paca, "paca", AARCH64_HWCAP_PACA, 0) \ + LINE(AARCH64_PACG, pacg, "pacg", AARCH64_HWCAP_PACG, 0) \ + LINE(AARCH64_DCPODP, dcpodp, "dcpodp", 0, AARCH64_HWCAP2_DCPODP) \ + LINE(AARCH64_SVE2, sve2, "sve2", 0, AARCH64_HWCAP2_SVE2) \ + LINE(AARCH64_SVEAES, sveaes, "sveaes", 0, AARCH64_HWCAP2_SVEAES) \ + LINE(AARCH64_SVEPMULL, svepmull, "svepmull", 0, AARCH64_HWCAP2_SVEPMULL) \ + LINE(AARCH64_SVEBITPERM, svebitperm, "svebitperm", 0, \ + AARCH64_HWCAP2_SVEBITPERM) \ + LINE(AARCH64_SVESHA3, svesha3, "svesha3", 0, AARCH64_HWCAP2_SVESHA3) \ + LINE(AARCH64_SVESM4, svesm4, "svesm4", 0, AARCH64_HWCAP2_SVESM4) \ + LINE(AARCH64_FLAGM2, flagm2, "flagm2", 0, AARCH64_HWCAP2_FLAGM2) \ + LINE(AARCH64_FRINT, frint, "frint", 0, AARCH64_HWCAP2_FRINT) \ + LINE(AARCH64_SVEI8MM, svei8mm, "svei8mm", 0, AARCH64_HWCAP2_SVEI8MM) \ + LINE(AARCH64_SVEF32MM, svef32mm, "svef32mm", 0, AARCH64_HWCAP2_SVEF32MM) \ + LINE(AARCH64_SVEF64MM, svef64mm, "svef64mm", 0, AARCH64_HWCAP2_SVEF64MM) \ + LINE(AARCH64_SVEBF16, svebf16, "svebf16", 0, AARCH64_HWCAP2_SVEBF16) \ + LINE(AARCH64_I8MM, i8mm, "i8mm", 0, AARCH64_HWCAP2_I8MM) \ + LINE(AARCH64_BF16, bf16, "bf16", 0, AARCH64_HWCAP2_BF16) \ + LINE(AARCH64_DGH, dgh, "dgh", 0, AARCH64_HWCAP2_DGH) \ + LINE(AARCH64_RNG, rng, "rng", 0, AARCH64_HWCAP2_RNG) \ + LINE(AARCH64_BTI, bti, "bti", 0, AARCH64_HWCAP2_BTI) \ + LINE(AARCH64_MTE, mte, "mte", 0, AARCH64_HWCAP2_MTE) \ + LINE(AARCH64_ECV, ecv, "ecv", 0, AARCH64_HWCAP2_ECV) \ + LINE(AARCH64_AFP, afp, "afp", 0, AARCH64_HWCAP2_AFP) \ + LINE(AARCH64_RPRES, rpres, "rpres", 0, AARCH64_HWCAP2_RPRES) \ + LINE(AARCH64_MTE3, mte3, "mte3", 0, AARCH64_HWCAP2_MTE3) \ + LINE(AARCH64_SME, sme, "sme", 0, AARCH64_HWCAP2_SME) \ + LINE(AARCH64_SME_I16I64, smei16i64, "smei16i64", 0, \ + AARCH64_HWCAP2_SME_I16I64) \ + LINE(AARCH64_SME_F64F64, smef64f64, "smef64f64", 0, \ + AARCH64_HWCAP2_SME_F64F64) \ + LINE(AARCH64_SME_I8I32, smei8i32, "smei8i32", 0, AARCH64_HWCAP2_SME_I8I32) \ + LINE(AARCH64_SME_F16F32, smef16f32, "smef16f32", 0, \ + AARCH64_HWCAP2_SME_F16F32) \ + LINE(AARCH64_SME_B16F32, smeb16f32, "smeb16f32", 0, \ + AARCH64_HWCAP2_SME_B16F32) \ + LINE(AARCH64_SME_F32F32, smef32f32, "smef32f32", 0, \ + AARCH64_HWCAP2_SME_F32F32) \ + LINE(AARCH64_SME_FA64, smefa64, "smefa64", 0, AARCH64_HWCAP2_SME_FA64) \ + LINE(AARCH64_WFXT, wfxt, "wfxt", 0, AARCH64_HWCAP2_WFXT) \ + LINE(AARCH64_EBF16, ebf16, "ebf16", 0, AARCH64_HWCAP2_EBF16) \ + LINE(AARCH64_SVE_EBF16, sveebf16, "sveebf16", 0, AARCH64_HWCAP2_SVE_EBF16) \ + LINE(AARCH64_CSSC, cssc, "cssc", 0, AARCH64_HWCAP2_CSSC) \ + LINE(AARCH64_RPRFM, rprfm, "rprfm", 0, AARCH64_HWCAP2_RPRFM) \ + LINE(AARCH64_SVE2P1, sve2p1, "sve2p1", 0, AARCH64_HWCAP2_SVE2P1) \ + LINE(AARCH64_SME2, sme2, "sme2", 0, AARCH64_HWCAP2_SME2) \ + LINE(AARCH64_SME2P1, sme2p1, "sme2p1", 0, AARCH64_HWCAP2_SME2P1) \ + LINE(AARCH64_SME_I16I32, smei16i32, "smei16i32", 0, \ + AARCH64_HWCAP2_SME_I16I32) \ + LINE(AARCH64_SME_BI32I32, smebi32i32, "smebi32i32", 0, \ + AARCH64_HWCAP2_SME_BI32I32) \ + LINE(AARCH64_SME_B16B16, smeb16b16, "smeb16b16", 0, \ + AARCH64_HWCAP2_SME_B16B16) \ + LINE(AARCH64_SME_F16F16, smef16f16, "smef16f16", 0, AARCH64_HWCAP2_SME_F16F16) +#define INTROSPECTION_PREFIX Aarch64 +#define INTROSPECTION_ENUM_PREFIX AARCH64 +#include "define_introspection_and_hwcaps.inl" diff --git a/src/impl_aarch64_linux_or_android.c b/src/impl_aarch64_linux_or_android.c index ef923d9..c0a764c 100644 --- a/src/impl_aarch64_linux_or_android.c +++ b/src/impl_aarch64_linux_or_android.c @@ -17,81 +17,7 @@ #ifdef CPU_FEATURES_ARCH_AARCH64 #if defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID) -#include "cpuinfo_aarch64.h" - -//////////////////////////////////////////////////////////////////////////////// -// Definitions for introspection. -//////////////////////////////////////////////////////////////////////////////// -#define INTROSPECTION_TABLE \ - LINE(AARCH64_FP, fp, "fp", AARCH64_HWCAP_FP, 0) \ - LINE(AARCH64_ASIMD, asimd, "asimd", AARCH64_HWCAP_ASIMD, 0) \ - LINE(AARCH64_EVTSTRM, evtstrm, "evtstrm", AARCH64_HWCAP_EVTSTRM, 0) \ - LINE(AARCH64_AES, aes, "aes", AARCH64_HWCAP_AES, 0) \ - LINE(AARCH64_PMULL, pmull, "pmull", AARCH64_HWCAP_PMULL, 0) \ - LINE(AARCH64_SHA1, sha1, "sha1", AARCH64_HWCAP_SHA1, 0) \ - LINE(AARCH64_SHA2, sha2, "sha2", AARCH64_HWCAP_SHA2, 0) \ - LINE(AARCH64_CRC32, crc32, "crc32", AARCH64_HWCAP_CRC32, 0) \ - LINE(AARCH64_ATOMICS, atomics, "atomics", AARCH64_HWCAP_ATOMICS, 0) \ - LINE(AARCH64_FPHP, fphp, "fphp", AARCH64_HWCAP_FPHP, 0) \ - LINE(AARCH64_ASIMDHP, asimdhp, "asimdhp", AARCH64_HWCAP_ASIMDHP, 0) \ - LINE(AARCH64_CPUID, cpuid, "cpuid", AARCH64_HWCAP_CPUID, 0) \ - LINE(AARCH64_ASIMDRDM, asimdrdm, "asimdrdm", AARCH64_HWCAP_ASIMDRDM, 0) \ - LINE(AARCH64_JSCVT, jscvt, "jscvt", AARCH64_HWCAP_JSCVT, 0) \ - LINE(AARCH64_FCMA, fcma, "fcma", AARCH64_HWCAP_FCMA, 0) \ - LINE(AARCH64_LRCPC, lrcpc, "lrcpc", AARCH64_HWCAP_LRCPC, 0) \ - LINE(AARCH64_DCPOP, dcpop, "dcpop", AARCH64_HWCAP_DCPOP, 0) \ - LINE(AARCH64_SHA3, sha3, "sha3", AARCH64_HWCAP_SHA3, 0) \ - LINE(AARCH64_SM3, sm3, "sm3", AARCH64_HWCAP_SM3, 0) \ - LINE(AARCH64_SM4, sm4, "sm4", AARCH64_HWCAP_SM4, 0) \ - LINE(AARCH64_ASIMDDP, asimddp, "asimddp", AARCH64_HWCAP_ASIMDDP, 0) \ - LINE(AARCH64_SHA512, sha512, "sha512", AARCH64_HWCAP_SHA512, 0) \ - LINE(AARCH64_SVE, sve, "sve", AARCH64_HWCAP_SVE, 0) \ - LINE(AARCH64_ASIMDFHM, asimdfhm, "asimdfhm", AARCH64_HWCAP_ASIMDFHM, 0) \ - LINE(AARCH64_DIT, dit, "dit", AARCH64_HWCAP_DIT, 0) \ - LINE(AARCH64_USCAT, uscat, "uscat", AARCH64_HWCAP_USCAT, 0) \ - LINE(AARCH64_ILRCPC, ilrcpc, "ilrcpc", AARCH64_HWCAP_ILRCPC, 0) \ - LINE(AARCH64_FLAGM, flagm, "flagm", AARCH64_HWCAP_FLAGM, 0) \ - LINE(AARCH64_SSBS, ssbs, "ssbs", AARCH64_HWCAP_SSBS, 0) \ - LINE(AARCH64_SB, sb, "sb", AARCH64_HWCAP_SB, 0) \ - LINE(AARCH64_PACA, paca, "paca", AARCH64_HWCAP_PACA, 0) \ - LINE(AARCH64_PACG, pacg, "pacg", AARCH64_HWCAP_PACG, 0) \ - LINE(AARCH64_DCPODP, dcpodp, "dcpodp", 0, AARCH64_HWCAP2_DCPODP) \ - LINE(AARCH64_SVE2, sve2, "sve2", 0, AARCH64_HWCAP2_SVE2) \ - LINE(AARCH64_SVEAES, sveaes, "sveaes", 0, AARCH64_HWCAP2_SVEAES) \ - LINE(AARCH64_SVEPMULL, svepmull, "svepmull", 0, AARCH64_HWCAP2_SVEPMULL) \ - LINE(AARCH64_SVEBITPERM, svebitperm, "svebitperm", 0, \ - AARCH64_HWCAP2_SVEBITPERM) \ - LINE(AARCH64_SVESHA3, svesha3, "svesha3", 0, AARCH64_HWCAP2_SVESHA3) \ - LINE(AARCH64_SVESM4, svesm4, "svesm4", 0, AARCH64_HWCAP2_SVESM4) \ - LINE(AARCH64_FLAGM2, flagm2, "flagm2", 0, AARCH64_HWCAP2_FLAGM2) \ - LINE(AARCH64_FRINT, frint, "frint", 0, AARCH64_HWCAP2_FRINT) \ - LINE(AARCH64_SVEI8MM, svei8mm, "svei8mm", 0, AARCH64_HWCAP2_SVEI8MM) \ - LINE(AARCH64_SVEF32MM, svef32mm, "svef32mm", 0, AARCH64_HWCAP2_SVEF32MM) \ - LINE(AARCH64_SVEF64MM, svef64mm, "svef64mm", 0, AARCH64_HWCAP2_SVEF64MM) \ - LINE(AARCH64_SVEBF16, svebf16, "svebf16", 0, AARCH64_HWCAP2_SVEBF16) \ - LINE(AARCH64_I8MM, i8mm, "i8mm", 0, AARCH64_HWCAP2_I8MM) \ - LINE(AARCH64_BF16, bf16, "bf16", 0, AARCH64_HWCAP2_BF16) \ - LINE(AARCH64_DGH, dgh, "dgh", 0, AARCH64_HWCAP2_DGH) \ - LINE(AARCH64_RNG, rng, "rng", 0, AARCH64_HWCAP2_RNG) \ - LINE(AARCH64_BTI, bti, "bti", 0, AARCH64_HWCAP2_BTI) \ - LINE(AARCH64_MTE, mte, "mte", 0, AARCH64_HWCAP2_MTE) \ - LINE(AARCH64_ECV, ecv, "ecv", 0, AARCH64_HWCAP2_ECV) \ - LINE(AARCH64_AFP, afp, "afp", 0, AARCH64_HWCAP2_AFP) \ - LINE(AARCH64_RPRES, rpres, "rpres", 0, AARCH64_HWCAP2_RPRES) -#define INTROSPECTION_PREFIX Aarch64 -#define INTROSPECTION_ENUM_PREFIX AARCH64 -#include "define_introspection_and_hwcaps.inl" - -//////////////////////////////////////////////////////////////////////////////// -// Implementation. -//////////////////////////////////////////////////////////////////////////////// - -#include <stdbool.h> - -#include "internal/bit_utils.h" -#include "internal/filesystem.h" -#include "internal/stack_line_reader.h" -#include "internal/string_view.h" +#include "impl_aarch64__base_implementation.inl" static bool HandleAarch64Line(const LineResult result, Aarch64Info* const info) { diff --git a/src/impl_aarch64_macos_or_iphone.c b/src/impl_aarch64_macos_or_iphone.c new file mode 100644 index 0000000..7b97896 --- /dev/null +++ b/src/impl_aarch64_macos_or_iphone.c @@ -0,0 +1,88 @@ +// Copyright 2021 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_MACOS) || defined(CPU_FEATURES_OS_IPHONE) + +#include "impl_aarch64__base_implementation.inl" + +#if !defined(HAVE_SYSCTLBYNAME) +#error "Darwin needs support for sysctlbyname" +#endif +#include <sys/sysctl.h> + +#if defined(CPU_FEATURES_MOCK_SYSCTL_AARCH64) +extern bool GetDarwinSysCtlByName(const char*); +extern int GetDarwinSysCtlByNameValue(const char* name); +#else +static int GetDarwinSysCtlByNameValue(const char* name) { + int enabled; + size_t enabled_len = sizeof(enabled); + const int failure = sysctlbyname(name, &enabled, &enabled_len, NULL, 0); + return failure ? 0 : enabled; +} + +static bool GetDarwinSysCtlByName(const char* name) { + return GetDarwinSysCtlByNameValue(name) != 0; +} +#endif + +static const Aarch64Info kEmptyAarch64Info; + +Aarch64Info GetAarch64Info(void) { + Aarch64Info info = kEmptyAarch64Info; + + // Handling Darwin platform through sysctlbyname. + info.implementer = GetDarwinSysCtlByNameValue("hw.cputype"); + info.variant = GetDarwinSysCtlByNameValue("hw.cpusubtype"); + info.part = GetDarwinSysCtlByNameValue("hw.cpufamily"); + info.revision = GetDarwinSysCtlByNameValue("hw.cpusubfamily"); + + info.features.fp = GetDarwinSysCtlByName("hw.optional.floatingpoint"); + info.features.asimd = GetDarwinSysCtlByName("hw.optional.AdvSIMD"); + info.features.aes = GetDarwinSysCtlByName("hw.optional.arm.FEAT_AES"); + info.features.pmull = GetDarwinSysCtlByName("hw.optional.arm.FEAT_PMULL"); + info.features.sha1 = GetDarwinSysCtlByName("hw.optional.arm.FEAT_SHA1"); + info.features.sha2 = GetDarwinSysCtlByName("hw.optional.arm.FEAT_SHA256"); + info.features.crc32 = GetDarwinSysCtlByName("hw.optional.armv8_crc32"); + info.features.atomics = GetDarwinSysCtlByName("hw.optional.arm.FEAT_LSE"); + info.features.fphp = GetDarwinSysCtlByName("hw.optional.arm.FEAT_FP16"); + info.features.asimdhp = GetDarwinSysCtlByName("hw.optional.arm.AdvSIMD_HPFPCvt"); + info.features.asimdrdm = GetDarwinSysCtlByName("hw.optional.arm.FEAT_RDM"); + info.features.jscvt = GetDarwinSysCtlByName("hw.optional.arm.FEAT_JSCVT"); + info.features.fcma = GetDarwinSysCtlByName("hw.optional.arm.FEAT_FCMA"); + info.features.lrcpc = GetDarwinSysCtlByName("hw.optional.arm.FEAT_LRCPC"); + info.features.dcpop = GetDarwinSysCtlByName("hw.optional.arm.FEAT_DPB"); + info.features.sha3 = GetDarwinSysCtlByName("hw.optional.arm.FEAT_SHA3"); + info.features.asimddp = GetDarwinSysCtlByName("hw.optional.arm.FEAT_DotProd"); + info.features.sha512 = GetDarwinSysCtlByName("hw.optional.arm.FEAT_SHA512"); + info.features.asimdfhm = GetDarwinSysCtlByName("hw.optional.arm.FEAT_FHM"); + info.features.dit = GetDarwinSysCtlByName("hw.optional.arm.FEAT_DIT"); + info.features.uscat = GetDarwinSysCtlByName("hw.optional.arm.FEAT_LSE2"); + info.features.flagm = GetDarwinSysCtlByName("hw.optional.arm.FEAT_FlagM"); + info.features.ssbs = GetDarwinSysCtlByName("hw.optional.arm.FEAT_SSBS"); + info.features.sb = GetDarwinSysCtlByName("hw.optional.arm.FEAT_SB"); + info.features.flagm2 = GetDarwinSysCtlByName("hw.optional.arm.FEAT_FlagM2"); + info.features.frint = GetDarwinSysCtlByName("hw.optional.arm.FEAT_FRINTTS"); + info.features.i8mm = GetDarwinSysCtlByName("hw.optional.arm.FEAT_I8MM"); + info.features.bf16 = GetDarwinSysCtlByName("hw.optional.arm.FEAT_BF16"); + info.features.bti = GetDarwinSysCtlByName("hw.optional.arm.FEAT_BTI"); + + return info; +} + +#endif // defined(CPU_FEATURES_OS_MACOS) || defined(CPU_FEATURES_OS_IPHONE) +#endif // CPU_FEATURES_ARCH_AARCH64 diff --git a/src/impl_loongarch_linux.c b/src/impl_loongarch_linux.c new file mode 100644 index 0000000..b9cea7b --- /dev/null +++ b/src/impl_loongarch_linux.c @@ -0,0 +1,89 @@ +// 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_LOONGARCH +#if defined(CPU_FEATURES_OS_LINUX) + +#include "cpuinfo_loongarch.h" + +//////////////////////////////////////////////////////////////////////////////// +// Definitions for introspection. +//////////////////////////////////////////////////////////////////////////////// +#define INTROSPECTION_TABLE \ + LINE(LOONGARCH_CPUCFG, CPUCFG, "cfg", HWCAP_LOONGARCH_CPUCFG, 0) \ + LINE(LOONGARCH_LAM, LAM, "lam", HWCAP_LOONGARCH_LAM, 0) \ + LINE(LOONGARCH_UAL, UAL, "ual", HWCAP_LOONGARCH_UAL, 0) \ + LINE(LOONGARCH_FPU, FPU, "fpu", HWCAP_LOONGARCH_FPU, 0) \ + LINE(LOONGARCH_LSX, LSX, "lsx", HWCAP_LOONGARCH_LSX, 0) \ + LINE(LOONGARCH_LASX, LASX, "lasx", HWCAP_LOONGARCH_LASX, 0) \ + LINE(LOONGARCH_CRC32, CRC32, "crc32", HWCAP_LOONGARCH_CRC32, 0) \ + LINE(LOONGARCH_COMPLEX, COMPLEX, "complex", HWCAP_LOONGARCH_COMPLEX, 0) \ + LINE(LOONGARCH_CRYPTO, CRYPTO, "crypto", HWCAP_LOONGARCH_CRYPTO, 0) \ + LINE(LOONGARCH_LVZ, LVZ, "lvz", HWCAP_LOONGARCH_LVZ, 0) \ + LINE(LOONGARCH_LBT_X86, LBT_X86, "lbt_x86", HWCAP_LOONGARCH_LBT_X86, 0) \ + LINE(LOONGARCH_LBT_ARM, LBT_ARM, "lbt_arm", HWCAP_LOONGARCH_LBT_ARM, 0) \ + LINE(LOONGARCH_LBT_MIPS, LBT_MIPS, "lbt_mips", HWCAP_LOONGARCH_LBT_MIPS, 0) \ + LINE(LOONGARCH_PTW, PTW, "ptw", HWCAP_LOONGARCH_PTW, 0) +#define INTROSPECTION_PREFIX LoongArch +#define INTROSPECTION_ENUM_PREFIX LOONGARCH +#include "define_introspection_and_hwcaps.inl" + +//////////////////////////////////////////////////////////////////////////////// +// Implementation. +//////////////////////////////////////////////////////////////////////////////// + +#include <stdbool.h> +#include <stdio.h> + +#include "internal/filesystem.h" +#include "internal/stack_line_reader.h" + +static const LoongArchInfo kEmptyLoongArchInfo; + +static bool HandleLoongArchLine(const LineResult result, LoongArchInfo* const info) { + StringView line = result.line; + StringView key, value; + if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) { + if (CpuFeatures_StringView_IsEquals(key, str("Features"))) { + for (size_t i = 0; i < LOONGARCH_LAST_; ++i) { + kSetters[i](&info->features, CpuFeatures_StringView_HasWord( + value, kCpuInfoFlags[i], ' ')); + } + } + } + return !result.eof; +} + +static void FillProcCpuInfoData(LoongArchInfo* const info) { + const int fd = CpuFeatures_OpenFile("/proc/cpuinfo"); + if (fd >= 0) { + StackLineReader reader; + StackLineReader_Initialize(&reader, fd); + for (;;) { + if (!HandleLoongArchLine(StackLineReader_NextLine(&reader), info)) break; + } + CpuFeatures_CloseFile(fd); + } +} + +LoongArchInfo GetLoongArchInfo(void) { + LoongArchInfo info = kEmptyLoongArchInfo; + FillProcCpuInfoData(&info); + return info; +} + +#endif // defined(CPU_FEATURES_OS_LINUX) +#endif // CPU_FEATURES_ARCH_LOONGARCH diff --git a/src/impl_x86__base_implementation.inl b/src/impl_x86__base_implementation.inl index 6a34bff..dfff46c 100644 --- a/src/impl_x86__base_implementation.inl +++ b/src/impl_x86__base_implementation.inl @@ -166,6 +166,7 @@ typedef struct { Leaf leaf_80000002; // brand string Leaf leaf_80000003; // brand string Leaf leaf_80000004; // brand string + Leaf leaf_80000021; // AMD Extended Feature Identification 2 } Leaves; static Leaves ReadLeaves(void) { @@ -186,6 +187,7 @@ static Leaves ReadLeaves(void) { .leaf_80000002 = SafeCpuIdEx(max_cpuid_leaf_ext, 0x80000002, 0), .leaf_80000003 = SafeCpuIdEx(max_cpuid_leaf_ext, 0x80000003, 0), .leaf_80000004 = SafeCpuIdEx(max_cpuid_leaf_ext, 0x80000004, 0), + .leaf_80000021 = SafeCpuIdEx(max_cpuid_leaf_ext, 0x80000021, 0), }; } @@ -390,6 +392,7 @@ static void ParseCpuId(const Leaves* leaves, X86Info* info, features->fs_rep_cmpsb_scasb = IsBitSet(leaf_7_1.eax, 12); features->adx = IsBitSet(leaf_7.ebx, 19); features->lzcnt = IsBitSet(leaf_80000001.ecx, 5); + features->lam = IsBitSet(leaf_7_1.eax, 26); ///////////////////////////////////////////////////////////////////////////// // The following section is devoted to Vector Extensions. @@ -447,6 +450,7 @@ static void ParseCpuId(const Leaves* leaves, X86Info* info, features->amx_bf16 = IsBitSet(leaf_7.edx, 22); features->amx_tile = IsBitSet(leaf_7.edx, 24); features->amx_int8 = IsBitSet(leaf_7.edx, 25); + features->amx_fp16 = IsBitSet(leaf_7_1.eax, 21); } } else { // When XCR0 is not available (Atom based or older cpus) we need to defer to @@ -462,6 +466,7 @@ static void ParseCpuId(const Leaves* leaves, X86Info* info, static void ParseExtraAMDCpuId(const Leaves* leaves, X86Info* info, OsPreserves os_preserves) { const Leaf leaf_80000001 = leaves->leaf_80000001; + const Leaf leaf_80000021 = leaves->leaf_80000021; X86Features* const features = &info->features; @@ -472,6 +477,8 @@ static void ParseExtraAMDCpuId(const Leaves* leaves, X86Info* info, if (os_preserves.avx_registers) { features->fma4 = IsBitSet(leaf_80000001.ecx, 16); } + + features->uai = IsBitSet(leaf_80000021.eax, 7); } static const X86Info kEmptyX86Info; @@ -641,6 +648,7 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) { } case CPUID(0x06, 0x97): case CPUID(0x06, 0x9A): + case CPUID(0x06, 0xBE): // https://en.wikichip.org/wiki/intel/microarchitectures/alder_lake return INTEL_ADL; case CPUID(0x06, 0xA5): @@ -811,6 +819,7 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) { case CPUID(0x17, 0x60): case CPUID(0x17, 0x68): case CPUID(0x17, 0x71): + case CPUID(0x17, 0x84): case CPUID(0x17, 0x90): case CPUID(0x17, 0x98): case CPUID(0x17, 0xA0): @@ -827,7 +836,9 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) { // https://en.wikichip.org/wiki/amd/microarchitectures/zen_3 return AMD_ZEN3; case CPUID(0x19, 0x10): + case CPUID(0x19, 0x11): case CPUID(0x19, 0x61): + case CPUID(0x19, 0x74): // https://en.wikichip.org/wiki/amd/microarchitectures/zen_4 return AMD_ZEN4; default: @@ -1966,6 +1977,7 @@ CacheInfo GetX86CacheInfo(void) { LINE(X86_AMX_BF16, amx_bf16, , , ) \ LINE(X86_AMX_TILE, amx_tile, , , ) \ LINE(X86_AMX_INT8, amx_int8, , , ) \ + LINE(X86_AMX_FP16, amx_fp16, , , ) \ LINE(X86_PCLMULQDQ, pclmulqdq, , , ) \ LINE(X86_SMX, smx, , , ) \ LINE(X86_SGX, sgx, , , ) \ @@ -1984,7 +1996,9 @@ CacheInfo GetX86CacheInfo(void) { LINE(X86_FS_REP_MOV, fs_rep_mov, , , ) \ LINE(X86_FZ_REP_MOVSB, fz_rep_movsb, , , ) \ LINE(X86_FS_REP_STOSB, fs_rep_stosb, , , ) \ - LINE(X86_FS_REP_CMPSB_SCASB, fs_rep_cmpsb_scasb, , , ) + LINE(X86_FS_REP_CMPSB_SCASB, fs_rep_cmpsb_scasb, , , ) \ + LINE(X86_LAM, lam, , , ) \ + LINE(X86_UAI, uai, , , ) #define INTROSPECTION_PREFIX X86 #define INTROSPECTION_ENUM_PREFIX X86 #include "define_introspection.inl" diff --git a/src/utils/list_cpu_features.c b/src/utils/list_cpu_features.c index 8226d85..83cd387 100644 --- a/src/utils/list_cpu_features.c +++ b/src/utils/list_cpu_features.c @@ -39,6 +39,8 @@ #include "cpuinfo_s390x.h" #elif defined(CPU_FEATURES_ARCH_RISCV) #include "cpuinfo_riscv.h" +#elif defined(CPU_FEATURES_ARCH_LOONGARCH) +#include "cpuinfo_loongarch.h" #endif // Design principles @@ -215,6 +217,9 @@ DEFINE_ADD_FLAGS(GetS390XFeaturesEnumValue, GetS390XFeaturesEnumName, S390XFeatu #elif defined(CPU_FEATURES_ARCH_RISCV) DEFINE_ADD_FLAGS(GetRiscvFeaturesEnumValue, GetRiscvFeaturesEnumName, RiscvFeatures, RISCV_LAST_) +#elif defined(CPU_FEATURES_ARCH_LOONGARCH) +DEFINE_ADD_FLAGS(GetLoongArchFeaturesEnumValue, GetLoongArchFeaturesEnumName, LoongArchFeatures, + LOONGARCH_LAST_) #endif // Prints a json string with characters escaping. @@ -432,6 +437,10 @@ static Node* CreateTree(void) { AddMapEntry(root, "vendor", CreateString(info.vendor)); AddMapEntry(root, "microarchitecture", CreateString(info.uarch)); AddFlags(root, &info.features); +#elif defined(CPU_FEATURES_ARCH_LOONGARCH) + const LoongArchInfo info = GetLoongArchInfo(); + AddMapEntry(root, "arch", CreateString("loongarch")); + AddFlags(root, &info.features); #endif return root; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f627d74..f21ff98 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -74,8 +74,15 @@ if(PROCESSOR_IS_AARCH64) add_executable(cpuinfo_aarch64_test cpuinfo_aarch64_test.cc ../src/impl_aarch64_linux_or_android.c - ../src/impl_aarch64_windows.c) - target_compile_definitions(cpuinfo_aarch64_test PUBLIC CPU_FEATURES_MOCK_CPUID_AARCH64) + ../src/impl_aarch64_windows.c + ../src/impl_aarch64_macos_or_iphone.c + ) + if(APPLE) + target_compile_definitions(cpuinfo_aarch64_test PUBLIC CPU_FEATURES_MOCK_SYSCTL_AARCH64) + target_compile_definitions(cpuinfo_aarch64_test PRIVATE HAVE_SYSCTLBYNAME) + else() + target_compile_definitions(cpuinfo_aarch64_test PUBLIC CPU_FEATURES_MOCK_CPUID_AARCH64) + endif() target_link_libraries(cpuinfo_aarch64_test all_libraries) add_test(NAME cpuinfo_aarch64_test COMMAND cpuinfo_aarch64_test) endif() @@ -107,3 +114,11 @@ if(PROCESSOR_IS_RISCV) target_link_libraries(cpuinfo_riscv_test all_libraries) add_test(NAME cpuinfo_riscv_test COMMAND cpuinfo_riscv_test) endif() +##------------------------------------------------------------------------------ +## cpuinfo_loongarch_test +if(PROCESSOR_IS_LOONGARCH) + add_executable(cpuinfo_loongarch_test cpuinfo_loongarch_test.cc ../src/impl_loongarch_linux.c) + target_link_libraries(cpuinfo_loongarch_test all_libraries) + add_test(NAME cpuinfo_loongarch_test COMMAND cpuinfo_loongarch_test) +endif() + diff --git a/test/cpuinfo_aarch64_test.cc b/test/cpuinfo_aarch64_test.cc index ef9abae..6aefa6b 100644 --- a/test/cpuinfo_aarch64_test.cc +++ b/test/cpuinfo_aarch64_test.cc @@ -25,8 +25,35 @@ namespace cpu_features { class FakeCpuAarch64 { +#if defined(CPU_FEATURES_OS_LINUX) + // No particular implementation for Linux as we use /proc/cpuinfo +#elif defined(CPU_FEATURES_OS_MACOS) + std::set<std::string> darwin_sysctlbyname_; + std::map<std::string, int> darwin_sysctlbynamevalue_; + + public: + bool GetDarwinSysCtlByName(std::string name) const { + return darwin_sysctlbyname_.count(name); + } + + int GetDarwinSysCtlByNameValue(std::string name) const { + const auto iter = darwin_sysctlbynamevalue_.find(name); + if (iter != darwin_sysctlbynamevalue_.end()) return iter->second; + return 0; + } + + void SetDarwinSysCtlByName(std::string name) { + darwin_sysctlbyname_.insert(name); + } + + void SetDarwinSysCtlByNameValue(std::string name, int value) { + darwin_sysctlbynamevalue_[name] = value; + } +#elif defined(CPU_FEATURES_OS_WINDOWS) + std::set<DWORD> windows_isprocessorfeaturepresent_; + WORD processor_revision_{}; + public: -#if defined(CPU_FEATURES_OS_WINDOWS) bool GetWindowsIsProcessorFeaturePresent(DWORD dwProcessorFeature) { return windows_isprocessorfeaturepresent_.count(dwProcessorFeature); } @@ -42,11 +69,7 @@ class FakeCpuAarch64 { void SetWindowsNativeSystemInfoProcessorRevision(WORD wProcessorRevision) { processor_revision_ = wProcessorRevision; } - - private: - std::set<DWORD> windows_isprocessorfeaturepresent_; - WORD processor_revision_{}; -#endif // CPU_FEATURES_OS_WINDOWS +#endif }; static FakeCpuAarch64* g_fake_cpu_instance = nullptr; @@ -56,7 +79,18 @@ static FakeCpuAarch64& cpu() { return *g_fake_cpu_instance; } -#if defined(CPU_FEATURES_OS_WINDOWS) +// Define OS dependent mock functions +#if defined(CPU_FEATURES_OS_LINUX) +// No particular functions to implement for Linux as we use /proc/cpuinfo +#elif defined(CPU_FEATURES_OS_MACOS) +extern "C" bool GetDarwinSysCtlByName(const char* name) { + return cpu().GetDarwinSysCtlByName(name); +} + +extern "C" int GetDarwinSysCtlByNameValue(const char* name) { + return cpu().GetDarwinSysCtlByNameValue(name); +} +#elif defined(CPU_FEATURES_OS_WINDOWS) extern "C" bool GetWindowsIsProcessorFeaturePresent(DWORD dwProcessorFeature) { return cpu().GetWindowsIsProcessorFeaturePresent(dwProcessorFeature); } @@ -64,7 +98,7 @@ extern "C" bool GetWindowsIsProcessorFeaturePresent(DWORD dwProcessorFeature) { extern "C" WORD GetWindowsNativeSystemInfoProcessorRevision() { return cpu().GetWindowsNativeSystemInfoProcessorRevision(); } -#endif // CPU_FEATURES_OS_WINDOWS +#endif namespace { @@ -80,7 +114,7 @@ class CpuidAarch64Test : public ::testing::Test { } }; -TEST(CpuinfoAarch64Test, Aarch64FeaturesEnum) { +TEST_F(CpuidAarch64Test, Aarch64FeaturesEnum) { const char* last_name = GetAarch64FeaturesEnumName(AARCH64_LAST_); EXPECT_STREQ(last_name, "unknown_feature"); for (int i = static_cast<int>(AARCH64_FP); @@ -93,10 +127,9 @@ TEST(CpuinfoAarch64Test, Aarch64FeaturesEnum) { } } +// OS dependent tests #if defined(CPU_FEATURES_OS_LINUX) -void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); } - -TEST(CpuinfoAarch64Test, FromHardwareCap) { +TEST_F(CpuidAarch64Test, FromHardwareCap) { ResetHwcaps(); SetHardwareCapabilities(AARCH64_HWCAP_FP | AARCH64_HWCAP_AES, 0); GetEmptyFilesystem(); // disabling /proc/cpuinfo @@ -135,7 +168,7 @@ TEST(CpuinfoAarch64Test, FromHardwareCap) { EXPECT_FALSE(info.features.pacg); } -TEST(CpuinfoAarch64Test, FromHardwareCap2) { +TEST_F(CpuidAarch64Test, FromHardwareCap2) { ResetHwcaps(); SetHardwareCapabilities(AARCH64_HWCAP_FP, AARCH64_HWCAP2_SVE2 | AARCH64_HWCAP2_BTI); @@ -164,7 +197,7 @@ TEST(CpuinfoAarch64Test, FromHardwareCap2) { EXPECT_FALSE(info.features.rng); } -TEST(CpuinfoAarch64Test, ARMCortexA53) { +TEST_F(CpuidAarch64Test, ARMCortexA53) { ResetHwcaps(); auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", @@ -244,10 +277,90 @@ CPU revision : 3)"); EXPECT_FALSE(info.features.ecv); EXPECT_FALSE(info.features.afp); EXPECT_FALSE(info.features.rpres); + EXPECT_FALSE(info.features.mte3); + EXPECT_FALSE(info.features.sme); + EXPECT_FALSE(info.features.smei16i64); + EXPECT_FALSE(info.features.smef64f64); + EXPECT_FALSE(info.features.smei8i32); + EXPECT_FALSE(info.features.smef16f32); + EXPECT_FALSE(info.features.smeb16f32); + EXPECT_FALSE(info.features.smef32f32); + EXPECT_FALSE(info.features.smefa64); + EXPECT_FALSE(info.features.wfxt); + EXPECT_FALSE(info.features.ebf16); + EXPECT_FALSE(info.features.sveebf16); + EXPECT_FALSE(info.features.cssc); + EXPECT_FALSE(info.features.rprfm); + EXPECT_FALSE(info.features.sve2p1); + EXPECT_FALSE(info.features.sme2); + EXPECT_FALSE(info.features.sme2p1); + EXPECT_FALSE(info.features.smei16i32); + EXPECT_FALSE(info.features.smebi32i32); + EXPECT_FALSE(info.features.smeb16b16); + EXPECT_FALSE(info.features.smef16f16); } -#endif // CPU_FEATURES_OS_LINUX +#elif defined(CPU_FEATURES_OS_MACOS) +TEST_F(CpuidAarch64Test, FromDarwinSysctlFromName) { + cpu().SetDarwinSysCtlByName("hw.optional.floatingpoint"); + cpu().SetDarwinSysCtlByName("hw.optional.neon"); + cpu().SetDarwinSysCtlByName("hw.optional.AdvSIMD_HPFPCvt"); + cpu().SetDarwinSysCtlByName("hw.optional.arm.FEAT_FP16"); + cpu().SetDarwinSysCtlByName("hw.optional.arm.FEAT_LSE"); + cpu().SetDarwinSysCtlByName("hw.optional.armv8_crc32"); + cpu().SetDarwinSysCtlByName("hw.optional.arm.FEAT_FHM"); + cpu().SetDarwinSysCtlByName("hw.optional.arm.FEAT_SHA512"); + cpu().SetDarwinSysCtlByName("hw.optional.arm.FEAT_SHA3"); + cpu().SetDarwinSysCtlByName("hw.optional.amx_version"); + cpu().SetDarwinSysCtlByName("hw.optional.ucnormal_mem"); + cpu().SetDarwinSysCtlByName("hw.optional.arm64"); -#if defined(CPU_FEATURES_OS_WINDOWS) + cpu().SetDarwinSysCtlByNameValue("hw.cputype", 16777228); + cpu().SetDarwinSysCtlByNameValue("hw.cpusubtype", 2); + cpu().SetDarwinSysCtlByNameValue("hw.cpu64bit", 1); + cpu().SetDarwinSysCtlByNameValue("hw.cpufamily", 458787763); + cpu().SetDarwinSysCtlByNameValue("hw.cpusubfamily", 2); + + const auto info = GetAarch64Info(); + + EXPECT_EQ(info.implementer, 0x100000C); + EXPECT_EQ(info.variant, 2); + EXPECT_EQ(info.part, 0x1B588BB3); + EXPECT_EQ(info.revision, 2); + + EXPECT_TRUE(info.features.fp); + EXPECT_FALSE(info.features.asimd); + EXPECT_FALSE(info.features.evtstrm); + EXPECT_FALSE(info.features.aes); + EXPECT_FALSE(info.features.pmull); + EXPECT_FALSE(info.features.sha1); + EXPECT_FALSE(info.features.sha2); + EXPECT_TRUE(info.features.crc32); + EXPECT_TRUE(info.features.atomics); + EXPECT_TRUE(info.features.fphp); + EXPECT_FALSE(info.features.asimdhp); + EXPECT_FALSE(info.features.cpuid); + EXPECT_FALSE(info.features.asimdrdm); + EXPECT_FALSE(info.features.jscvt); + EXPECT_FALSE(info.features.fcma); + EXPECT_FALSE(info.features.lrcpc); + EXPECT_FALSE(info.features.dcpop); + EXPECT_TRUE(info.features.sha3); + EXPECT_FALSE(info.features.sm3); + EXPECT_FALSE(info.features.sm4); + EXPECT_FALSE(info.features.asimddp); + EXPECT_TRUE(info.features.sha512); + EXPECT_FALSE(info.features.sve); + EXPECT_TRUE(info.features.asimdfhm); + EXPECT_FALSE(info.features.dit); + EXPECT_FALSE(info.features.uscat); + EXPECT_FALSE(info.features.ilrcpc); + EXPECT_FALSE(info.features.flagm); + EXPECT_FALSE(info.features.ssbs); + EXPECT_FALSE(info.features.sb); + EXPECT_FALSE(info.features.paca); + EXPECT_FALSE(info.features.pacg); +} +#elif defined(CPU_FEATURES_OS_WINDOWS) TEST_F(CpuidAarch64Test, WINDOWS_AARCH64_RPI4) { cpu().SetWindowsNativeSystemInfoProcessorRevision(0x03); cpu().SetWindowsIsProcessorFeaturePresent(PF_ARM_VFP_32_REGISTERS_AVAILABLE); @@ -271,6 +384,5 @@ TEST_F(CpuidAarch64Test, WINDOWS_AARCH64_RPI4) { EXPECT_FALSE(info.features.lrcpc); } #endif // CPU_FEATURES_OS_WINDOWS - } // namespace } // namespace cpu_features diff --git a/test/cpuinfo_loongarch_test.cc b/test/cpuinfo_loongarch_test.cc new file mode 100644 index 0000000..14f544f --- /dev/null +++ b/test/cpuinfo_loongarch_test.cc @@ -0,0 +1,179 @@ +// Copyright 2022 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 "cpuinfo_loongarch.h" + +#include "filesystem_for_testing.h" +#include "gtest/gtest.h" +#include "hwcaps_for_testing.h" + +namespace cpu_features { +namespace { + +TEST(CpuinfoLoongArchvTest, UnknownFromCpuInfo) { + ResetHwcaps(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", R"( +system type : generic-loongson-machine + +processor : 0 +package : 0 +core : 0 +CPU Family : Loongson-64bit +Model Name : Loongson-3A5000-HV +CPU Revision : 0x11 +FPU Revision : 0x00 +CPU MHz : 2500.00 +BogoMIPS : 5000.00 +TLB Entries : 2112 +Address Sizes : 48 bits physical, 48 bits virtual +ISA : loongarch32 loongarch64 +Features : cpucfg lam ual fpu lsx lasx crc32 complex crypto lvz lbt_x86 lbt_arm lbt_mips +Hardware Watchpoint : yes, iwatch count: 8, dwatch count: 8 + +processor : 1 +package : 0 +core : 1 +CPU Family : Loongson-64bit +Model Name : Loongson-3A5000-HV +CPU Revision : 0x11 +FPU Revision : 0x00 +CPU MHz : 2500.00 +BogoMIPS : 5000.00 +TLB Entries : 2112 +Address Sizes : 48 bits physical, 48 bits virtual +ISA : loongarch32 loongarch64 +Features : cpucfg lam ual fpu lsx lasx crc32 complex crypto lvz lbt_x86 lbt_arm lbt_mips +Hardware Watchpoint : yes, iwatch count: 8, dwatch count: 8 + +processor : 2 +package : 0 +core : 2 +CPU Family : Loongson-64bit +Model Name : Loongson-3A5000-HV +CPU Revision : 0x11 +FPU Revision : 0x00 +CPU MHz : 2500.00 +BogoMIPS : 5000.00 +TLB Entries : 2112 +Address Sizes : 48 bits physical, 48 bits virtual +ISA : loongarch32 loongarch64 +Features : cpucfg lam ual fpu lsx lasx crc32 complex crypto lvz lbt_x86 lbt_arm lbt_mips +Hardware Watchpoint : yes, iwatch count: 8, dwatch count: 8 + +processor : 3 +package : 0 +core : 3 +CPU Family : Loongson-64bit +Model Name : Loongson-3A5000-HV +CPU Revision : 0x11 +FPU Revision : 0x00 +CPU MHz : 2500.00 +BogoMIPS : 5000.00 +TLB Entries : 2112 +Address Sizes : 48 bits physical, 48 bits virtual +ISA : loongarch32 loongarch64 +Features : cpucfg lam ual fpu lsx lasx crc32 complex crypto lvz lbt_x86 lbt_arm lbt_mips +Hardware Watchpoint : yes, iwatch count: 8, dwatch count: 8)"); + const auto info = GetLoongArchInfo(); + EXPECT_FALSE(info.features.CPUCFG); + EXPECT_TRUE(info.features.LAM); + EXPECT_TRUE(info.features.UAL); + EXPECT_TRUE(info.features.FPU); + EXPECT_TRUE(info.features.LSX); + EXPECT_TRUE(info.features.LASX); + EXPECT_TRUE(info.features.CRC32); + EXPECT_TRUE(info.features.COMPLEX); + EXPECT_TRUE(info.features.CRYPTO); + EXPECT_TRUE(info.features.LVZ); + EXPECT_TRUE(info.features.LBT_X86); + EXPECT_TRUE(info.features.LBT_ARM); + EXPECT_TRUE(info.features.LBT_MIPS); +} + +TEST(CpuinfoLoongArchvTest, QemuCpuInfo) { + ResetHwcaps(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", R"( +system type : generic-loongson-machine + +processor : 0 +package : 0 +core : 0 +CPU Family : Loongson-64bit +Model Name : Loongson-3A5000 +CPU Revision : 0x10 +FPU Revision : 0x01 +CPU MHz : 2000.00 +BogoMIPS : 4000.00 +TLB Entries : 2112 +Address Sizes : 48 bits physical, 48 bits virtual +ISA : loongarch32 loongarch64 +Features : cpucfg lam ual fpu crc32 +Hardware Watchpoint : yes, iwatch count: 0, dwatch count: 0 + +processor : 1 +package : 0 +core : 1 +CPU Family : Loongson-64bit +Model Name : Loongson-3A5000 +CPU Revision : 0x10 +FPU Revision : 0x01 +CPU MHz : 2000.00 +BogoMIPS : 4000.00 +TLB Entries : 2112 +Address Sizes : 48 bits physical, 48 bits virtual +ISA : loongarch32 loongarch64 +Features : cpucfg lam ual fpu crc32 +Hardware Watchpoint : yes, iwatch count: 0, dwatch count: 0 + +processor : 2 +package : 0 +core : 2 +CPU Family : Loongson-64bit +Model Name : Loongson-3A5000 +CPU Revision : 0x10 +FPU Revision : 0x01 +CPU MHz : 2000.00 +BogoMIPS : 4000.00 +TLB Entries : 2112 +Address Sizes : 48 bits physical, 48 bits virtual +ISA : loongarch32 loongarch64 +Features : cpucfg lam ual fpu crc32 +Hardware Watchpoint : yes, iwatch count: 0, dwatch count: 0 + +processor : 3 +package : 0 +core : 3 +CPU Family : Loongson-64bit +Model Name : Loongson-3A5000 +CPU Revision : 0x10 +FPU Revision : 0x01 +CPU MHz : 2000.00 +BogoMIPS : 4000.00 +TLB Entries : 2112 +Address Sizes : 48 bits physical, 48 bits virtual +ISA : loongarch32 loongarch64 +Features : cpucfg lam ual fpu crc32 +Hardware Watchpoint : yes, iwatch count: 0, dwatch count: 0)"); + const auto info = GetLoongArchInfo(); + EXPECT_FALSE(info.features.CPUCFG); + EXPECT_TRUE(info.features.LAM); + EXPECT_TRUE(info.features.UAL); + EXPECT_TRUE(info.features.FPU); + EXPECT_TRUE(info.features.CRC32); +} + +} // namespace +} // namespace cpu_features diff --git a/test/cpuinfo_x86_test.cc b/test/cpuinfo_x86_test.cc index de271cc..328aa5c 100644 --- a/test/cpuinfo_x86_test.cc +++ b/test/cpuinfo_x86_test.cc @@ -184,6 +184,8 @@ TEST_F(CpuidX86Test, SandyBridge) { EXPECT_FALSE(features.movbe); EXPECT_FALSE(features.rdrnd); EXPECT_FALSE(features.adx); + EXPECT_FALSE(features.lam); + EXPECT_FALSE(features.uai); } const int UNDEF = -1; @@ -770,6 +772,20 @@ TEST_F(CpuidX86Test, AMD_K17_ZEN2_XBOX_SERIES_X) { EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_ZEN2); } +// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0880F40_K17_CPUID.txt +TEST_F(CpuidX86Test, AMD_K17_ZEN2_4800S) { + cpu().SetLeaves({ + {{0x00000000, 0}, Leaf{0x00000010, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x00000001, 0}, Leaf{0x00880F40, 0x00100800, 0x7ED8320B, 0x178BFBFF}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD); + EXPECT_EQ(info.family, 0x17); + EXPECT_EQ(info.model, 0x84); + EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_ZEN2); +} + // http://users.atw.hu/instlatx64/HygonGenuine/HygonGenuine0900F02_Hygon_CPUID3.txt TEST_F(CpuidX86Test, AMD_K18_ZEN_DHYANA) { cpu().SetLeaves({ @@ -894,6 +910,7 @@ TEST_F(CpuidX86Test, AMD_K19_ZEN4_RAPHAEL) { {{0x80000002, 0}, Leaf{0x20444D41, 0x657A7952, 0x2035206E, 0x30303637}}, {{0x80000003, 0}, Leaf{0x2D362058, 0x65726F43, 0x6F725020, 0x73736563}}, {{0x80000004, 0}, Leaf{0x2020726F, 0x20202020, 0x20202020, 0x00202020}}, + {{0x80000021, 0}, Leaf{0x00062FCF, 0x0000015C, 0x00000000, 0x00000000}}, }); const auto info = GetX86Info(); @@ -902,9 +919,25 @@ TEST_F(CpuidX86Test, AMD_K19_ZEN4_RAPHAEL) { EXPECT_EQ(info.model, 0x61); EXPECT_STREQ(info.brand_string, "AMD Ryzen 5 7600X 6-Core Processor "); + EXPECT_TRUE(info.features.uai); EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_ZEN4); } +// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0A70F41_K19_Phoenix_03_CPUID.txt +TEST_F(CpuidX86Test, AMD_K19_ZEN4_PHOENIX) { + cpu().SetLeaves({ + {{0x00000000, 0}, Leaf{0x00000010, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x00000001, 0}, Leaf{0x00A70F41, 0x00100800, 0x7EF8320B, 0x178BFBFF}}, + {{0x80000000, 0}, Leaf{0x80000028, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x80000001, 0}, Leaf{0x00A70F41, 0x50000000, 0x75C237FF, 0x2FD3FBFF}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD); + EXPECT_EQ(info.family, 0x19); + EXPECT_EQ(info.model, 0x74); +} + // http://users.atw.hu/instlatx64/HygonGenuine/HygonGenuine0900F11_Hygon_01_CPUID.txt TEST_F(CpuidX86Test, AMD_K18_ZEN_DHYANA_OCTAL_CORE_C86_3250) { cpu().SetLeaves({ @@ -940,6 +973,20 @@ TEST_F(CpuidX86Test, AMD_ZEN2_MENDOCINO) { EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_ZEN2); } +// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0A10F11_K19_Genoa_02_CPUID.txt +TEST_F(CpuidX86Test, AMD_K19_ZEN4_GENOA) { + cpu().SetLeaves({ + {{0x00000000, 0}, Leaf{0x00000010, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x00000001, 0}, Leaf{0x00A10F11, 0x00200800, 0x7EFA320B, 0x178BFBFF}}, + }); + const auto info = GetX86Info(); + + EXPECT_EQ(info.model, 0x11); + EXPECT_EQ(info.family, 0x19); + EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_AUTHENTIC_AMD); + EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_ZEN4); +} + // http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel00906A4_AlderLakeP_00_CPUID.txt TEST_F(CpuidX86Test, INTEL_ALDER_LAKE_AVX_VNNI) { cpu().SetOsBackupsExtendedRegisters(true); @@ -1689,6 +1736,20 @@ TEST_F(CpuidX86Test, INTEL_RAPTOR_LAKE_S) { EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_RPL); } +// http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel00B06E0_AlderLakeN_03_CPUID.txt +TEST_F(CpuidX86Test, INTEL_ALDER_LAKE_N) { + cpu().SetLeaves({ + {{0x00000000, 0}, Leaf{0x00000020, 0x756E6547, 0x6C65746E, 0x49656E69}}, + {{0x00000001, 0}, Leaf{0x000B06E0, 0x00800800, 0x7FFAFBBF, 0xBFEBFBFF}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, CPU_FEATURES_VENDOR_GENUINE_INTEL); + EXPECT_EQ(info.family, 0x06); + EXPECT_EQ(info.model, 0xBE); + EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_ADL); +} + // https://github.com/google/cpu_features/issues/200 // http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel00206F2_Eagleton_CPUID.txt #if defined(CPU_FEATURES_OS_WINDOWS) |