diff options
author | Martin Storsjö <martin@martin.st> | 2023-05-25 15:47:15 +0300 |
---|---|---|
committer | Martin Storsjö <martin@martin.st> | 2023-06-06 12:40:57 +0300 |
commit | 493fcde50a84cb23854335bcb0e55c6f383d55db (patch) | |
tree | 3f7c40669b1a45ee1f6c00f858b8e387399796cf | |
parent | 397cb623c85a515663f410821ba2dded3404112f (diff) | |
download | ffmpeg-493fcde50a84cb23854335bcb0e55c6f383d55db.tar.gz |
aarch64: Add Linux runtime cpu feature detection using HWCAP_CPUID
Based partially on code by Janne Grunau.
Signed-off-by: Martin Storsjö <martin@martin.st>
-rwxr-xr-x | configure | 2 | ||||
-rw-r--r-- | libavutil/aarch64/cpu.c | 52 |
2 files changed, 54 insertions, 0 deletions
@@ -2209,6 +2209,7 @@ HAVE_LIST_PUB=" HEADERS_LIST=" arpa_inet_h + asm_hwcap_h asm_types_h cdio_paranoia_h cdio_paranoia_paranoia_h @@ -6432,6 +6433,7 @@ check_headers io.h enabled libdrm && check_headers linux/dma-buf.h +check_headers asm/hwcap.h check_headers linux/perf_event.h check_headers libcrystalhd/libcrystalhd_if.h check_headers malloc.h diff --git a/libavutil/aarch64/cpu.c b/libavutil/aarch64/cpu.c index 0c76f5ad15..025bf30828 100644 --- a/libavutil/aarch64/cpu.c +++ b/libavutil/aarch64/cpu.c @@ -20,6 +20,56 @@ #include "libavutil/cpu_internal.h" #include "config.h" +#if (defined(__linux__) || defined(__ANDROID__)) && HAVE_GETAUXVAL && HAVE_ASM_HWCAP_H +#include <stdint.h> +#include <asm/hwcap.h> +#include <sys/auxv.h> + +#define get_cpu_feature_reg(reg, val) \ + __asm__("mrs %0, " #reg : "=r" (val)) + +static int detect_flags(void) +{ + int flags = 0; + unsigned long hwcap; + + hwcap = getauxval(AT_HWCAP); + +#if defined(HWCAP_CPUID) + // We can check for DOTPROD and I8MM using HWCAP_ASIMDDP and + // HWCAP2_I8MM too, avoiding to read the CPUID registers (which triggers + // a trap, handled by the kernel). However the HWCAP_* defines for these + // extensions are added much later than HWCAP_CPUID, so the userland + // headers might lack support for them even if the binary later is run + // on hardware that does support it (and where the kernel might support + // HWCAP_CPUID). + // See https://www.kernel.org/doc/html/latest/arm64/cpu-feature-registers.html + if (hwcap & HWCAP_CPUID) { + uint64_t tmp; + + get_cpu_feature_reg(ID_AA64ISAR0_EL1, tmp); + if (((tmp >> 44) & 0xf) == 0x1) + flags |= AV_CPU_FLAG_DOTPROD; + get_cpu_feature_reg(ID_AA64ISAR1_EL1, tmp); + if (((tmp >> 52) & 0xf) == 0x1) + flags |= AV_CPU_FLAG_I8MM; + } +#else + (void)hwcap; +#endif + + return flags; +} + +#else + +static int detect_flags(void) +{ + return 0; +} + +#endif + int ff_get_cpu_flags_aarch64(void) { int flags = AV_CPU_FLAG_ARMV8 * HAVE_ARMV8 | @@ -33,6 +83,8 @@ int ff_get_cpu_flags_aarch64(void) flags |= AV_CPU_FLAG_I8MM; #endif + flags |= detect_flags(); + return flags; } |