From patchwork Fri Mar 9 22:04:07 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Stultz X-Patchwork-Id: 7196 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 4D52C23E01 for ; Fri, 9 Mar 2012 22:04:23 +0000 (UTC) Received: from mail-iy0-f180.google.com (mail-iy0-f180.google.com [209.85.210.180]) by fiordland.canonical.com (Postfix) with ESMTP id E75CFA18014 for ; Fri, 9 Mar 2012 22:04:22 +0000 (UTC) Received: by iage36 with SMTP id e36so3693034iag.11 for ; Fri, 09 Mar 2012 14:04:22 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf:from:to:cc :subject:date:message-id:x-mailer:x-content-scanned:x-cbid :x-gm-message-state; bh=O687dMcPh1Fbv1CxW5No+maZBVAkyDFeBcumCboqolk=; b=Tev1ctmbzMk3oR583peIF15ktruLaUMI5z2iXtQwE8cOMsabBAL7V5imvCIrcem/eE NELbovYe6ta+ukClpzMAXxOlyhHW9EOGhBBDn59BjRnLgSTQ+2Q/+AjIFgAftivN2xtw RwC1KY8+MDfCVe9iXa0eO0XD9VM8Aa/CoZ7DkRHJEf+nallPDTD/QyI+7vVYSmX2cmXx Q8YRA1Z0mucw0lkF+PfpmXkhvM36nuKmGXAbG7+6mYmaGWCNrntKn1/0jYC9Ev8tKkfs juQP8n1vrU0s9t9NE8d61Mqt8Ghu9g1X/otwpj0uVnGi1QbRHjo1D7V1kNWpCfoEqkdk YSYQ== Received: by 10.42.147.199 with SMTP id o7mr5035281icv.50.1331330662383; Fri, 09 Mar 2012 14:04:22 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.231.53.18 with SMTP id k18csp41611ibg; Fri, 9 Mar 2012 14:04:21 -0800 (PST) Received: by 10.68.226.130 with SMTP id rs2mr7052517pbc.9.1331330661344; Fri, 09 Mar 2012 14:04:21 -0800 (PST) Received: from e39.co.us.ibm.com (e39.co.us.ibm.com. [32.97.110.160]) by mx.google.com with ESMTPS id t9si8826788pbi.103.2012.03.09.14.04.20 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 09 Mar 2012 14:04:21 -0800 (PST) Received-SPF: pass (google.com: domain of jstultz@us.ibm.com designates 32.97.110.160 as permitted sender) client-ip=32.97.110.160; Authentication-Results: mx.google.com; spf=pass (google.com: domain of jstultz@us.ibm.com designates 32.97.110.160 as permitted sender) smtp.mail=jstultz@us.ibm.com Received: from /spool/local by e39.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 9 Mar 2012 15:04:19 -0700 Received: from d03dlp03.boulder.ibm.com (9.17.202.179) by e39.co.us.ibm.com (192.168.1.139) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Fri, 9 Mar 2012 15:04:13 -0700 Received: from d03relay03.boulder.ibm.com (d03relay03.boulder.ibm.com [9.17.195.228]) by d03dlp03.boulder.ibm.com (Postfix) with ESMTP id 8E36C19D8048; Fri, 9 Mar 2012 15:04:06 -0700 (MST) Received: from d03av04.boulder.ibm.com (d03av04.boulder.ibm.com [9.17.195.170]) by d03relay03.boulder.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q29M4BSX186888; Fri, 9 Mar 2012 15:04:11 -0700 Received: from d03av04.boulder.ibm.com (loopback [127.0.0.1]) by d03av04.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q29M4Apq019048; Fri, 9 Mar 2012 15:04:10 -0700 Received: from kernel.beaverton.ibm.com (kernel.beaverton.ibm.com [9.47.67.96]) by d03av04.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id q29M49dT019001; Fri, 9 Mar 2012 15:04:10 -0700 Received: by kernel.beaverton.ibm.com (Postfix, from userid 1056) id 19A1BC043A; Fri, 9 Mar 2012 14:04:09 -0800 (PST) From: John Stultz To: LKML Cc: John Stultz , Andy Lutomirski , Thomas Gleixner , John Stultz Subject: [PATCH] time: x86: Fix race switching from vsyscall to non-vsyscall clock Date: Fri, 9 Mar 2012 14:04:07 -0800 Message-Id: <1331330647-31480-1-git-send-email-john.stultz@linaro.org> X-Mailer: git-send-email 1.7.3.2.146.gca209 X-Content-Scanned: Fidelis XPS MAILER x-cbid: 12030922-4242-0000-0000-000001021A29 X-Gm-Message-State: ALoCoQkF6BecV7U7Bk2Y6O4EvIAYq8fswoY6ngOyXrWi/UoW6fQsGMWloLVgsuBEUOs1MTPucYae When switching from a vsyscall capable to a non-vsyscall capable clocksource, there was a small race, where the last vsyscall gettimeofday before the switch might return a invalid time value using the new non-vsyscall enabled clocksource values after the switch is complete. This is due to the vsyscall code checking the vclock_mode once outside of the seqcount protected section. After it reads the vclock mode, it doesn't re-check that the sampled clock data that is obtained in the seqcount critical section still matches. The fix is to sample vclock_mode inside the protected section, and as long as it isn't VCLOCK_NONE, return the calculated value. If it has changed and is now VCLOCK_NONE, fall back to the syscall gettime calculation. CC: Andy Lutomirski CC: Thomas Gleixner Signed-off-by: John Stultz --- arch/x86/vdso/vclock_gettime.c | 25 ++++++++++++++++++++----- 1 files changed, 20 insertions(+), 5 deletions(-) diff --git a/arch/x86/vdso/vclock_gettime.c b/arch/x86/vdso/vclock_gettime.c index 6bc0e72..e7cf1dd 100644 --- a/arch/x86/vdso/vclock_gettime.c +++ b/arch/x86/vdso/vclock_gettime.c @@ -85,21 +85,28 @@ notrace static inline long vgetns(void) notrace static noinline int do_realtime(struct timespec *ts) { unsigned long seq, ns; + int mode; do { seq = read_seqbegin(>od->lock); + mode = gtod->clock.vclock_mode; ts->tv_sec = gtod->wall_time_sec; ts->tv_nsec = gtod->wall_time_nsec; ns = vgetns(); } while (unlikely(read_seqretry(>od->lock, seq))); + timespec_add_ns(ts, ns); + if (mode == VCLOCK_NONE) + return -1; return 0; } notrace static noinline int do_monotonic(struct timespec *ts) { unsigned long seq, ns, secs; + int mode; do { seq = read_seqbegin(>od->lock); + mode = gtod->clock.vclock_mode; secs = gtod->wall_time_sec; ns = gtod->wall_time_nsec + vgetns(); secs += gtod->wall_to_monotonic.tv_sec; @@ -116,6 +123,8 @@ notrace static noinline int do_monotonic(struct timespec *ts) ts->tv_sec = secs; ts->tv_nsec = ns; + if (mode == VCLOCK_NONE) + return -1; return 0; } @@ -158,19 +167,25 @@ notrace int __vdso_clock_gettime(clockid_t clock, struct timespec *ts) { switch (clock) { case CLOCK_REALTIME: - if (likely(gtod->clock.vclock_mode != VCLOCK_NONE)) - return do_realtime(ts); + if (likely(gtod->clock.vclock_mode != VCLOCK_NONE)) { + if (do_realtime(ts)) + goto fallback; + return 0; + } break; case CLOCK_MONOTONIC: - if (likely(gtod->clock.vclock_mode != VCLOCK_NONE)) - return do_monotonic(ts); + if (likely(gtod->clock.vclock_mode != VCLOCK_NONE)) { + if (do_monotonic(ts)) + goto fallback; + return 0; + } break; case CLOCK_REALTIME_COARSE: return do_realtime_coarse(ts); case CLOCK_MONOTONIC_COARSE: return do_monotonic_coarse(ts); } - +fallback: return vdso_fallback_gettime(clock, ts); } int clock_gettime(clockid_t, struct timespec *)