From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Adrian Hunter <adrian.hunter@intel.com>,
Thomas Gleixner <tglx@linutronix.de>,
Sasha Levin <sashal@kernel.org>,
jstultz@google.com
Subject: [PATCH AUTOSEL 6.9 10/35] clocksource: Make watchdog and suspend-timing multiplication overflow safe
Date: Mon, 27 May 2024 10:11:15 -0400 [thread overview]
Message-ID: <20240527141214.3844331-10-sashal@kernel.org> (raw)
In-Reply-To: <20240527141214.3844331-1-sashal@kernel.org>
From: Adrian Hunter <adrian.hunter@intel.com>
[ Upstream commit d0304569fb019d1bcfbbbce1ce6df6b96f04079b ]
Kernel timekeeping is designed to keep the change in cycles (since the last
timer interrupt) below max_cycles, which prevents multiplication overflow
when converting cycles to nanoseconds. However, if timer interrupts stop,
the clocksource_cyc2ns() calculation will eventually overflow.
Add protection against that. Simplify by folding together
clocksource_delta() and clocksource_cyc2ns() into cycles_to_nsec_safe().
Check against max_cycles, falling back to a slower higher precision
calculation.
Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/20240325064023.2997-20-adrian.hunter@intel.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
kernel/time/clocksource.c | 42 +++++++++++++++++++--------------------
1 file changed, 20 insertions(+), 22 deletions(-)
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index e5b260aa0e02c..4d50d53ac719f 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -20,6 +20,16 @@
#include "tick-internal.h"
#include "timekeeping_internal.h"
+static noinline u64 cycles_to_nsec_safe(struct clocksource *cs, u64 start, u64 end)
+{
+ u64 delta = clocksource_delta(end, start, cs->mask);
+
+ if (likely(delta < cs->max_cycles))
+ return clocksource_cyc2ns(delta, cs->mult, cs->shift);
+
+ return mul_u64_u32_shr(delta, cs->mult, cs->shift);
+}
+
/**
* clocks_calc_mult_shift - calculate mult/shift factors for scaled math of clocks
* @mult: pointer to mult variable
@@ -222,8 +232,8 @@ enum wd_read_status {
static enum wd_read_status cs_watchdog_read(struct clocksource *cs, u64 *csnow, u64 *wdnow)
{
unsigned int nretries, max_retries;
- u64 wd_end, wd_end2, wd_delta;
int64_t wd_delay, wd_seq_delay;
+ u64 wd_end, wd_end2;
max_retries = clocksource_get_max_watchdog_retry();
for (nretries = 0; nretries <= max_retries; nretries++) {
@@ -234,9 +244,7 @@ static enum wd_read_status cs_watchdog_read(struct clocksource *cs, u64 *csnow,
wd_end2 = watchdog->read(watchdog);
local_irq_enable();
- wd_delta = clocksource_delta(wd_end, *wdnow, watchdog->mask);
- wd_delay = clocksource_cyc2ns(wd_delta, watchdog->mult,
- watchdog->shift);
+ wd_delay = cycles_to_nsec_safe(watchdog, *wdnow, wd_end);
if (wd_delay <= WATCHDOG_MAX_SKEW) {
if (nretries > 1 || nretries >= max_retries) {
pr_warn("timekeeping watchdog on CPU%d: %s retried %d times before success\n",
@@ -254,8 +262,7 @@ static enum wd_read_status cs_watchdog_read(struct clocksource *cs, u64 *csnow,
* report system busy, reinit the watchdog and skip the current
* watchdog test.
*/
- wd_delta = clocksource_delta(wd_end2, wd_end, watchdog->mask);
- wd_seq_delay = clocksource_cyc2ns(wd_delta, watchdog->mult, watchdog->shift);
+ wd_seq_delay = cycles_to_nsec_safe(watchdog, wd_end, wd_end2);
if (wd_seq_delay > WATCHDOG_MAX_SKEW/2)
goto skip_test;
}
@@ -366,8 +373,7 @@ void clocksource_verify_percpu(struct clocksource *cs)
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);
+ cs_nsec = cycles_to_nsec_safe(cs, csnow_begin, csnow_end);
if (cs_nsec > cs_nsec_max)
cs_nsec_max = cs_nsec;
if (cs_nsec < cs_nsec_min)
@@ -398,8 +404,8 @@ static inline void clocksource_reset_watchdog(void)
static void clocksource_watchdog(struct timer_list *unused)
{
- u64 csnow, wdnow, cslast, wdlast, delta;
int64_t wd_nsec, cs_nsec, interval;
+ u64 csnow, wdnow, cslast, wdlast;
int next_cpu, reset_pending;
struct clocksource *cs;
enum wd_read_status read_ret;
@@ -456,12 +462,8 @@ static void clocksource_watchdog(struct timer_list *unused)
continue;
}
- delta = clocksource_delta(wdnow, cs->wd_last, watchdog->mask);
- wd_nsec = clocksource_cyc2ns(delta, watchdog->mult,
- watchdog->shift);
-
- delta = clocksource_delta(csnow, cs->cs_last, cs->mask);
- cs_nsec = clocksource_cyc2ns(delta, cs->mult, cs->shift);
+ wd_nsec = cycles_to_nsec_safe(watchdog, cs->wd_last, wdnow);
+ cs_nsec = cycles_to_nsec_safe(cs, cs->cs_last, csnow);
wdlast = cs->wd_last; /* save these in case we print them */
cslast = cs->cs_last;
cs->cs_last = csnow;
@@ -832,7 +834,7 @@ void clocksource_start_suspend_timing(struct clocksource *cs, u64 start_cycles)
*/
u64 clocksource_stop_suspend_timing(struct clocksource *cs, u64 cycle_now)
{
- u64 now, delta, nsec = 0;
+ u64 now, nsec = 0;
if (!suspend_clocksource)
return 0;
@@ -847,12 +849,8 @@ u64 clocksource_stop_suspend_timing(struct clocksource *cs, u64 cycle_now)
else
now = suspend_clocksource->read(suspend_clocksource);
- if (now > suspend_start) {
- delta = clocksource_delta(now, suspend_start,
- suspend_clocksource->mask);
- nsec = mul_u64_u32_shr(delta, suspend_clocksource->mult,
- suspend_clocksource->shift);
- }
+ if (now > suspend_start)
+ nsec = cycles_to_nsec_safe(suspend_clocksource, suspend_start, now);
/*
* Disable the suspend timer to save power if current clocksource is
--
2.43.0
next prev parent reply other threads:[~2024-05-27 14:12 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-05-27 14:11 [PATCH AUTOSEL 6.9 01/35] ssb: Fix potential NULL pointer dereference in ssb_device_uevent() Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 02/35] selftests/bpf: Prevent client connect before server bind in test_tc_tunnel.sh Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 03/35] selftests/bpf: Fix flaky test btf_map_in_map/lookup_update Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 04/35] bpf: Avoid kfree_rcu() under lock in bpf_lpm_trie Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 05/35] devlink: use kvzalloc() to allocate devlink instance resources Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 06/35] batman-adv: bypass empty buckets in batadv_purge_orig_ref() Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 07/35] wifi: rtw89: 8852c: add quirk to set PCI BER for certain platforms Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 08/35] wifi: ath9k: work around memset overflow warning Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 09/35] af_packet: avoid a false positive warning in packet_setsockopt() Sasha Levin
2024-05-27 14:11 ` Sasha Levin [this message]
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 11/35] ACPI: x86: Add PNP_UART1_SKIP quirk for Lenovo Blade2 tablets Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 12/35] net: sfp: add quirk for another multigig RollBall transceiver Sasha Levin
2024-05-27 14:54 ` Marek Behún
2024-06-19 14:28 ` Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 13/35] drop_monitor: replace spin_lock by raw_spin_lock Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 14/35] ACPI: resource: Do IRQ override on GMxBGxx (XMG APEX 17 M23) Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 15/35] wifi: ath12k: fix kernel crash during resume Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 16/35] scsi: qedi: Fix crash while reading debugfs attribute Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 17/35] net: sfp: enhance quirk for Fibrestore 2.5G copper SFP module Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 18/35] net: sfp: add quirk for ATS SFP-GE-T 1000Base-TX module Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 19/35] net/sched: fix false lockdep warning on qdisc root lock Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 20/35] arm64/sysreg: Update PIE permission encodings Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 21/35] kselftest: arm64: Add a null pointer check Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 22/35] net: dsa: realtek: keep default LED state in rtl8366rb Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 23/35] net: dsa: realtek: do not assert reset on remove Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 24/35] ACPI: resource: Skip IRQ override on Asus Vivobook Pro N6506MV Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 25/35] netpoll: Fix race condition in netpoll_owner_active Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 26/35] wifi: ath12k: fix the problem that down grade phy mode operation Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 27/35] wifi: mt76: mt7921s: fix potential hung tasks during chip recovery Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 28/35] HID: Add quirk for Logitech Casa touchpad Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 29/35] HID: asus: fix more n-key report descriptors if n-key quirked Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 30/35] ACPI: video: Add backlight=native quirk for Lenovo Slim 7 16ARH7 Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 31/35] HID: bpf: add in-tree HID-BPF fix for the HP Elite Presenter Mouse Sasha Levin
2024-05-27 14:50 ` Benjamin Tissoires
2024-06-19 14:29 ` Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 32/35] bpf: avoid uninitialized warnings in verifier_global_subprogs.c Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 33/35] selftests: net: fix timestamp not arriving in cmsg_time.sh Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 34/35] net: ena: Add validation for completion descriptors consistency Sasha Levin
2024-05-27 14:11 ` [PATCH AUTOSEL 6.9 35/35] Bluetooth: ath3k: Fix multiple issues reported by checkpatch.pl Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240527141214.3844331-10-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=jstultz@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@vger.kernel.org \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox