When building linux kernel Image, we set the value HZ
. linux kernel has the default HZ
value. It is a software clock frequency the kernel operates at and 1/HZ (=jiffies)
is the unit of scheduler interval. Of course this HZ
should be coming from a real hardware timer generating interrupt. So my question is : we can set HZ
when building kernel image, but what CONFIG value should I change (especially for arm64 case) to apply the real clock frequency generating this timer interrupt? I believe there should be a CONFIG value because some FPGA boards can be running at lower clock frequency and it is dependent on hardware design. If this config value is not correct, the 250MHz will not be really 250MHz. What CONFIG value should I change?
3 Answers
Things happen just the other way round : The interrupt rate is programmed by the system depending on CONFIG_HZ value.
HZ is the frequency with which the system's timer hardware is programmed to interrupt the kernel.
On arm arches, the arm global timer is used for that purpose. It will fire its interrupts following the result given by comparators. It is clocked by PERIPHCLK but, thanks to the timers framework, there is then no need (and even no added value) for it to be in sync with whatever HZ value.
You should change HZ
, but if you don’t want 100Hz, 250Hz, 300Hz or 1kHz, you’ll have to patch kernel/Kconfig.hz
to allow other values. With the current kernel configuration, HZ
is derived from HZ_100
, HZ_250
, HZ_300
, or HZ_1000
, and manually specifying any other value will result in your build asking for one of those four values to be chosen.
Yes, as others answered, the timer is programmed to generate the required interrupt (or higher resolution maybe) according to the HZ value from the kernel configuration. But my question was how to pass actual clock frequency of the counter. For example, if the clock frequency was 25MHz, and if the kernel was set with HZ_250, the clock will be programmed to fire every 100,000 clocks (because 25MHz/250Hz = 100,000). But if the clock frequency was 20Mhz, it should be programmed to fire (expire and make interrupt) every 80,000 clocks.
I looked into the kernel source and found that if the device tree provides the actual clock frequency (it's different board to board, or chip to chip) kernel uses the value given by the dtb(device tree blob) (The device node with compatibility string "arm, armv8-timer" seems to be the counter). Otherwise the kernel reads system register cntfreq_el0 register and I saw u-boot program sets with with a value given by the u-boot program designer (in config header file, because it's totally board dependent).
The time_init() function in start_kernel() seems to be doing that. Before time_init(), there comes tick_init() and init_timers() functions for registering timer softirq. (actual setting of the timer later?)
I'm not very much sure but this seems to answer my original question.