From patchwork Fri Jan 2 23:17:41 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Stultz X-Patchwork-Id: 42709 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-la0-f70.google.com (mail-la0-f70.google.com [209.85.215.70]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 25A2D20545 for ; Fri, 2 Jan 2015 23:17:56 +0000 (UTC) Received: by mail-la0-f70.google.com with SMTP id hs14sf10819594lab.5 for ; Fri, 02 Jan 2015 15:17:54 -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:x-original-sender:x-original-authentication-results :precedence:mailing-list:list-id:list-post:list-help:list-archive :list-unsubscribe; bh=pJTLcmcJLsDUbWbs1QStvuSjsT5BXf5eCTLwDKkv7GM=; b=cfbVBW05ebaEiE7an9Ze+gUxutgU/Pxowlj/LrBN57gclVWK36fPv6kUNsqCZBMMWn mx3tva8KFaT6fZV7mlYHagcDkRmuTnwDDxz+wW4uytD7uaVrkBaQ5o9XXCf/SUTgLjMt WnW5Xk3UytVmDwJ0zZFWcW6WsGVthF1g9ucBlDqCIoFTj691weefUnSDn1oEgC6Hb7JV JqbuE0hVNTsk538SZm3jTdiQQRqkJstiDy8R/k+wEukW1dgBFJJSI1IXyfn481SCNyzJ FyyV5lQrhS1cIyyt5cctOuk3om/voHm/vQ/x69XK4FAQ9FRFMJgDTwI9gwMfy1pH/qhP ae4A== X-Gm-Message-State: ALoCoQn8E1D47vngau2c3owRgYfeXnw2ICw0NXCRD8ZMTHEJpl+prm2pVaqOjJX90Sm8U0Rl0XRZ X-Received: by 10.180.189.116 with SMTP id gh20mr107019wic.2.1420240674942; Fri, 02 Jan 2015 15:17:54 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.26.200 with SMTP id n8ls1777620lag.15.gmail; Fri, 02 Jan 2015 15:17:54 -0800 (PST) X-Received: by 10.152.18.135 with SMTP id w7mr63970674lad.47.1420240674773; Fri, 02 Jan 2015 15:17:54 -0800 (PST) Received: from mail-la0-f48.google.com (mail-la0-f48.google.com. [209.85.215.48]) by mx.google.com with ESMTPS id w8si41797236lal.81.2015.01.02.15.17.54 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 02 Jan 2015 15:17:54 -0800 (PST) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.48 as permitted sender) client-ip=209.85.215.48; Received: by mail-la0-f48.google.com with SMTP id gf13so16245549lab.35 for ; Fri, 02 Jan 2015 15:17:54 -0800 (PST) X-Received: by 10.112.235.137 with SMTP id um9mr78958192lbc.41.1420240674308; Fri, 02 Jan 2015 15:17:54 -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 c8csp309578lbb; Fri, 2 Jan 2015 15:17:53 -0800 (PST) X-Received: by 10.70.102.193 with SMTP id fq1mr127466457pdb.19.1420240672417; Fri, 02 Jan 2015 15:17:52 -0800 (PST) Received: from mail-pa0-f45.google.com (mail-pa0-f45.google.com. [209.85.220.45]) by mx.google.com with ESMTPS id ez8si60200848pdb.164.2015.01.02.15.17.51 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 02 Jan 2015 15:17:52 -0800 (PST) Received-SPF: pass (google.com: domain of john.stultz@linaro.org designates 209.85.220.45 as permitted sender) client-ip=209.85.220.45; Received: by mail-pa0-f45.google.com with SMTP id lf10so24814062pab.32 for ; Fri, 02 Jan 2015 15:17:51 -0800 (PST) X-Received: by 10.68.212.229 with SMTP id nn5mr42159201pbc.52.1420240671284; Fri, 02 Jan 2015 15:17:51 -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 nv7sm47523035pbc.29.2015.01.02.15.17.50 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 02 Jan 2015 15:17:50 -0800 (PST) From: John Stultz To: Linux Kernel Mailing List Cc: John Stultz , Dave Jones , Linus Torvalds , Thomas Gleixner , Chris Mason , Ingo Molnar , Peter Zijlstra , Sasha Levin , "Paul E. McKenney" Subject: [PATCH] time: Add debugging checks to warn if we see delays Date: Fri, 2 Jan 2015 15:17:41 -0800 Message-Id: <1420240661-8115-1-git-send-email-john.stultz@linaro.org> X-Mailer: git-send-email 1.9.1 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.215.48 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: , Recently there's been some request for better sanity checking in the time code, so that its more clear when something is going wrong since timekeeping issues could manifest in a large number of strange ways with various subsystems. Thus, this patch adds some extra infrastructure to save the maximum cycle value that can be used before we see multiplicaiton overflows, and adds a check in update_wall_time to print warnings if we see the call delayed beyond the overflow point, or beyond the clocksource max_idle_ns value which is currently 87.5% of the overflow point. Tested this a bit by halting qemu for specified lengths of time to trigger the warnings. This still needs some work, but wanted to send it out for some initial feedback and testing. Cc: Dave Jones Cc: Linus Torvalds Cc: Thomas Gleixner Cc: Chris Mason Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Sasha Levin Cc: "Paul E. McKenney" Signed-off-by: John Stultz --- include/linux/clocksource.h | 3 +++ kernel/time/clocksource.c | 27 +++++++++++++++++++++++---- kernel/time/jiffies.c | 1 + kernel/time/timekeeping.c | 18 ++++++++++++++++++ 4 files changed, 45 insertions(+), 4 deletions(-) diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index abcafaa..5c892e1 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -174,6 +174,7 @@ struct clocksource { u32 mult; u32 shift; u64 max_idle_ns; + cycle_t max_cycles; u32 maxadj; #ifdef CONFIG_ARCH_CLOCKSOURCE_DATA struct arch_clocksource_data archdata; @@ -291,6 +292,8 @@ extern struct clocksource * __init clocksource_default_clock(void); extern void clocksource_mark_unstable(struct clocksource *cs); extern u64 +clocks_calc_max_cycles(u32 mult, u32 maxadj, u64 mask); +extern u64 clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask); extern void clocks_calc_mult_shift(u32 *mult, u32 *shift, u32 from, u32 to, u32 minsec); diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index b79f39b..6384783 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -540,15 +540,14 @@ static u32 clocksource_max_adjustment(struct clocksource *cs) } /** - * clocks_calc_max_nsecs - Returns maximum nanoseconds that can be converted + * clocks_calc_max_cycles - Returns maximum cycles that can be converted to nsecs * @mult: cycle to nanosecond multiplier - * @shift: cycle to nanosecond divisor (power of two) * @maxadj: maximum adjustment value to mult (~11%) * @mask: bitmask for two's complement subtraction of non 64 bit counters */ -u64 clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask) +u64 clocks_calc_max_cycles(u32 mult, u32 maxadj, u64 mask) { - u64 max_nsecs, max_cycles; + u64 max_cycles; /* * Calculate the maximum number of cycles that we can pass to the @@ -569,6 +568,24 @@ u64 clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask) /* * The actual maximum number of cycles we can defer the clocksource is * determined by the minimum of max_cycles and mask. + */ + return min(max_cycles, mask); +} + + +/** + * clocks_calc_max_nsecs - Returns maximum nanoseconds that can be converted + * @mult: cycle to nanosecond multiplier + * @shift: cycle to nanosecond divisor (power of two) + * @maxadj: maximum adjustment value to mult (~11%) + * @mask: bitmask for two's complement subtraction of non 64 bit counters + */ +u64 clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask) +{ + u64 max_nsecs, max_cycles; + + max_cycles = clocks_calc_max_cycles(mult, maxadj, mask); + /* * Note: Here we subtract the maxadj to make sure we don't sleep for * too long if there's a large negative adjustment. */ @@ -771,6 +788,7 @@ void __clocksource_updatefreq_scale(struct clocksource *cs, u32 scale, u32 freq) cs->maxadj = clocksource_max_adjustment(cs); } + cs->max_cycles = clocks_calc_max_cycles(cs->mult, cs->maxadj, cs->mask); cs->max_idle_ns = clocksource_max_deferment(cs); } EXPORT_SYMBOL_GPL(__clocksource_updatefreq_scale); @@ -818,6 +836,7 @@ int clocksource_register(struct clocksource *cs) cs->name); /* calculate max idle time permitted for this clocksource */ + cs->max_cycles = clocks_calc_max_cycles(cs->mult, cs->maxadj, cs->mask); cs->max_idle_ns = clocksource_max_deferment(cs); mutex_lock(&clocksource_mutex); diff --git a/kernel/time/jiffies.c b/kernel/time/jiffies.c index a6a5bf5..7e41390 100644 --- a/kernel/time/jiffies.c +++ b/kernel/time/jiffies.c @@ -71,6 +71,7 @@ static struct clocksource clocksource_jiffies = { .mask = 0xffffffff, /*32bits*/ .mult = NSEC_PER_JIFFY << JIFFIES_SHIFT, /* details above */ .shift = JIFFIES_SHIFT, + .max_cycles = 10, }; __cacheline_aligned_in_smp DEFINE_SEQLOCK(jiffies_lock); diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 6a93185..c7f0dd6 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -1319,6 +1319,22 @@ static int __init timekeeping_init_ops(void) } device_initcall(timekeeping_init_ops); +static void timekeeping_check_offset(struct timekeeper *tk, cycle_t offset) +{ + + cycle_t max_cycles = tk->tkr.clock->max_cycles; + const char *name = tk->tkr.clock->name; + + if (offset > max_cycles) + printk("ERROR: cycle offset (%lld) is larger then" + " allowed %s max_cycles (%lld)\n", + offset, name, max_cycles); + else if (offset > (max_cycles - (max_cycles >> 3))) + printk("WARNING: cycle offset (%lld) is too close" + " to %s max_cycles overflow margin (%lld)\n", + offset, name, max_cycles); +} + /* * Apply a multiplier adjustment to the timekeeper */ @@ -1602,6 +1618,8 @@ void update_wall_time(void) if (offset < real_tk->cycle_interval) goto out; + timekeeping_check_offset(real_tk, offset); + /* * With NO_HZ we may have to accumulate many cycle_intervals * (think "ticks") worth of time at once. To do this efficiently,