Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ARM64 detection via asm #186

Closed
wants to merge 14 commits into from
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_arm.h)
elseif(PROCESSOR_IS_AARCH64)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_aarch64.h)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/cpuid_aarch64.h)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/cputype_aarch64.h)
elseif(PROCESSOR_IS_X86)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_x86.h)
list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/cpuid_x86.h)
Expand Down
2 changes: 1 addition & 1 deletion include/cpu_features_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
#define CPU_FEATURES_ARCH_ARM
#endif

#if defined(__aarch64__)
#if (defined(__aarch64__) || defined(__arm64__))
#define CPU_FEATURES_ARCH_AARCH64
#endif

Expand Down
4 changes: 2 additions & 2 deletions include/internal/bit_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ inline static bool IsBitSet(uint32_t reg, uint32_t bit) {
return (reg >> bit) & 0x1;
}

inline static uint32_t ExtractBitRange(uint32_t reg, uint32_t msb,
uint32_t lsb) {
inline static uint64_t ExtractBitRange(uint64_t reg, uint64_t msb,
uint64_t lsb) {
Comment on lines +30 to +31
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed overflow when occurs extract bit range from ID_AA64_*

const uint64_t bits = msb - lsb + 1ULL;
const uint64_t mask = (1ULL << bits) - 1ULL;
assert(msb >= lsb);
Expand Down
34 changes: 34 additions & 0 deletions include/internal/cpuid_aarch64.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// 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.

#ifndef CPU_FEATURES_CPUTYPE_AARCH64_H_
#define CPU_FEATURES_CPUTYPE_AARCH64_H_

#include <stdint.h>

#include "cpu_features_macros.h"

CPU_FEATURES_START_CPP_NAMESPACE

uint64_t GetCpuid_MIDR_EL1();
uint64_t GetCpuid_ID_AA64ISAR0_EL1();
uint64_t GetCpuid_ID_AA64ISAR1_EL1();
uint64_t GetCpuid_ID_AA64PFR0_EL1();
uint64_t GetCpuid_ID_AA64ZFR0_EL1();
uint64_t GetCpuid_ID_AA64MMFR2_EL1();
uint64_t GetCpuid_ID_AA64PFR1_EL1();

CPU_FEATURES_END_CPP_NAMESPACE

#endif // CPU_FEATURES_CPUTYPE_AARCH64_H_
211 changes: 211 additions & 0 deletions include/internal/cputype_aarch64.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
// 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.

#ifndef CPU_FEATURES_CPUTYPE_AARCH64_H_
#define CPU_FEATURES_CPUTYPE_AARCH64_H_

// Arm Architecture Reference Manual Armv8, for A-profile architecture. D13.2.98
// https://elixir.bootlin.com/linux/latest/source/arch/arm64/include/asm/cputype.h

#define MIDR_REVISION_SHIFT 0
#define MIDR_PARTNUM_SHIFT 4
#define MIDR_ARCHITECTURE_SHIFT 16
#define MIDR_IMPLEMENTOR_SHIFT 24

// MIDR: implementor, partnum
#define MIDR_CPU_MODEL_IP(imp, partnum) \
(((imp) << MIDR_IMPLEMENTOR_SHIFT) | (0xF << MIDR_ARCHITECTURE_SHIFT) | \
((partnum) << MIDR_PARTNUM_SHIFT))

// MIDR: implementor, partnum, revision
#define MIDR_CPU_MODEL_IPR(imp, partnum, revision) \
(((imp) << MIDR_IMPLEMENTOR_SHIFT) | (0xF << MIDR_ARCHITECTURE_SHIFT) | \
((partnum) << MIDR_PARTNUM_SHIFT) | ((revision) << MIDR_REVISION_SHIFT))

#define ARM_CPU_IMP_ARM 0x41 // ARM Limited.
#define ARM_CPU_IMP_BRCM 0x42 // Broadcom Corporation.
#define ARM_CPU_IMP_CAVIUM 0x43 // Cavium Inc.
#define CPU_VID_DEC 0x44 // Digital Equipment Corporation.
#define ARM_CPU_IMP_FUJITSU 0x46 // Fujitsu Ltd.
#define ARM_CPU_IMP_HISI 0x48 // HISI
#define ARM_CPU_IMP_INFINEON 0x49 // Infineon Technologies AG.
#define CPU_VID_MOTOROLA 0x4D // Motorola - Freescale Semiconductor Inc.
#define ARM_CPU_IMP_NVIDIA 0x4E // NVIDIA Corporation.
#define ARM_CPU_IMP_APM 0x50 // Applied Micro Circuits Corporation.
#define ARM_CPU_IMP_QCOM 0x51 // Qualcomm Inc.
#define ARM_CPU_IMP_MARVELL 0x56 // Marvell International Ltd.
#define ARM_CPU_IMP_APPLE 0x61 // Apple Inc.
#define ARM_CPU_IMP_INTEL 0x69 // Intel Corporation.
#define ARM_CPU_IMP_AMPERE 0xC0 // Ampere Computing.

#define ARM_CPU_PART_AEM_V8 0xD0F
#define ARM_CPU_PART_FOUNDATION 0xD00
#define ARM_CPU_PART_CORTEX_A57 0xD07
#define ARM_CPU_PART_CORTEX_A72 0xD08
#define ARM_CPU_PART_CORTEX_A53 0xD03
#define ARM_CPU_PART_CORTEX_A73 0xD09
#define ARM_CPU_PART_CORTEX_A75 0xD0A
#define ARM_CPU_PART_CORTEX_A35 0xD04
#define ARM_CPU_PART_CORTEX_A55 0xD05
#define ARM_CPU_PART_CORTEX_A76 0xD0B
#define ARM_CPU_PART_NEOVERSE_N1 0xD0C
#define ARM_CPU_PART_CORTEX_A77 0xD0D

#define APM_CPU_PART_POTENZA 0x000

#define CAVIUM_CPU_PART_THUNDERX 0x0A1
#define CAVIUM_CPU_PART_THUNDERX_81XX 0x0A2
#define CAVIUM_CPU_PART_THUNDERX_83XX 0x0A3
#define CAVIUM_CPU_PART_THUNDERX2 0x0AF

#define BRCM_CPU_PART_BRAHMA_B53 0x100
#define BRCM_CPU_PART_VULCAN 0x516

#define QCOM_CPU_PART_FALKOR_V1 0x800
#define QCOM_CPU_PART_FALKOR 0xC00
#define QCOM_CPU_PART_KRYO 0x200
#define QCOM_CPU_PART_KRYO_2XX_GOLD 0x800
#define QCOM_CPU_PART_KRYO_2XX_SILVER 0x801
#define QCOM_CPU_PART_KRYO_3XX_SILVER 0x803
#define QCOM_CPU_PART_KRYO_4XX_GOLD 0x804
#define QCOM_CPU_PART_KRYO_4XX_SILVER 0x805

#define NVIDIA_CPU_PART_DENVER 0x003
#define NVIDIA_CPU_PART_CARMEL 0x004

#define FUJITSU_CPU_PART_A64FX 0x001

#define HISI_CPU_PART_TSV110 0xD01

#define APPLE_CPU_PART_ICESTORM 0x020
#define APPLE_CPU_PART_FIRESTORM 0x021
#define APPLE_CPU_PART_M1_ICESTORM_TONGA 0x022
#define APPLE_CPU_PART_M1_FIRESTORM_TONGA 0x023

#define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53)
#define MIDR_CORTEX_A53_R3 \
MIDR_CPU_MODEL_IPR(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53, 3)

#define MIDR_CORTEX_A57 \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57)
#define MIDR_CORTEX_A72 \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A72)
#define MIDR_CORTEX_A73 \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A73)
#define MIDR_CORTEX_A75 \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A75)
#define MIDR_CORTEX_A35 \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A35)
#define MIDR_CORTEX_A55 \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A55)
#define MIDR_CORTEX_A76 \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76)
#define MIDR_NEOVERSE_N1 \
MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N1)
#define MIDR_CORTEX_A77 \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A77)

#define MIDR_THUNDERX \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
#define MIDR_THUNDERX_81XX \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
#define MIDR_THUNDERX_83XX \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)
#define MIDR_CAVIUM_THUNDERX2 \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX2)

#define MIDR_BRAHMA_B53 \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_BRCM, BRCM_CPU_PART_BRAHMA_B53)
#define MIDR_BRCM_VULCAN \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_BRCM, BRCM_CPU_PART_VULCAN)

#define MIDR_QCOM_FALKOR_V1 \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR_V1)
#define MIDR_QCOM_FALKOR \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR)
#define MIDR_QCOM_KRYO MIDR_CPU_MODEL_IP(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO)
#define MIDR_QCOM_KRYO_2XX_GOLD \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_2XX_GOLD)
#define MIDR_QCOM_KRYO_2XX_SILVER \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_2XX_SILVER)
#define MIDR_QCOM_KRYO_3XX_SILVER \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_3XX_SILVER)
#define MIDR_QCOM_KRYO_4XX_GOLD \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_4XX_GOLD)
#define MIDR_QCOM_KRYO_4XX_SILVER \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO_4XX_SILVER)

#define MIDR_NVIDIA_DENVER \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_DENVER)
#define MIDR_NVIDIA_CARMEL \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_CARMEL)

#define MIDR_FUJITSU_A64FX \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_FUJITSU, FUJITSU_CPU_PART_A64FX)

#define MIDR_HISI_TSV110 \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_HISI, HISI_CPU_PART_TSV110)

#define MIDR_APPLE_M1_ICESTORM \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM)
#define MIDR_APPLE_M1_FIRESTORM \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM)
#define MIDR_APPLE_M1_ICESTORM_TONGA \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_TONGA)
#define MIDR_APPLE_M1_FIRESTORM_TONGA \
MIDR_CPU_MODEL_IP(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_TONGA)

#define ID_AA64_SCHEME0_SHIFT 0
#define ID_AA64_SCHEME1_SHIFT 4
#define ID_AA64_SCHEME2_SHIFT 8
#define ID_AA64_SCHEME3_SHIFT 12
#define ID_AA64_SCHEME4_SHIFT 16
#define ID_AA64_SCHEME5_SHIFT 20
#define ID_AA64_SCHEME6_SHIFT 24
#define ID_AA64_SCHEME7_SHIFT 28
#define ID_AA64_SCHEME8_SHIFT 32
#define ID_AA64_SCHEME9_SHIFT 36
#define ID_AA64_SCHEME10_SHIFT 40
#define ID_AA64_SCHEME11_SHIFT 44
#define ID_AA64_SCHEME12_SHIFT 48
#define ID_AA64_SCHEME13_SHIFT 52
#define ID_AA64_SCHEME14_SHIFT 56
#define ID_AA64_SCHEME15_SHIFT 60

#define ID_AA64_SCHEME_MODEL(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, \
r12, r13, r14, r15) \
(((r15) << ID_AA64_SCHEME15_SHIFT) | ((r14) << ID_AA64_SCHEME14_SHIFT) | \
((r13) << ID_AA64_SCHEME13_SHIFT) | ((r12) << ID_AA64_SCHEME12_SHIFT) | \
((r11) << ID_AA64_SCHEME11_SHIFT) | ((r10) << ID_AA64_SCHEME10_SHIFT) | \
((r9) << ID_AA64_SCHEME9_SHIFT) | ((r8) << ID_AA64_SCHEME8_SHIFT) | \
((r7) << ID_AA64_SCHEME7_SHIFT) | ((r6) << ID_AA64_SCHEME6_SHIFT) | \
((r5) << ID_AA64_SCHEME5_SHIFT) | ((r4) << ID_AA64_SCHEME4_SHIFT) | \
((r3) << ID_AA64_SCHEME3_SHIFT) | ((r2) << ID_AA64_SCHEME2_SHIFT) | \
((r1) << ID_AA64_SCHEME1_SHIFT) | ((r0) << ID_AA64_SCHEME0_SHIFT))

///////////////////////////////////////////////////////////////////////////////
// ID_AA64ISAR0_EL1
///////////////////////////////////////////////////////////////////////////////
#define ID_AA64ISAR0_EL1_ARM_CORTEX_A53_R3 \
ID_AA64_SCHEME_MODEL(0UL, 2UL, 1UL, 1UL, 1UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, \
0UL, 0UL, 0UL, 0UL, 0UL)

///////////////////////////////////////////////////////////////////////////////
// ID_AA64PFR0_EL1
///////////////////////////////////////////////////////////////////////////////
#define ID_AA64PFR0_EL1_ARM_CORTEX_A53_R3 \
ID_AA64_SCHEME_MODEL(0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, \
0UL, 0UL, 0UL, 0UL, 0UL)

#endif // CPU_FEATURES_CPUTYPE_AARCH64_H_
69 changes: 69 additions & 0 deletions src/define_cpuid_aarch64.inl
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// 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 "stringize.inl"

#define OP0_SHIFT 19
#define OP1_SHIFT 16
#define CRN_SHIFT 12
#define CRM_SHIFT 8
#define OP2_SHIFT 5

#define SYS_REG(op0, op1, crn, crm, op2) \
(((op0) << OP0_SHIFT) | ((op1) << OP1_SHIFT) | ((crn) << CRN_SHIFT) | \
((crm) << CRM_SHIFT) | ((op2) << OP2_SHIFT))

#define SYS_MIDR_EL1 SYS_REG(3, 0, 0, 0, 0)

#define SYS_ID_AA64PFR0_EL1 SYS_REG(3, 0, 0, 4, 0)
#define SYS_ID_AA64PFR1_EL1 SYS_REG(3, 0, 0, 4, 1)
#define SYS_ID_AA64ZFR0_EL1 SYS_REG(3, 0, 0, 4, 4)

#define SYS_ID_AA64ISAR0_EL1 SYS_REG(3, 0, 0, 6, 0)
#define SYS_ID_AA64ISAR1_EL1 SYS_REG(3, 0, 0, 6, 1)

#define SYS_ID_AA64MMFR2_EL1 SYS_REG(3, 0, 0, 7, 2)

#if (defined(CPU_FEATURES_COMPILER_GCC) || defined(CPU_FEATURES_COMPILER_CLANG))
#define EMIT_INST(x) ".inst " STRINGIZE((x)) "\n\t"

#define DEFINE_MRS_MSR_S_REGNUM \
" .irp " \
"num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25, " \
"26,27,28,29,30\n" \
" .equ .L__reg_num_x\\num, \\num\n" \
" .endr\n" \
" .equ .L__reg_num_xzr, 31\n"

#define DEFINE_MRS_S \
DEFINE_MRS_MSR_S_REGNUM \
" .macro mrs_s, rt, sreg\n" EMIT_INST( \
0xD5200000 | (\\sreg) | (.L__reg_num_\\rt)) " .endm\n"

#define UNDEFINE_MRS_S " .purgem mrs_s\n"

#define MRS_S(v, r) \
DEFINE_MRS_S \
" mrs_s " v ", " STRINGIZE(r) "\n" UNDEFINE_MRS_S

// For registers without architectural names.
#define READ_SYS_REG_S(r) \
({ \
uint64_t __val; \
asm volatile(MRS_S("%0", r) : "=r"(__val)); \
__val; \
})
#else
#error "Unsupported compiler, aarch64 cpuid requires either GCC or Clang."
#endif
3 changes: 1 addition & 2 deletions src/define_introspection.inl
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@

#include <stdbool.h>

#define STRINGIZE_(s) #s
#define STRINGIZE(s) STRINGIZE_(s)
#include "stringize.inl"

#define FEAT_TYPE_NAME__(X) X##Features
#define FEAT_TYPE_NAME_(X) FEAT_TYPE_NAME__(X)
Expand Down
Loading