Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/cpuinfo-mock.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ int CPUINFO_ABI cpuinfo_mock_close(int fd);
ssize_t CPUINFO_ABI cpuinfo_mock_read(int fd, void* buffer, size_t capacity);

#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
void CPUINFO_ABI cpuinfo_set_hwcap(uint32_t hwcap);
void CPUINFO_ABI cpuinfo_set_hwcap(uint64_t hwcap);
#endif
#if CPUINFO_ARCH_ARM
void CPUINFO_ABI cpuinfo_set_hwcap2(uint64_t hwcap2);
Expand Down
27 changes: 27 additions & 0 deletions include/cpuinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -1762,6 +1762,9 @@ struct cpuinfo_arm_isa {
bool sme_bi32i32;
bool sme_b16b16;
bool sme_f16f16;
bool fp8;
bool f8dot;
bool f8mm;
uint32_t svelen;
uint32_t smelen;
#endif
Expand Down Expand Up @@ -2072,6 +2075,30 @@ static inline bool cpuinfo_has_arm_i8mm(void) {
#endif
}

static inline bool cpuinfo_has_arm_fp8(void) {
#if CPUINFO_ARCH_ARM64
return cpuinfo_isa.fp8;
#else
return false;
#endif
}

static inline bool cpuinfo_has_arm_f8dot(void) {
#if CPUINFO_ARCH_ARM64
return cpuinfo_isa.f8dot;
#else
return false;
#endif
}

static inline bool cpuinfo_has_arm_f8mm(void) {
#if CPUINFO_ARCH_ARM64
return cpuinfo_isa.f8mm;
#else
return false;
#endif
}

static inline bool cpuinfo_has_arm_aes(void) {
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
return cpuinfo_isa.aes;
Expand Down
2 changes: 1 addition & 1 deletion src/arm/linux/aarch32-isa.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ void cpuinfo_set_wcid(uint32_t wcid) {
#endif

void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo(
uint32_t features,
uint64_t features,
uint64_t features2,
uint32_t midr,
uint32_t architecture_version,
Expand Down
11 changes: 10 additions & 1 deletion src/arm/linux/aarch64-isa.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include <sys/prctl.h>

void cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
uint32_t features,
uint64_t features,
uint64_t features2,
uint32_t midr,
const struct cpuinfo_arm_chipset chipset[restrict static 1],
Expand Down Expand Up @@ -174,6 +174,15 @@ void cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
if (features & CPUINFO_ARM_LINUX_FEATURE_ASIMDFHM) {
isa->fhm = true;
}
if (features2 & CPUINFO_ARM_LINUX_FEATURE2_FP8) {
isa->fp8 = true;
}
if (features2 & CPUINFO_ARM_LINUX_FEATURE2_F8DOT) {
isa->f8dot = true;
}
if (features & CPUINFO_ARM_LINUX_FEATURE_F8MM) {
isa->f8mm = true;
}

#ifndef PR_SVE_GET_VL
#define PR_SVE_GET_VL 51
Expand Down
15 changes: 9 additions & 6 deletions src/arm/linux/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ struct cpuinfo_arm_linux_proc_cpuinfo_cache {
#define CPUINFO_ARM_LINUX_FEATURE_SB UINT32_C(0x20000000)
#define CPUINFO_ARM_LINUX_FEATURE_PACA UINT32_C(0x40000000)
#define CPUINFO_ARM_LINUX_FEATURE_PACG UINT32_C(0x80000000)
#define CPUINFO_ARM_LINUX_FEATURE_F8MM UINT64_C(0x0000000800000000)

#define CPUINFO_ARM_LINUX_FEATURE2_DCPODP UINT32_C(0x00000001)
#define CPUINFO_ARM_LINUX_FEATURE2_SVE2 UINT32_C(0x00000002)
Expand All @@ -145,6 +146,8 @@ struct cpuinfo_arm_linux_proc_cpuinfo_cache {
#define CPUINFO_ARM_LINUX_FEATURE2_SME_BI32I32 UINT64_C(0x0000010000000000)
#define CPUINFO_ARM_LINUX_FEATURE2_SME_B16B16 UINT64_C(0x0000020000000000)
#define CPUINFO_ARM_LINUX_FEATURE2_SME_F16F16 UINT64_C(0x0000040000000000)
#define CPUINFO_ARM_LINUX_FEATURE2_FP8 UINT64_C(0x0008000000000000)
#define CPUINFO_ARM_LINUX_FEATURE2_F8DOT UINT64_C(0x0020000000000000)
#endif

#define CPUINFO_ARM_LINUX_VALID_ARCHITECTURE UINT32_C(0x00010000)
Expand Down Expand Up @@ -179,7 +182,7 @@ struct cpuinfo_arm_linux_processor {
uint32_t architecture_flags;
struct cpuinfo_arm_linux_proc_cpuinfo_cache proc_cpuinfo_cache;
#endif
uint32_t features;
uint64_t features;
uint64_t features2;
/**
* Main ID Register value.
Expand Down Expand Up @@ -302,14 +305,14 @@ CPUINFO_INTERNAL bool cpuinfo_arm_linux_parse_proc_cpuinfo(

#if CPUINFO_ARCH_ARM
CPUINFO_INTERNAL bool cpuinfo_arm_linux_hwcap_from_getauxval(
uint32_t hwcap[restrict static 1],
uint64_t hwcap[restrict static 1],
uint64_t hwcap2[restrict static 1]);
CPUINFO_INTERNAL bool cpuinfo_arm_linux_hwcap_from_procfs(
uint32_t hwcap[restrict static 1],
uint64_t hwcap[restrict static 1],
uint64_t hwcap2[restrict static 1]);

CPUINFO_INTERNAL void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo(
uint32_t features,
uint64_t features,
uint64_t features2,
uint32_t midr,
uint32_t architecture_version,
Expand All @@ -318,11 +321,11 @@ CPUINFO_INTERNAL void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo(
struct cpuinfo_arm_isa isa[restrict static 1]);
#elif CPUINFO_ARCH_ARM64
CPUINFO_INTERNAL void cpuinfo_arm_linux_hwcap_from_getauxval(
uint32_t hwcap[restrict static 1],
uint64_t hwcap[restrict static 1],
uint64_t hwcap2[restrict static 1]);

CPUINFO_INTERNAL void cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
uint32_t features,
uint64_t features,
uint64_t features2,
uint32_t midr,
const struct cpuinfo_arm_chipset chipset[restrict static 1],
Expand Down
6 changes: 6 additions & 0 deletions src/arm/linux/cpuinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,12 @@ static void parse_features(
} else if (memcmp(feature_start, "lrcpc", feature_length) == 0) {
#if CPUINFO_ARCH_ARM64
processor->features |= CPUINFO_ARM_LINUX_FEATURE_LRCPC;
} else if (memcmp(feature_start, "f8cvt", feature_length) == 0) {
processor->features2 |= CPUINFO_ARM_LINUX_FEATURE2_FP8;
} else if (memcmp(feature_start, "f8dp4", feature_length) == 0) {
processor->features2 |= CPUINFO_ARM_LINUX_FEATURE2_F8DOT;
} else if (memcmp(feature_start, "f8mm8", feature_length) == 0) {
processor->features |= CPUINFO_ARM_LINUX_FEATURE_F8MM;
#endif
#if CPUINFO_ARCH_ARM
} else if (memcmp(feature_start, "thumb", feature_length) == 0) {
Expand Down
22 changes: 11 additions & 11 deletions src/arm/linux/hwcap.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
#endif

#if CPUINFO_MOCK
static uint32_t mock_hwcap = 0;
void cpuinfo_set_hwcap(uint32_t hwcap) {
static uint64_t mock_hwcap = 0;
void cpuinfo_set_hwcap(uint64_t hwcap) {
mock_hwcap = hwcap;
}

Expand All @@ -40,7 +40,7 @@ void cpuinfo_set_hwcap2(uint64_t hwcap2) {
#if CPUINFO_ARCH_ARM
typedef unsigned long (*getauxval_function_t)(unsigned long);

bool cpuinfo_arm_linux_hwcap_from_getauxval(uint32_t hwcap[restrict static 1], uint64_t hwcap2[restrict static 1]) {
bool cpuinfo_arm_linux_hwcap_from_getauxval(uint64_t hwcap[restrict static 1], uint64_t hwcap2[restrict static 1]) {
#if CPUINFO_MOCK
*hwcap = mock_hwcap;
*hwcap2 = mock_hwcap2;
Expand All @@ -63,8 +63,8 @@ bool cpuinfo_arm_linux_hwcap_from_getauxval(uint32_t hwcap[restrict static 1], u
goto cleanup;
}

*hwcap = getauxval(AT_HWCAP);
*hwcap2 = getauxval(AT_HWCAP2);
*hwcap = (uint64_t)getauxval(AT_HWCAP);
*hwcap2 = (uint64_t)getauxval(AT_HWCAP2);

cleanup:
if (libc != NULL) {
Expand All @@ -74,16 +74,16 @@ bool cpuinfo_arm_linux_hwcap_from_getauxval(uint32_t hwcap[restrict static 1], u
return getauxval != NULL;
#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) && (__GLIBC__ > 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ >= 16)
/* GNU/Linux: getauxval is supported since glibc-2.16 */
*hwcap = getauxval(AT_HWCAP);
*hwcap2 = getauxval(AT_HWCAP2);
*hwcap = (uint64_t)getauxval(AT_HWCAP);
*hwcap2 = (uint64_t)getauxval(AT_HWCAP2);
return true;
#else
return false;
#endif
}

#ifdef __ANDROID__
bool cpuinfo_arm_linux_hwcap_from_procfs(uint32_t hwcap[restrict static 1], uint64_t hwcap2[restrict static 1]) {
bool cpuinfo_arm_linux_hwcap_from_procfs(uint64_t hwcap[restrict static 1], uint64_t hwcap2[restrict static 1]) {
#if CPUINFO_MOCK
*hwcap = mock_hwcap;
*hwcap2 = mock_hwcap2;
Expand All @@ -110,7 +110,7 @@ bool cpuinfo_arm_linux_hwcap_from_procfs(uint32_t hwcap[restrict static 1], uint
if (bytes_read == sizeof(elf_auxv)) {
switch (elf_auxv.a_type) {
case AT_HWCAP:
hwcaps[0] = (uint32_t)elf_auxv.a_un.a_val;
hwcaps[0] = elf_auxv.a_un.a_val;
break;
case AT_HWCAP2:
hwcaps[1] = (uint64_t)elf_auxv.a_un.a_val;
Expand Down Expand Up @@ -141,12 +141,12 @@ bool cpuinfo_arm_linux_hwcap_from_procfs(uint32_t hwcap[restrict static 1], uint
}
#endif /* __ANDROID__ */
#elif CPUINFO_ARCH_ARM64
void cpuinfo_arm_linux_hwcap_from_getauxval(uint32_t hwcap[restrict static 1], uint64_t hwcap2[restrict static 1]) {
void cpuinfo_arm_linux_hwcap_from_getauxval(uint64_t hwcap[restrict static 1], uint64_t hwcap2[restrict static 1]) {
#if CPUINFO_MOCK
*hwcap = mock_hwcap;
*hwcap2 = mock_hwcap2;
#else
*hwcap = (uint32_t)getauxval(AT_HWCAP);
*hwcap = (uint64_t)getauxval(AT_HWCAP);
*hwcap2 = (uint64_t)getauxval(AT_HWCAP2);
return;
#endif
Expand Down
4 changes: 2 additions & 2 deletions src/arm/linux/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ void cpuinfo_arm_linux_init(void) {
#endif

#if CPUINFO_ARCH_ARM
uint32_t isa_features = 0;
uint64_t isa_features = 0;
uint64_t isa_features2 = 0;
#ifdef __ANDROID__
/*
Expand Down Expand Up @@ -388,7 +388,7 @@ void cpuinfo_arm_linux_init(void) {
&chipset,
&cpuinfo_isa);
#elif CPUINFO_ARCH_ARM64
uint32_t isa_features = 0;
uint64_t isa_features = 0;
uint64_t isa_features2 = 0;
/* getauxval is always available on ARM64 Android */
cpuinfo_arm_linux_hwcap_from_getauxval(&isa_features, &isa_features2);
Expand Down
3 changes: 3 additions & 0 deletions src/arm/mach/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,9 @@ void cpuinfo_arm_mach_init(void) {
cpuinfo_isa.sme_bi32i32 = get_sys_info_by_name("hw.optional.arm.SME_BI32I32") != 0;
cpuinfo_isa.sme_b16b16 = get_sys_info_by_name("hw.optional.arm.FEAT_SME_B16B16") != 0;
cpuinfo_isa.sme_f16f16 = get_sys_info_by_name("hw.optional.arm.FEAT_SME_F16F16") != 0;
cpuinfo_isa.fp8 = get_sys_info_by_name("hw.optional.arm.FEAT_FP8") != 0;
cpuinfo_isa.f8dot = get_sys_info_by_name("hw.optional.arm.FEAT_FP8DOT4") != 0;
cpuinfo_isa.f8mm = get_sys_info_by_name("hw.optional.arm.FEAT_F8F32MM") != 0;

cpuinfo_isa.smelen = get_sys_info_by_name("hw.optional.arm.sme_max_svl_b");

Expand Down
9 changes: 9 additions & 0 deletions src/arm/windows/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,15 @@ static void set_cpuinfo_isa_fields(void) {
// - sme_bi32i32

cpuinfo_isa.bf16 = IsProcessorFeaturePresent(PF_ARM_V86_BF16_INSTRUCTIONS_AVAILABLE) != 0;
#if defined(PF_ARM_V87_FP8_INSTRUCTIONS_AVAILABLE)
cpuinfo_isa.fp8 = IsProcessorFeaturePresent(PF_ARM_V87_FP8_INSTRUCTIONS_AVAILABLE) != 0;
#endif
#if defined(PF_ARM_V87_FP8_DOT4_INSTRUCTIONS_AVAILABLE)
cpuinfo_isa.f8dot = IsProcessorFeaturePresent(PF_ARM_V87_FP8_DOT4_INSTRUCTIONS_AVAILABLE) != 0;
#endif
#if defined(PF_ARM_V87_FP8_F32MM_INSTRUCTIONS_AVAILABLE)
cpuinfo_isa.f8mm = IsProcessorFeaturePresent(PF_ARM_V87_FP8_F32MM_INSTRUCTIONS_AVAILABLE) != 0;
#endif

// TODO: This is not available in the Windows SDK yet , so conservatively go with the lowest value (128 bits)
// https://developer.arm.com/documentation/101427/0102/Register-descriptions/Scalable-vector-extensions--SVE--registers/ZCR-EL1--SVE-Control-Register--EL1
Expand Down
12 changes: 12 additions & 0 deletions test/mock/pixel-8.cc
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,18 @@ TEST(ISA, crc32) {
ASSERT_TRUE(cpuinfo_has_arm_crc32());
}

TEST(ISA, fp8) {
ASSERT_FALSE(cpuinfo_has_arm_fp8());
}

TEST(ISA, f8dot) {
ASSERT_FALSE(cpuinfo_has_arm_f8dot());
}

TEST(ISA, f8mm) {
ASSERT_FALSE(cpuinfo_has_arm_f8mm());
}

TEST(L1I, count) {
ASSERT_EQ(9, cpuinfo_get_l1i_caches_count());
}
Expand Down
3 changes: 3 additions & 0 deletions tools/isa-info.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@ int main(int argc, char** argv) {
printf("\tARM v8.2 Int8 matrix multiplication: %s\n", cpuinfo_has_arm_i8mm() ? "yes" : "no");
printf("\tARM v8.3 JS conversion: %s\n", cpuinfo_has_arm_jscvt() ? "yes" : "no");
printf("\tARM v8.3 complex: %s\n", cpuinfo_has_arm_fcma() ? "yes" : "no");
printf("\tARM v8.7 FP8: %s\n", cpuinfo_has_arm_fp8() ? "yes" : "no");
printf("\tARM v8.7 FP8 dot product: %s\n", cpuinfo_has_arm_f8dot() ? "yes" : "no");
printf("\tARM v8.7 FP8 matrix multiplication: %s\n", cpuinfo_has_arm_f8mm() ? "yes" : "no");

printf("SIMD extensions:\n");
printf("\tARM SVE: %s\n", cpuinfo_has_arm_sve() ? "yes" : "no");
Expand Down
Loading