[patch 00/38] treewide: Cleanup LATCH, CLOCK_TICK_RATE and get_cycles() [ab]use

Thomas Gleixner
2026-04-10T12:18:40Z

First of all sorry for the insanely big Cc list, but people can't make
their mind up whether they want to be Cc'ed on everything or not. So I'm
opting for the worst case to cater to the people who want to be Cc'ed on
everything and assume that the rest of you got used to it by now. I really
wanted this to be more confined but a treewide cleanup does not give a lot
of options.

That said, let me explain what this is about.

1) LATCH

The LATCH define goes back to Linux version 0.1 and has survived until
today for the very wrong reasons.

Initially it was based on the x86 PIT frequency and also steered the
timekeeping conversions.

With the arrival of non x86 architectures it got changed to be based
on CLOCK_TICK_RATE in order not to change core code which depended on
LATCH.

That all got meaningless when timers, timekeeping and scheduling
infrastructure got rewritten more than two decades ago.

But there is still a lonely survivor in arch/x86/kernel/apm_32.c
which dates back to Linux 1.3.46 (Dec. 1995)

Which causes the next historical gem

2) CLOCK_TICK_RATE

When Linux got expanded beyond i386 LATCH was made "flexible" by
basing it on CLOCK_TICK_RATE to adjust for other frequencies than the
i386 PIT frequency.

As LATCH this got meaningless long ago and for amusement value it got
copied into new architectures arriving way after it got obsolete for
no reason but with comments to the effect that it's meaningless

And of course it had a lonely survivor in arch/x86/kernel/setup.c
despite it being only an alias for PIT_TICK_RATE for a very long time.

3) get_cycles()

That was introduced in 2.1.133pre4 (Dec. 1998) to utilize the back
then brand new TSC. The introduction broke everything except i386 SMP
with a CPU having a TSC and got then fixed up within a couple of days
with empty stubs returning 0 and #ifdeffery for CONFIG_TSC before the
2.2.0 release.

It's amusing that the naming deliberately ignored that TSC is the
acronym for Time Stamp Counter and not Cycle Counter and rather went
for the underlying coincidence that the TSC was running at the same
fixed frequency as the CPU core.

That turned out to be interesting when CPUs started to have frequency
scaling as the TSC then turned into a variable frequency random number
generator.

A decade later CPU designers came to senses and made the TSC invariant
usually running at the nominal CPU frequency, which allowed to use it
for reliable timekeeping purposes.

Non x86 architectures implemented get_cycles() based on whatever
continuously running counter they had available in their CPUs. Some of
them actual CPU cycle counters, but many of them running at a fixed
frequency which was completely unrelated to CPU cycles.

Around 2004/5 the timekeeping subsystem was completely rewritten and
made generic along with the scheduling clock and other related
infrastructure. With that rewrite get_cycles() got mostly obsolete,
but despite it being on the todo list of quite some people it never
ceased to exist and it was just a conveniance vehicle to base other
things like the recent addition of random_get_entropy() on top with a
hideous #ifdef/#define macro maze.

The other remaining use cases are mostly debugging and testing
code. Especially the usage in performance test code is hillarious at
best. While the name get_cycles() suggests that it provides access to
CPU cycles the reality is that it provides a unspecified counter for
most systems, where a lot of architectures simply return 0 because
they either do not have such a counter or did not bother to implement
it at all.

So in fact get_cycles() should have been renamed to get_bogo_cycles()
long ago matching the BogoMIPS "impress your friends" printk which
still exists for historical amusement value.

But the real solution is to remove it all together instead of
proliferating the bogosity.

This is what this series does with the following steps:

1) Cleanup some header dependency hell which got unearthed by the
restructuring and went unnoticed so far. It's amazing how the kernel
build system magically "works". This affects not only x86, but the
main fallout was observed and fixed there. ARM64 and MIPS are at
least as bad as they silently rely on the accidental asm/timex.h
include through a variety of generic headers to make their
architecture code compile. See the changelog and patches specific to
those two.

2) Removal of LATCH

3) Removal of CLOCK_TICK_RATE

4) Consolidation of cycles_t which was a typedef in asm/timex.h

5) Cleanup of read_current_timer() which is only used for delay
calibration and has nothing to do with get_cycles()

6) Cleanup of get_cycles() usage in debug and test code

7) Decoupling of random_get_entropy() from get_cycles()

8) Removal of asm/timex.h includes except for architecture internal
usage where necessary.

At the end get_cycles() survives in a couple of architectures as a purely
architecture internal implementation detail.

This survives compile testing on all architectures except hexagon and nios2
because the current cross tools based on gcc15 do not offer a compiler for
them anymore. Boot tested on x86 and some qemu instances covering only a
few architectures.

The series applies on v7.0-rc7 and with very minor conflicts on -next. It
is also available from git:

git://git.kernel.org/pub/scm/linux/kernel/git/tglx/devel.git getcycles-v1

Thanks,

tglx
---
arch/alpha/include/asm/timex.h | 33 --------
arch/arc/include/asm/timex.h | 15 ---
arch/arm/include/asm/timex.h | 16 ---
arch/arm64/include/asm/timex.h | 18 ----
arch/hexagon/include/asm/timex.h | 23 -----
arch/m68k/include/asm/timex.h | 42 ----------
arch/microblaze/include/asm/timex.h | 13 ---
arch/mips/include/asm/timex.h | 102 -------------------------
arch/sh/include/asm/timex.h | 24 -----
arch/sparc/include/asm/timex.h | 9 --
arch/sparc/include/asm/timex_32.h | 14 ---
arch/um/include/asm/timex.h | 9 --
b/Documentation/fb/udlfb.rst | 4
b/arch/Kconfig | 10 ++
b/arch/alpha/Kconfig | 1
b/arch/alpha/include/asm/random.h | 14 +++
b/arch/arm/Kconfig | 2
b/arch/arm/include/asm/delay.h | 1
b/arch/arm/include/asm/random.h | 14 +++
b/arch/arm/lib/delay.c | 14 +--
b/arch/arm/mach-omap1/Kconfig | 2
b/arch/arm64/Kconfig | 2
b/arch/arm64/include/asm/io.h | 5 -
b/arch/arm64/include/asm/ptp_vmclock.h | 12 ++
b/arch/arm64/include/asm/random.h | 11 ++
b/arch/arm64/include/asm/rqspinlock.h | 1
b/arch/arm64/kernel/time.c | 6 +
b/arch/arm64/kernel/topology.c | 1
b/arch/arm64/kernel/traps.c | 1
b/arch/arm64/kvm/emulate-nested.c | 1
b/arch/arm64/kvm/hyp/include/hyp/switch.h | 1
b/arch/arm64/lib/delay.c | 1
b/arch/hexagon/Kconfig | 1
b/arch/hexagon/kernel/time.c | 8 +
b/arch/loongarch/Kconfig | 1
b/arch/loongarch/include/asm/random.h | 15 +++
b/arch/loongarch/include/asm/timex.h | 2
b/arch/loongarch/kernel/relocate.c | 1
b/arch/loongarch/kernel/syscall.c | 1
b/arch/loongarch/lib/delay.c | 2
b/arch/m68k/Kconfig | 1
b/arch/m68k/amiga/config.c | 1
b/arch/m68k/include/asm/random.h | 14 +++
b/arch/m68k/kernel/time.c | 2
b/arch/mips/Kconfig | 1
b/arch/mips/generic/init.c | 1
b/arch/mips/include/asm/random.h | 7 +
b/arch/mips/kernel/pm-cps.c | 1
b/arch/mips/kernel/proc.c | 1
b/arch/mips/kernel/relocate.c | 2
b/arch/mips/kernel/time.c | 53 ++++++++++++
b/arch/mips/lib/dump_tlb.c | 1
b/arch/mips/mm/cache.c | 1
b/arch/nios2/Kconfig | 1
b/arch/nios2/include/asm/random.h | 14 +++
b/arch/nios2/include/asm/timex.h | 7 -
b/arch/nios2/kernel/time.c | 4
b/arch/openrisc/Kconfig | 2
b/arch/openrisc/include/asm/random.h | 12 ++
b/arch/openrisc/include/asm/timex.h | 10 --
b/arch/openrisc/lib/delay.c | 8 -
b/arch/parisc/Kconfig | 1
b/arch/parisc/include/asm/random.h | 12 ++
b/arch/parisc/include/asm/timex.h | 10 --
b/arch/parisc/kernel/processor.c | 1
b/arch/parisc/kernel/time.c | 1
b/arch/powerpc/Kconfig | 1
b/arch/powerpc/include/asm/random.h | 13 +++
b/arch/powerpc/include/asm/timex.h | 25 ------
b/arch/powerpc/platforms/cell/spufs/switch.c | 5 -
b/arch/riscv/Kconfig | 2
b/arch/riscv/include/asm/random.h | 25 ++++++
b/arch/riscv/include/asm/timex.h | 23 -----
b/arch/riscv/kernel/unaligned_access_speed.c | 1
b/arch/riscv/kvm/vcpu_timer.c | 1
b/arch/riscv/lib/delay.c | 8 +
b/arch/s390/Kconfig | 1
b/arch/s390/include/asm/random.h | 12 ++
b/arch/s390/include/asm/timex.h | 10 --
b/arch/s390/kernel/time.c | 1
b/arch/s390/kernel/vtime.c | 1
b/arch/sparc/Kconfig | 2
b/arch/sparc/include/asm/random.h | 15 +++
b/arch/sparc/include/asm/timex_64.h | 20 ----
b/arch/sparc/kernel/pcic.c | 1
b/arch/sparc/kernel/time_32.c | 1
b/arch/sparc/kernel/time_64.c | 4
b/arch/sparc/vdso/vclock_gettime.c | 1
b/arch/x86/Kconfig | 4
b/arch/x86/include/asm/iommu.h | 3
b/arch/x86/include/asm/msr.h | 5 -
b/arch/x86/include/asm/percpu.h | 5 -
b/arch/x86/include/asm/percpu_types.h | 17 ++++
b/arch/x86/include/asm/ptp_vmclock.h | 12 ++
b/arch/x86/include/asm/pvclock.h | 1
b/arch/x86/include/asm/random.h | 12 --
b/arch/x86/include/asm/smp.h | 2
b/arch/x86/include/asm/tsc.h | 11 --
b/arch/x86/include/asm/vdso/gettimeofday.h | 5 -
b/arch/x86/kernel/apm_32.c | 4
b/arch/x86/kernel/cpu/mce/core.c | 1
b/arch/x86/kernel/nmi.c | 1
b/arch/x86/kernel/setup.c | 2
b/arch/x86/kernel/smpboot.c | 1
b/arch/x86/kernel/tsc.c | 12 +-
b/arch/x86/lib/delay.c | 8 -
b/crypto/jitterentropy-kcapi.c | 1
b/crypto/tcrypt.c | 84 ++++++++++----------
b/drivers/iommu/intel/dmar.c | 4
b/drivers/iommu/intel/iommu.h | 8 +
b/drivers/irqchip/irq-apple-aic.c | 1
b/drivers/misc/sgi-gru/gruhandles.c | 20 +---
b/drivers/misc/sgi-gru/grukservices.c | 3
b/drivers/misc/sgi-gru/grutlbpurge.c | 5 -
b/drivers/net/arcnet/arc-rimi.c | 4
b/drivers/net/arcnet/arcdevice.h | 20 ----
b/drivers/net/arcnet/com20020.c | 6 -
b/drivers/net/arcnet/com90io.c | 6 -
b/drivers/net/arcnet/com90xx.c | 4
b/drivers/net/hamradio/baycom_epp.c | 51 ------------
b/drivers/net/wireless/ath/wil6210/debugfs.c | 2
b/drivers/net/wireless/ath/wil6210/txrx.c | 6 -
b/drivers/net/wireless/ath/wil6210/txrx_edma.c | 4
b/drivers/net/wireless/ath/wil6210/wil6210.h | 3
b/drivers/ptp/Kconfig | 6 -
b/drivers/ptp/ptp_vmclock.c | 6 -
b/drivers/video/fbdev/udlfb.c | 24 ++---
b/fs/ext4/mballoc.c | 4
b/include/asm-generic/Kbuild | 2
b/include/asm-generic/percpu_types.h | 20 ++++
b/include/linux/compiler_types.h | 1
b/include/linux/delay.h | 2
b/include/linux/jiffies.h | 3
b/include/linux/random.h | 18 ++++
b/include/linux/timex.h | 26 ------
b/include/linux/types.h | 6 +
b/init/calibrate.c | 19 ++--
b/kernel/kcsan/core.c | 3
b/kernel/kcsan/debugfs.c | 8 -
b/kernel/time/timer.c | 1
b/lib/interval_tree_test.c | 17 +---
b/lib/rbtree_test.c | 47 +++++------
b/lib/test_vmalloc.c | 10 +-
b/mm/kasan/sw_tags.c | 2
b/mm/slub.c | 37 +++++----
include/asm-generic/timex.h | 23 -----
146 files changed, 622 insertions(+), 796 deletions(-)