[FFmpeg-devel,PR] arm, aarch64: Don't use the ccnt / pmccntr_el0 registers for READ_TIME (PR #24805)
Commit Message
PR #24805 opened by Martin Storsjö (mstorsjo)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24805
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24805.patch
These registers aren't universally readable - on Linux, they are
inaccessible from user space by default, unless they have been
unlocked (e.g. with a custom kernel module). Attempting to read them
triggers an illegal instruction.
This doesn't make any difference for checkasm, which uses its own
definitions of timers. Checkasm dynamically tests which timers are
accessible and picks the best one that is usable.
This avoids surprises if READ_TIME is used outside of a benchmarking
context. (av_get_random_seed() has got a final fallback through
get_generic_seed(), which uses READ_TIME.)
The recently added test fate-softfloat also contains START_TIMER /
STOP_TIMER, which uses READ_TIME. This would cause the fate-softfloat
test to fail on Linux on arm or aarch64, if built with
--disable-linux-perf.
The default on Linux is to try to detect perf by default. In these
cases, the test doesn't trigger the illegal instruction, even
if the START_TIMER / STOP_TIMER benchmarking fails if perf isn't
accessible to the current user.
On Windows, these registers actually are documented to always be
readable from user space. However, if Windows binaries are run in
Wine on Linux, and the register hasn't been unlocked for user space,
then we hit the illegal instruction.
Thus: This fixes illegal instructions in the fate-softfloat test
in some build configurations, and avoids potential issues if any
other code ends up calling READ_TIME.
From 323266be2bd655177d235ab140ec84cfccb8ff5b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <martin@martin.st>
Date: Wed, 30 Sep 2026 09:46:33 +0300
Subject: [PATCH 1/2] arm, aarch64: Don't use the ccnt / pmccntr_el0 registers
for READ_TIME
These registers aren't universally readable - on Linux, they are
inaccessible from user space by default, unless they have been
unlocked (e.g. with a custom kernel module). Attempting to read them
triggers an illegal instruction.
This doesn't make any difference for checkasm, which uses its own
definitions of timers. Checkasm dynamically tests which timers are
accessible and picks the best one that is usable.
This avoids surprises if READ_TIME is used outside of a benchmarking
context. (av_get_random_seed() has got a final fallback through
get_generic_seed(), which uses READ_TIME.)
The recently added test fate-softfloat also contains START_TIMER /
STOP_TIMER, which uses READ_TIME. This would cause the fate-softfloat
test to fail on Linux on arm or aarch64, if built with
--disable-linux-perf.
The default on Linux is to try to detect perf by default. In these
cases, the test doesn't trigger the illegal instruction, even
if the START_TIMER / STOP_TIMER benchmarking fails if perf isn't
accessible to the current user.
On Windows, these registers actually are documented to always be
readable from user space. However, if Windows binaries are run in
Wine on Linux, and the register hasn't been unlocked for user space,
then we hit the illegal instruction.
Thus: This fixes illegal instructions in the fate-softfloat test
in some build configurations, and avoids potential issues if any
other code ends up calling READ_TIME.
---
libavutil/aarch64/timer.h | 7 -------
libavutil/arm/timer.h | 13 +------------
2 files changed, 1 insertion(+), 19 deletions(-)
@@ -33,16 +33,9 @@ static inline uint64_t read_time(void)
uint64_t cycle_counter;
__asm__ volatile(
"isb \t\n"
-#if defined(__ANDROID__) || defined(__APPLE__)
// cntvct_el0 has lower resolution than pmccntr_el0, but is usually
// accessible from user space by default.
"mrs %0, cntvct_el0 "
-#else
- // pmccntr_el0 has higher resolution, but is usually not accessible
- // from user space by default (but access can be enabled with a custom
- // kernel module).
- "mrs %0, pmccntr_el0 "
-#endif
: "=r"(cycle_counter) :: "memory" );
return cycle_counter;
@@ -30,17 +30,6 @@
#define AV_READ_TIME mach_absolute_time
-#elif HAVE_INLINE_ASM && defined(__ARM_ARCH_7A__) && !defined(__ANDROID__)
-
-#define AV_READ_TIME read_time
-
-static inline uint64_t read_time(void)
-{
- unsigned cc;
- __asm__ volatile ("mrc p15, 0, %0, c9, c13, 0" : "=r"(cc));
- return cc;
-}
-
-#endif /* HAVE_INLINE_ASM && __ARM_ARCH_7A__ */
+#endif /* __APPLE__ */
#endif /* AVUTIL_ARM_TIMER_H */
--
2.52.0
From 452542265bfbee4bc9030927aa8a854e7be81a84 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <martin@martin.st>
Date: Wed, 30 Sep 2026 10:00:51 +0300
Subject: [PATCH 2/2] arm: Remove the arm/timer.h header
After removing the inline assembly timer implementation, the remaining
case for Apple platforms isn't necessary here, as we have that as
a generic fallback in libavutil/timer.h.
---
libavutil/arm/timer.h | 35 -----------------------------------
libavutil/timer.h | 2 --
2 files changed, 37 deletions(-)
delete mode 100644 libavutil/arm/timer.h
deleted file mode 100644
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2009 Mans Rullgard <mans@mansr.com>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef AVUTIL_ARM_TIMER_H
-#define AVUTIL_ARM_TIMER_H
-
-#include <stdint.h>
-#include "config.h"
-
-#if defined(__APPLE__)
-
-#include <mach/mach_time.h>
-
-#define AV_READ_TIME mach_absolute_time
-
-#endif /* __APPLE__ */
-
-#endif /* AVUTIL_ARM_TIMER_H */
@@ -57,8 +57,6 @@
#if ARCH_AARCH64
# include "aarch64/timer.h"
-#elif ARCH_ARM
-# include "arm/timer.h"
#elif ARCH_PPC
# include "ppc/timer.h"
#elif ARCH_X86