[PATCH v3 6/8] clocksource/drivers/arm_arch_timer: Add command-line control over the counter errata management

Marc Zyngier maz at kernel.org
Sun Aug 2 09:53:25 PDT 2026


While we now have a safe way to use "fast" accessors once all CPUs
have booted, this leaves people booting with maxcpus= on non-broken
hardware stuck with the "slow" counter accessors.

Give these people a way out by adding a new command-line parameter
aptly named clocksource.arm_arch_timer.cnt_errata, which allows
the user to promise that no erratum handling is required for the
counters by setting this value to 0.

Warnings will be emitted if the user has over-promised.

Suggested-by; Will Deacon <will at kernel.org>
Signed-off-by: Marc Zyngier <maz at kernel.org>
---
 Documentation/admin-guide/kernel-parameters.txt | 13 +++++++++++++
 drivers/clocksource/arm_arch_timer.c            | 17 ++++++++++++++++-
 2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index b5493a7f8f228..f0e6534269c2b 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -830,6 +830,19 @@ Kernel parameters
 			loops can be debugged more effectively on production
 			systems.
 
+	clocksource.arm_arch_timer.cnt_errata=
+			[ARM64,EARLY]
+			Format: <bool>
+			Enable/disable the counter errata management.
+			Enabling it switches over to fast accessors once it is
+			known that no CPU requires any workaround while reading
+			the counters.
+			Disabling it will bypass workarounds when reading the
+			counters, even if not all the CPUs have been probed.
+			Warnings will be produced if the need for a workaround
+			is detected.
+			Default is enabled.
+
 	clocksource.verify_n_cpus= [KNL]
 			Limit the number of CPUs checked for clocksources
 			marked with CLOCK_SOURCE_VERIFY_PERCPU that
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 747f51d9225c2..b3b31d4f4815f 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -500,8 +500,10 @@ void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa
 			per_cpu(timer_unstable_counter_workaround, i) = wa;
 	}
 
-	if (wa->read_cntvct_el0 || wa->read_cntpct_el0)
+	if (wa->read_cntvct_el0 || wa->read_cntpct_el0) {
+		WARN_ON_ONCE(!arch_counter_broken_accessors());
 		atomic_set(&timer_unstable_counter_workaround_in_use, 1);
+	}
 
 	/*
 	 * Don't use the vdso fastpath if errata require using the
@@ -597,12 +599,22 @@ static void arch_timer_set_direct_accessors(void)
 	if (!arch_timer_counter_has_wa())
 		schedule_work(&enable_accessors_wk);
 }
+
+static bool cnt_errata_config __initdata = true;
+
+static int __init early_cnt_errata(char *buf)
+{
+	return kstrtobool(buf, &cnt_errata_config);
+}
+early_param("clocksource.arm_arch_timer.cnt_errata", early_cnt_errata);
 #else
 #define arch_timer_check_ool_workaround(t,a)		do { } while(0)
 #define arch_timer_this_cpu_has_cntvct_wa()		({false;})
 #define arch_timer_counter_has_wa()			({false;})
 static inline bool arch_counter_broken_accessors(void)	{ return false ; }
 #define arch_timer_set_direct_accessors()		do { } while(0)
+#define enable_direct_accessors(w)			do { } while(0)
+#define cnt_errata_config				false
 #endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */
 
 static __always_inline irqreturn_t timer_handler(const int access,
@@ -955,6 +967,9 @@ static void __init arch_counter_register(void)
 	u64 start_count;
 	int width;
 
+	if (!cnt_errata_config)
+		enable_direct_accessors(NULL);
+
 	switch (arch_timer_uses_ppi) {
 	case ARCH_TIMER_PHYS_SECURE_PPI:
 	case ARCH_TIMER_PHYS_NONSECURE_PPI:
-- 
2.47.3




More information about the linux-arm-kernel mailing list