Skip to content
Closed
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
Copy Markdown
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