From 191ce9d1fde84190f18cd3faf0ef8594f442b313 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Wed, 16 Nov 2016 16:36:26 +0100 Subject: [PATCH] s390/time: fix clocksource steering for negative clock offsets The TOD clock offset injected by an STP sync check can be negative. If the resulting total tod_steering_delta gets negative the kernel will panic. Change the type of tod_steering_delta to a signed type. Reported-by: Dan Carpenter Fixes: 75c7b6f3f6ba ("s390/time: steer clocksource on STP sync events") Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/time.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 33082f6cbb5d..867d0a057046 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -63,7 +63,7 @@ unsigned char ptff_function_mask[16]; static unsigned long long lpar_offset; static unsigned long long initial_leap_seconds; static unsigned long long tod_steering_end; -static unsigned long long tod_steering_delta; +static long long tod_steering_delta; /* * Get time offsets with PTFF @@ -223,8 +223,7 @@ static cycle_t read_tod_clock(struct clocksource *cs) * therefore steered in ~9h. The adjust will decrease * over time, until it finally reaches 0. */ - now += ((s64) tod_steering_delta < 0) ? - (adj >> 15) : -(adj >> 15); + now += (tod_steering_delta < 0) ? (adj >> 15) : -(adj >> 15); preempt_enable(); return now; } @@ -412,7 +411,7 @@ static void clock_sync_global(unsigned long long delta) adj = tod_steering_end - now; if (unlikely((s64) adj >= 0)) /* Calculate how much of the old adjustment is left. */ - tod_steering_delta = ((s64) tod_steering_delta < 0) ? + tod_steering_delta = (tod_steering_delta < 0) ? -(adj >> 15) : (adj >> 15); tod_steering_delta += delta; if ((abs(tod_steering_delta) >> 48) != 0)