Received: by 2002:a05:6a10:f3d0:0:0:0:0 with SMTP id a16csp2826419pxv; Mon, 12 Jul 2021 02:54:44 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxtlmEIQMk4AIolNAxHj5KFgU9TjKZtCfNtrelswR2dlycYhi/hfNtHhIEveKlWdlwCldmH X-Received: by 2002:a02:ccad:: with SMTP id t13mr1703944jap.29.1626083684657; Mon, 12 Jul 2021 02:54:44 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1626083684; cv=none; d=google.com; s=arc-20160816; b=sfrstq/5fXy+AIUtsPkKFTBWrBJSYR8TnwPUIllFbHVjY+v2QTEwE9rvoBvPQsFux8 oeMmjjl0H7qoEW2kX6P3MCWSXxNOQnkVHDBIKHFaoseJpcv9RLMq6cvdvFTuBFnKFWrA aBL+FwV+afMmD+87Nxxrr9x3X+bsqEmJYQr+Om1ik0DxMqwc6oLShu+vvMyt62CwsQkf v5IeuaUsQ2mnm25nXmMwqkN3XlrHOb/3Ev8VUWtgBRgt4LN4na3rqP6sSxLRyGq0fDHt TrlrGl3c7bh0t0MBB7DygWAlvXghXK4wrvUWnygsamzinNRIkkCyw3Qgj0IcU72XSN+x WTRQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=ZBYedA+Cv4B0SxS2BZBbVU6I+jtWJpa5jaUN71D75oY=; b=pKWT6V9ycUSXZlNz6zS9U8NNV4wJOPBlshlQfpKGcvtQcREXh7MOBtLlbh7H9Ad/kz ljoIcDhjSpR8S4As29wC2y7B724SJaUMNzSS+1e+YaTrJlLP9gqpGaCW0FbZEzSnRBeP nwK4cr3lwFwF476A02azpWYUATvB2TcPctRgou38in6xbHwJumL9v4zVz3jJ7g9tDOh3 v5Gxyy5P9I6BuXqiJvYwLtv01GasSAwwJKymzdVPk6p8QYGcQSmvk7TnqKLh8qa4ODA2 Tmfq+7WisN9tM9o3U8f/YqKPVX/XMhTa+fer47zFahKZ13uQWMVZHXC6iW1Sp4Cehmn6 r9Zw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=s6XXomAN; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id v14si17025218iom.9.2021.07.12.02.54.33; Mon, 12 Jul 2021 02:54:44 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=s6XXomAN; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239907AbhGLGzq (ORCPT + 99 others); Mon, 12 Jul 2021 02:55:46 -0400 Received: from mail.kernel.org ([198.145.29.99]:37048 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235368AbhGLGk3 (ORCPT ); Mon, 12 Jul 2021 02:40:29 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id EFC3F610D0; Mon, 12 Jul 2021 06:37:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1626071860; bh=cTjkLwMZSasIKfovcgtDzGCyZJ4G44dJFKwPH0SFYYM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=s6XXomANRvqkZ1IU333dVlXo1/MXERILyQLKxbhtbazsLaX2eDzXkLwrxXVojXHP1 zfEFUtwWiIOj3uVzFu0GKHlxdg+cHJkugmyi/gDumMJL3D1snRQvo5q+NxwrE5okaI 0AOIKUpefgxG2A6L7IVmifljE72D5k0phV4bxw30= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Chris Mason , "Paul E. McKenney" , Thomas Gleixner , Feng Tang , Sasha Levin Subject: [PATCH 5.10 199/593] clocksource: Check per-CPU clock synchronization when marked unstable Date: Mon, 12 Jul 2021 08:05:59 +0200 Message-Id: <20210712060904.913776248@linuxfoundation.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210712060843.180606720@linuxfoundation.org> References: <20210712060843.180606720@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Paul E. McKenney [ Upstream commit 7560c02bdffb7c52d1457fa551b9e745d4b9e754 ] Some sorts of per-CPU clock sources have a history of going out of synchronization with each other. However, this problem has purportedy been solved in the past ten years. Except that it is all too possible that the problem has instead simply been made less likely, which might mean that some of the occasional "Marking clocksource 'tsc' as unstable" messages might be due to desynchronization. How would anyone know? Therefore apply CPU-to-CPU synchronization checking to newly unstable clocksource that are marked with the new CLOCK_SOURCE_VERIFY_PERCPU flag. Lists of desynchronized CPUs are printed, with the caveat that if it is the reporting CPU that is itself desynchronized, it will appear that all the other clocks are wrong. Just like in real life. Reported-by: Chris Mason Signed-off-by: Paul E. McKenney Signed-off-by: Thomas Gleixner Acked-by: Feng Tang Link: https://lore.kernel.org/r/20210527190124.440372-2-paulmck@kernel.org Signed-off-by: Sasha Levin --- arch/x86/kernel/tsc.c | 3 +- include/linux/clocksource.h | 2 +- kernel/time/clocksource.c | 60 +++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index f70dffc2771f..56289170753c 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -1151,7 +1151,8 @@ static struct clocksource clocksource_tsc = { .mask = CLOCKSOURCE_MASK(64), .flags = CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_VALID_FOR_HRES | - CLOCK_SOURCE_MUST_VERIFY, + CLOCK_SOURCE_MUST_VERIFY | + CLOCK_SOURCE_VERIFY_PERCPU, .vdso_clock_mode = VDSO_CLOCKMODE_TSC, .enable = tsc_cs_enable, .resume = tsc_resume, diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index 86d143db6523..83a3ebff7456 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -131,7 +131,7 @@ struct clocksource { #define CLOCK_SOURCE_UNSTABLE 0x40 #define CLOCK_SOURCE_SUSPEND_NONSTOP 0x80 #define CLOCK_SOURCE_RESELECT 0x100 - +#define CLOCK_SOURCE_VERIFY_PERCPU 0x200 /* simplify initialization of mask field */ #define CLOCKSOURCE_MASK(bits) GENMASK_ULL((bits) - 1, 0) diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index a2059b78e34b..74492f08660c 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -224,6 +224,60 @@ static bool cs_watchdog_read(struct clocksource *cs, u64 *csnow, u64 *wdnow) return false; } +static u64 csnow_mid; +static cpumask_t cpus_ahead; +static cpumask_t cpus_behind; + +static void clocksource_verify_one_cpu(void *csin) +{ + struct clocksource *cs = (struct clocksource *)csin; + + csnow_mid = cs->read(cs); +} + +static void clocksource_verify_percpu(struct clocksource *cs) +{ + int64_t cs_nsec, cs_nsec_max = 0, cs_nsec_min = LLONG_MAX; + u64 csnow_begin, csnow_end; + int cpu, testcpu; + s64 delta; + + cpumask_clear(&cpus_ahead); + cpumask_clear(&cpus_behind); + preempt_disable(); + testcpu = smp_processor_id(); + pr_warn("Checking clocksource %s synchronization from CPU %d.\n", cs->name, testcpu); + for_each_online_cpu(cpu) { + if (cpu == testcpu) + continue; + csnow_begin = cs->read(cs); + smp_call_function_single(cpu, clocksource_verify_one_cpu, cs, 1); + csnow_end = cs->read(cs); + delta = (s64)((csnow_mid - csnow_begin) & cs->mask); + if (delta < 0) + cpumask_set_cpu(cpu, &cpus_behind); + delta = (csnow_end - csnow_mid) & cs->mask; + if (delta < 0) + cpumask_set_cpu(cpu, &cpus_ahead); + delta = clocksource_delta(csnow_end, csnow_begin, cs->mask); + cs_nsec = clocksource_cyc2ns(delta, cs->mult, cs->shift); + if (cs_nsec > cs_nsec_max) + cs_nsec_max = cs_nsec; + if (cs_nsec < cs_nsec_min) + cs_nsec_min = cs_nsec; + } + preempt_enable(); + if (!cpumask_empty(&cpus_ahead)) + pr_warn(" CPUs %*pbl ahead of CPU %d for clocksource %s.\n", + cpumask_pr_args(&cpus_ahead), testcpu, cs->name); + if (!cpumask_empty(&cpus_behind)) + pr_warn(" CPUs %*pbl behind CPU %d for clocksource %s.\n", + cpumask_pr_args(&cpus_behind), testcpu, cs->name); + if (!cpumask_empty(&cpus_ahead) || !cpumask_empty(&cpus_behind)) + pr_warn(" CPU %d check durations %lldns - %lldns for clocksource %s.\n", + testcpu, cs_nsec_min, cs_nsec_max, cs->name); +} + static void clocksource_watchdog(struct timer_list *unused) { u64 csnow, wdnow, cslast, wdlast, delta; @@ -448,6 +502,12 @@ static int __clocksource_watchdog_kthread(void) unsigned long flags; int select = 0; + /* Do any required per-CPU skew verification. */ + if (curr_clocksource && + curr_clocksource->flags & CLOCK_SOURCE_UNSTABLE && + curr_clocksource->flags & CLOCK_SOURCE_VERIFY_PERCPU) + clocksource_verify_percpu(curr_clocksource); + spin_lock_irqsave(&watchdog_lock, flags); list_for_each_entry_safe(cs, tmp, &watchdog_list, wd_list) { if (cs->flags & CLOCK_SOURCE_UNSTABLE) { -- 2.30.2