Skip to content

Commit

Permalink
clocksource/drivers/arm_arch_timer: Disable timer before programming …
Browse files Browse the repository at this point in the history
…CVAL

commit e7d65e4 upstream.

Due to the fact that the use of `writeq_relaxed()` to program CVAL is
not guaranteed to be atomic, it is necessary to disable the timer before
programming CVAL.

However, if the MMIO timer is already enabled and has not yet expired,
there is a possibility of unexpected behavior occurring: when the CPU
enters the idle state during this period, and if the CPU's local event
is earlier than the broadcast event, the following process occurs:

tick_broadcast_enter()
  tick_broadcast_oneshot_control(TICK_BROADCAST_ENTER)
    __tick_broadcast_oneshot_control()
      ___tick_broadcast_oneshot_control()
        tick_broadcast_set_event()
          clockevents_program_event()
            set_next_event_mem()

During this process, the MMIO timer remains enabled while programming
CVAL. To prevent such behavior, disable timer explicitly prior to
programming CVAL.

Fixes: 8b82c4f ("clocksource/drivers/arm_arch_timer: Move MMIO timer programming over to CVAL")
Cc: stable@vger.kernel.org
Signed-off-by: Walter Chang <walter.chang@mediatek.com>
Acked-by: Marc Zyngier <maz@kernel.org>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Link: https://lore.kernel.org/r/20230717090735.19370-1-walter.chang@mediatek.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Walter Chang authored and gregkh committed Sep 19, 2023
1 parent f295318 commit de43bc1
Showing 1 changed file with 7 additions and 0 deletions.
7 changes: 7 additions & 0 deletions drivers/clocksource/arm_arch_timer.c
Expand Up @@ -773,6 +773,13 @@ static __always_inline void set_next_event_mem(const int access, unsigned long e
u64 cnt;

ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk);

/* Timer must be disabled before programming CVAL */
if (ctrl & ARCH_TIMER_CTRL_ENABLE) {
ctrl &= ~ARCH_TIMER_CTRL_ENABLE;
arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
}

ctrl |= ARCH_TIMER_CTRL_ENABLE;
ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;

Expand Down

0 comments on commit de43bc1

Please sign in to comment.