From patchwork Fri Jan 23 00:09:23 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Stultz X-Patchwork-Id: 43551 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-we0-f200.google.com (mail-we0-f200.google.com [74.125.82.200]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id B859E218DB for ; Fri, 23 Jan 2015 00:10:00 +0000 (UTC) Received: by mail-we0-f200.google.com with SMTP id m14sf2594399wev.3 for ; Thu, 22 Jan 2015 16:10:00 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=9aBZdXrAcfGKikFl0Hwc9mXcASmDatvU+Zrj9ZxQ+aY=; b=UBPUM73mJF1Bp5VQ9y6kNuL4B84kP3qu/xfF/Jia3M97hVv5Oiwgbyj4rX+pIX+PVW 9oy3FLf+Vj0aDXNdNdMKBbRcWtpjInudX9EMrW+/cf5snTfMWrl+u/0c0bZkgMHeU4Wu yT6h+rgdmJlrifDQ74cvRgXcbZHntkbd1fBT4uNCc4Y/DEvBdv9tw+lQHa6BguHHfn+E ru9MoONa3YPFl9MCeZgIqTebebJG+HY0lq1Fd52/K4jCOT+1fuLs3GDPDurGSpi0Oa0z BxqO6Uzl1FjgAr+IfHy9aWGpirqCH0XbRt9jXvetI1OEcg0ltRz5MNdIY1rPkMRF6bGs MZZg== X-Gm-Message-State: ALoCoQkYhKzTnkCwYL4ZBYGHlIPpDdfUo3dR/i3xkKzcfbZsf6KKT+g3dT8NRuM9tvtfLti0LsU/ X-Received: by 10.152.2.40 with SMTP id 8mr2746lar.7.1421971800020; Thu, 22 Jan 2015 16:10:00 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.29.133 with SMTP id k5ls187208lah.48.gmail; Thu, 22 Jan 2015 16:09:59 -0800 (PST) X-Received: by 10.112.64.35 with SMTP id l3mr4458255lbs.82.1421971799803; Thu, 22 Jan 2015 16:09:59 -0800 (PST) Received: from mail-lb0-f175.google.com (mail-lb0-f175.google.com. [209.85.217.175]) by mx.google.com with ESMTPS id qr3si22030489lbb.73.2015.01.22.16.09.59 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 22 Jan 2015 16:09:59 -0800 (PST) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.175 as permitted sender) client-ip=209.85.217.175; Received: by mail-lb0-f175.google.com with SMTP id 10so3251629lbg.6 for ; Thu, 22 Jan 2015 16:09:59 -0800 (PST) X-Received: by 10.152.197.5 with SMTP id iq5mr4567626lac.6.1421971799581; Thu, 22 Jan 2015 16:09:59 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.112.9.200 with SMTP id c8csp63959lbb; Thu, 22 Jan 2015 16:09:58 -0800 (PST) X-Received: by 10.68.222.130 with SMTP id qm2mr6749190pbc.44.1421971783651; Thu, 22 Jan 2015 16:09:43 -0800 (PST) Received: from mail-pa0-f41.google.com (mail-pa0-f41.google.com. [209.85.220.41]) by mx.google.com with ESMTPS id uq4si13904172pbc.165.2015.01.22.16.09.42 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 22 Jan 2015 16:09:43 -0800 (PST) Received-SPF: pass (google.com: domain of john.stultz@linaro.org designates 209.85.220.41 as permitted sender) client-ip=209.85.220.41; Received: by mail-pa0-f41.google.com with SMTP id kq14so2376352pab.0 for ; Thu, 22 Jan 2015 16:09:42 -0800 (PST) X-Received: by 10.70.43.236 with SMTP id z12mr6895699pdl.22.1421971782704; Thu, 22 Jan 2015 16:09:42 -0800 (PST) Received: from localhost.localdomain (c-67-170-153-23.hsd1.or.comcast.net. [67.170.153.23]) by mx.google.com with ESMTPSA id am14sm10405657pac.35.2015.01.22.16.09.41 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 22 Jan 2015 16:09:42 -0800 (PST) From: John Stultz To: Linux Kernel Mailing List Cc: John Stultz , Dave Jones , Linus Torvalds , Thomas Gleixner , Richard Cochran , Prarit Bhargava , Stephen Boyd , Ingo Molnar , Peter Zijlstra Subject: [PATCH 08/12] time: Add warnings when overflows or underflows are observed Date: Thu, 22 Jan 2015 16:09:23 -0800 Message-Id: <1421971767-17707-9-git-send-email-john.stultz@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1421971767-17707-1-git-send-email-john.stultz@linaro.org> References: <1421971767-17707-1-git-send-email-john.stultz@linaro.org> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: john.stultz@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.175 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , It was suggested that the underflow/overflow protection should probably throw some sort of warning out, rather then just silently fixing the issue. So this patch adds some warnings here. The flag variables used are not protected by locks, but since we can't print from the reading functions, just being able to say we saw an issue in the update interval is useful enough, and can be slightly racy without real consequnece. The big complication is that we're only under a read seqlock, so the data could shift under us during our calcualtion to see if there was a problem. This patch avoids this issue by nesting another seqlock which allows us to snapshot the just required values atomically. So we shouldn't see false positives. I also added some basic ratelimiting here, since on one build machine w/ skewed TSCs it was fairly noisy at bootup. Cc: Dave Jones Cc: Linus Torvalds Cc: Thomas Gleixner Cc: Richard Cochran Cc: Prarit Bhargava Cc: Stephen Boyd Cc: Ingo Molnar Cc: Peter Zijlstra Signed-off-by: John Stultz --- kernel/time/timekeeping.c | 58 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 568186c..d216b0e 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -119,11 +119,23 @@ static inline void tk_update_sleep_time(struct timekeeper *tk, ktime_t delta) } #ifdef CONFIG_DEBUG_TIMEKEEPING +#define WARNINGFREQ (HZ*300) /* 5 minute rate-limiting */ +/* + * These simple flag variables are managed + * without locks, which is racy, but ok since + * we don't really care about being super + * precise about how many events were seen, + * just that a problem was observed. + */ +static int timekeeping_underflow_seen; +static int timekeeping_overflow_seen; + static void timekeeping_check_update(struct timekeeper *tk, cycle_t offset) { cycle_t max_cycles = tk->tkr.clock->max_cycles; const char *name = tk->tkr.clock->name; + static long last_warning; /* we always hold write on timekeeper lock */ if (offset > max_cycles) printk_deferred("ERROR: cycle offset (%lld) is larger then" @@ -133,28 +145,60 @@ static void timekeeping_check_update(struct timekeeper *tk, cycle_t offset) printk_deferred("WARNING: cycle offset (%lld) is past" " the %s 50%% safety margin (%lld)\n", offset, name, max_cycles>>1); + + if (timekeeping_underflow_seen) { + if (jiffies - last_warning > WARNINGFREQ) { + printk_deferred("WARNING: Clocksource underflow observed\n"); + last_warning = jiffies; + } + timekeeping_underflow_seen = 0; + } + if (timekeeping_overflow_seen) { + if (jiffies - last_warning > WARNINGFREQ) { + printk_deferred("WARNING: Clocksource overflow observed\n"); + last_warning = jiffies; + } + timekeeping_overflow_seen = 0; + } + } static inline cycle_t timekeeping_get_delta(struct tk_read_base *tkr) { - cycle_t cycle_now, delta; + cycle_t now, last, mask, max, delta; + unsigned int seq; - /* read clocksource */ - cycle_now = tkr->read(tkr->clock); + /* + * Since we're called holding a seqlock, the data may shift + * under us while we're doign the calculation. This can cause + * false positives, since we'd note a problem but throw the + * results away. So nest another seqlock here to atomically + * grab the points we are checking with. + */ + do { + seq = read_seqcount_begin(&tk_core.seq); + now = tkr->read(tkr->clock); + last = tkr->cycle_last; + mask = tkr->mask; + max = tkr->clock->max_cycles; + } while (read_seqcount_retry(&tk_core.seq, seq)); - /* calculate the delta since the last update_wall_time */ - delta = clocksource_delta(cycle_now, tkr->cycle_last, tkr->mask); + delta = clocksource_delta(now, last, mask); /* * Try to catch underflows by checking if we are seeing small * mask-relative negative values. */ - if (unlikely((~delta & tkr->mask) < (tkr->mask >> 3))) + if (unlikely((~delta & mask) < (mask >> 3))) { + timekeeping_underflow_seen = 1; delta = 0; + } /* Cap delta value to the max_cycles values to avoid mult overflows */ - if (unlikely(delta > tkr->clock->max_cycles)) + if (unlikely(delta > max)) { + timekeeping_overflow_seen = 1; delta = tkr->clock->max_cycles; + } return delta; }