Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clocksource/drivers/arm_arch_timer: Correct fault programming of CNTKCTL_EL1.EVNTI

ARM virtual counter supports event stream, it can only trigger an event
when the trigger bit (the value of CNTKCTL_EL1.EVNTI) of CNTVCT_EL0 changes,
so the actual period of event stream is 2^(cntkctl_evnti + 1). For example,
when the trigger bit is 0, then virtual counter trigger an event for every
two cycles.

While we're at it, rework the way we compute the trigger bit position
by making it more obvious that when bits [n:n-1] are both set (with n
being the most significant bit), we pick bit (n + 1).

Fixes: 037f637767a8 ("drivers: clocksource: add support for ARM architected timer event stream")
Suggested-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
Acked-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Link: https://lore.kernel.org/r/20201204073126.6920-3-zhukeqian1@huawei.com

authored by

Keqian Zhu and committed by
Daniel Lezcano
8b7770b8 d8cc3905

+16 -7
+16 -7
drivers/clocksource/arm_arch_timer.c
··· 822 822 823 823 static void arch_timer_configure_evtstream(void) 824 824 { 825 - int evt_stream_div, pos; 825 + int evt_stream_div, lsb; 826 826 827 - /* Find the closest power of two to the divisor */ 828 - evt_stream_div = arch_timer_rate / ARCH_TIMER_EVT_STREAM_FREQ; 829 - pos = fls(evt_stream_div); 830 - if (pos > 1 && !(evt_stream_div & (1 << (pos - 2)))) 831 - pos--; 827 + /* 828 + * As the event stream can at most be generated at half the frequency 829 + * of the counter, use half the frequency when computing the divider. 830 + */ 831 + evt_stream_div = arch_timer_rate / ARCH_TIMER_EVT_STREAM_FREQ / 2; 832 + 833 + /* 834 + * Find the closest power of two to the divisor. If the adjacent bit 835 + * of lsb (last set bit, starts from 0) is set, then we use (lsb + 1). 836 + */ 837 + lsb = fls(evt_stream_div) - 1; 838 + if (lsb > 0 && (evt_stream_div & BIT(lsb - 1))) 839 + lsb++; 840 + 832 841 /* enable event stream */ 833 - arch_timer_evtstrm_enable(min(pos, 15)); 842 + arch_timer_evtstrm_enable(max(0, min(lsb, 15))); 834 843 } 835 844 836 845 static void arch_counter_set_user_access(void)