{"id":2235045,"url":"http://patchwork.ozlabs.org/api/1.2/patches/2235045/?format=json","web_url":"http://patchwork.ozlabs.org/project/linuxppc-dev/patch/20260508131647.43868-10-frederic@kernel.org/","project":{"id":2,"url":"http://patchwork.ozlabs.org/api/1.2/projects/2/?format=json","name":"Linux PPC development","link_name":"linuxppc-dev","list_id":"linuxppc-dev.lists.ozlabs.org","list_email":"linuxppc-dev@lists.ozlabs.org","web_url":"https://github.com/linuxppc/wiki/wiki","scm_url":"https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git","webscm_url":"https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git/","list_archive_url":"https://lore.kernel.org/linuxppc-dev/","list_archive_url_format":"https://lore.kernel.org/linuxppc-dev/{}/","commit_url_format":"https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git/commit/?id={}"},"msgid":"<20260508131647.43868-10-frederic@kernel.org>","list_archive_url":"https://lore.kernel.org/linuxppc-dev/20260508131647.43868-10-frederic@kernel.org/","date":"2026-05-08T13:16:41","name":"[09/15] tick/sched: Move dyntick-idle cputime accounting to cputime code","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"c12043428fbde6343c65dadcbfe4e2120c89e5c6","submitter":{"id":79411,"url":"http://patchwork.ozlabs.org/api/1.2/people/79411/?format=json","name":"Frederic Weisbecker","email":"frederic@kernel.org"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/linuxppc-dev/patch/20260508131647.43868-10-frederic@kernel.org/mbox/","series":[{"id":503389,"url":"http://patchwork.ozlabs.org/api/1.2/series/503389/?format=json","web_url":"http://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=503389","date":"2026-05-08T13:16:32","name":"tick/sched: Refactor idle cputime accounting","version":4,"mbox":"http://patchwork.ozlabs.org/series/503389/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2235045/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2235045/checks/","tags":{},"related":[],"headers":{"Return-Path":"\n <linuxppc-dev+bounces-20619-incoming=patchwork.ozlabs.org@lists.ozlabs.org>","X-Original-To":["incoming@patchwork.ozlabs.org","linuxppc-dev@lists.ozlabs.org"],"Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256\n header.s=k20201202 header.b=b03JG/0C;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org\n (client-ip=112.213.38.117; helo=lists.ozlabs.org;\n envelope-from=linuxppc-dev+bounces-20619-incoming=patchwork.ozlabs.org@lists.ozlabs.org;\n receiver=patchwork.ozlabs.org)","lists.ozlabs.org;\n arc=none smtp.remote-ip=172.105.4.254","lists.ozlabs.org;\n dmarc=pass (p=quarantine dis=none) header.from=kernel.org","lists.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256\n header.s=k20201202 header.b=b03JG/0C;\n\tdkim-atps=neutral","lists.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=kernel.org\n (client-ip=172.105.4.254; helo=tor.source.kernel.org;\n envelope-from=frederic@kernel.org; receiver=lists.ozlabs.org)"],"Received":["from lists.ozlabs.org (lists.ozlabs.org [112.213.38.117])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4gBqSK488pz1yKm\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 08 May 2026 23:18:25 +1000 (AEST)","from boromir.ozlabs.org (localhost [127.0.0.1])\n\tby lists.ozlabs.org (Postfix) with ESMTP id 4gBqSK3Dkdz3bl7;\n\tFri, 08 May 2026 23:18:25 +1000 (AEST)","from tor.source.kernel.org (tor.source.kernel.org [172.105.4.254])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby lists.ozlabs.org (Postfix) with ESMTPS id 4gBqSJ39JMz30VL\n\tfor <linuxppc-dev@lists.ozlabs.org>; Fri, 08 May 2026 23:18:24 +1000 (AEST)","from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58])\n\tby tor.source.kernel.org (Postfix) with ESMTP id 84A20600AE;\n\tFri,  8 May 2026 13:18:22 +0000 (UTC)","by smtp.kernel.org (Postfix) with ESMTPSA id 2984EC2BCB0;\n\tFri,  8 May 2026 13:18:14 +0000 (UTC)"],"ARC-Seal":"i=1; a=rsa-sha256; d=lists.ozlabs.org; s=201707; t=1778246305;\n\tcv=none;\n b=Qo9v52x0FEgAcs1Hj6VRGBuQ4PFpXFrpf27VNSd/tTC27NzEIjr/O+OQ5B2rP0EeFGyf3eYYchBaVZ7R5EmFsjDQKO7LLrDkpxNf5IuQzRhdLFJyaxzkNLSXTCsCIKOznp8FSykjJKwGKBe1zMrGpueVyJKGh+kfmm7WvqdZuS2HHegSCNb1I08LVaNruhgelXr5ulsHRJ9ApeTTg+aY8oM+B6X3vFKl5CW4kd59iZ3n38VZTp6otIDa0npdef3GKeQfd3T4hiR6rZYf9OlT3ZCcM+uv7V4TFSXmjcUOLiBDFH3gWe7381CspIXWBn64gmP9ToAoxKDm2aR87DN+ug==","ARC-Message-Signature":"i=1; a=rsa-sha256; d=lists.ozlabs.org; s=201707;\n\tt=1778246305; c=relaxed/relaxed;\n\tbh=XR9D7hgopKAiZWRxp1KdNiAZN0za/E0fSMPJGx1wvM4=;\n\th=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version;\n b=a8hiOcAGt71uZaa0ZGJs/HCyF4l976wcvLKvRhnbsy8rMBHuQCjeKApBaPmkOu77/wkG5dG4Pt5VhcRjC3KFopUyN7UJZd3XkPrJ2oBc05EfWPre4TQf42C4AVEPWZ61ENaJiu8I58pgnKdnl3WkYYe4s/P31NK8TPGXmxqQ/5ipN4hKz8mM2DLQUrvKs3m7C0sCJ64DTcAp8f+veG6mh9ln9W2X+3WS6CtBYxHD5FcpMXbu8QHS0Oy9unhOKbA/YXwWh5sD/ALVgjLbPINn8oSYr1gE/rypVQFbJZ0ih2IKeLLX7SIrE8aZea/lg6O853ZKPbJ6UIA6ADX0DWipcw==","ARC-Authentication-Results":"i=1; lists.ozlabs.org;\n dmarc=pass (p=quarantine dis=none) header.from=kernel.org;\n dkim=pass (2048-bit key;\n unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256\n header.s=k20201202 header.b=b03JG/0C; dkim-atps=neutral;\n spf=pass (client-ip=172.105.4.254; helo=tor.source.kernel.org;\n envelope-from=frederic@kernel.org;\n receiver=lists.ozlabs.org) smtp.mailfrom=kernel.org","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org;\n\ts=k20201202; t=1778246302;\n\tbh=u0vNvN9NtF+AsX8/Y+QNB08Illj907nXS1MtqiyyDWI=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=b03JG/0Cc9XSCeKKg8g3/tA2h1fJv9Ek3cPqLiDrg84ZStWD53YYSIONP4WAuh4/u\n\t bEk0gSg8yi3OBVOWzfvklBu9UpcBDKqSbqXCqts34xdSwrRGa9jF+O6LAvsd20z/yY\n\t rxYBif/Lr3jIguxvb7EVOeQz+eIDp/N8l95vRURu2ql3kJNPMN8yiFlb0kvo/wKTVM\n\t emHntXqYwlcU9g1/enzjSxEPFRE5sFk4Vb3f5ZWAaRbu4dKnOqhvfbRn96/4circ0q\n\t 8XlQcefuVU2/TCQjJXK9OlqPrvh/m3dH3KUJsfSHCy4Rsi1eSlMzO3q4CNnkkcpo5m\n\t usDk3aIQHSXgg==","From":"Frederic Weisbecker <frederic@kernel.org>","To":"LKML <linux-kernel@vger.kernel.org>","Cc":"Frederic Weisbecker <frederic@kernel.org>,\n\t\"Christophe Leroy (CS GROUP)\" <chleroy@kernel.org>,\n\t\"Rafael J. Wysocki\" <rafael@kernel.org>,\n\tAlexander Gordeev <agordeev@linux.ibm.com>,\n\tAnna-Maria Behnsen <anna-maria@linutronix.de>,\n\tBen Segall <bsegall@google.com>, Boqun Feng <boqun.feng@gmail.com>,\n\tChristian Borntraeger <borntraeger@linux.ibm.com>,\n\tDietmar Eggemann <dietmar.eggemann@arm.com>,\n\tHeiko Carstens <hca@linux.ibm.com>, Ingo Molnar <mingo@kernel.org>,\n\tIngo Molnar <mingo@redhat.com>, Jan Kiszka <jan.kiszka@siemens.com>,\n\tJoel Fernandes <joelagnelf@nvidia.com>,\n\tJuri Lelli <juri.lelli@redhat.com>,\n\tKieran Bingham <kbingham@kernel.org>,\n\tMadhavan Srinivasan <maddy@linux.ibm.com>,\n\tMel Gorman <mgorman@suse.de>, Michael Ellerman <mpe@ellerman.id.au>,\n\tNeeraj Upadhyay <neeraj.upadhyay@kernel.org>,\n\tNicholas Piggin <npiggin@gmail.com>,\n\t\"Paul E . McKenney\" <paulmck@kernel.org>,\n\tPeter Zijlstra <peterz@infradead.org>, Sashiko@lists.ozlabs.org,\n\tShrikanth Hegde <sshegde@linux.ibm.com>,\n\tSteven Rostedt <rostedt@goodmis.org>,\n\tSven Schnelle <svens@linux.ibm.com>,\n\tThomas Gleixner <tglx@linutronix.de>,\n\tUladzislau Rezki <urezki@gmail.com>,\n\tValentin Schneider <vschneid@redhat.com>,\n\tVasily Gorbik <gor@linux.ibm.com>,\n\tVincent Guittot <vincent.guittot@linaro.org>,\n\tViresh Kumar <viresh.kumar@linaro.org>,\n\tXin Zhao <jackzxcui1989@163.com>, linux-pm@vger.kernel.org,\n\tlinux-s390@vger.kernel.org, linuxppc-dev@lists.ozlabs.org","Subject":"[PATCH 09/15] tick/sched: Move dyntick-idle cputime accounting to\n cputime code","Date":"Fri,  8 May 2026 15:16:41 +0200","Message-ID":"<20260508131647.43868-10-frederic@kernel.org>","X-Mailer":"git-send-email 2.53.0","In-Reply-To":"<20260508131647.43868-1-frederic@kernel.org>","References":"<20260508131647.43868-1-frederic@kernel.org>","X-Mailing-List":"linuxppc-dev@lists.ozlabs.org","List-Id":"<linuxppc-dev.lists.ozlabs.org>","List-Help":"<mailto:linuxppc-dev+help@lists.ozlabs.org>","List-Owner":"<mailto:linuxppc-dev+owner@lists.ozlabs.org>","List-Post":"<mailto:linuxppc-dev@lists.ozlabs.org>","List-Archive":"<https://lore.kernel.org/linuxppc-dev/>,\n  <https://lists.ozlabs.org/pipermail/linuxppc-dev/>","List-Subscribe":"<mailto:linuxppc-dev+subscribe@lists.ozlabs.org>,\n  <mailto:linuxppc-dev+subscribe-digest@lists.ozlabs.org>,\n  <mailto:linuxppc-dev+subscribe-nomail@lists.ozlabs.org>","List-Unsubscribe":"<mailto:linuxppc-dev+unsubscribe@lists.ozlabs.org>","Precedence":"list","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","X-Spam-Status":"No, score=-0.6 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED,\n\tDKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS\n\tautolearn=disabled version=4.0.1 OzLabs 8","X-Spam-Checker-Version":"SpamAssassin 4.0.1 (2024-03-25) on lists.ozlabs.org"},"content":"Although the dynticks-idle cputime accounting is necessarily tied to\nthe tick subsystem, the actual related accounting code has no business\nresiding there and should be part of the scheduler cputime code.\n\nMove away the relevant pieces and state machine to where they belong.\n\nSigned-off-by: Frederic Weisbecker <frederic@kernel.org>\nTested-by: Shrikanth Hegde <sshegde@linux.ibm.com>\n---\n include/linux/kernel_stat.h |  14 +++-\n kernel/sched/core.c         |   6 +-\n kernel/sched/cputime.c      | 148 ++++++++++++++++++++++++++++++--\n kernel/time/tick-sched.c    | 163 +++++++-----------------------------\n 4 files changed, 188 insertions(+), 143 deletions(-)","diff":"diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h\nindex ba65aad308a1..9343353ac7a3 100644\n--- a/include/linux/kernel_stat.h\n+++ b/include/linux/kernel_stat.h\n@@ -35,9 +35,12 @@ enum cpu_usage_stat {\n \n struct kernel_cpustat {\n #ifdef CONFIG_NO_HZ_COMMON\n-\tint idle_dyntick;\n+\tbool\t\tidle_dyntick;\n+\tbool\t\tidle_elapse;\n+\tseqcount_t\tidle_sleeptime_seq;\n+\tu64\t\tidle_entrytime;\n #endif\n-\tu64 cpustat[NR_STATS];\n+\tu64\t\tcpustat[NR_STATS];\n };\n \n struct kernel_stat {\n@@ -103,8 +106,11 @@ static inline unsigned long kstat_cpu_irqs_sum(unsigned int cpu)\n }\n \n #ifdef CONFIG_NO_HZ_COMMON\n-extern void kcpustat_dyntick_start(void);\n-extern void kcpustat_dyntick_stop(void);\n+extern void kcpustat_dyntick_start(u64 now);\n+extern void kcpustat_dyntick_stop(u64 now);\n+extern void kcpustat_irq_enter(u64 now);\n+extern void kcpustat_irq_exit(u64 now);\n+\n static inline bool kcpustat_idle_dyntick(void)\n {\n \treturn __this_cpu_read(kernel_cpustat.idle_dyntick);\ndiff --git a/kernel/sched/core.c b/kernel/sched/core.c\nindex da20fb6ea25a..0cfc027a955d 100644\n--- a/kernel/sched/core.c\n+++ b/kernel/sched/core.c\n@@ -5517,7 +5517,11 @@ void sched_exec(void)\n }\n \n DEFINE_PER_CPU(struct kernel_stat, kstat);\n-DEFINE_PER_CPU(struct kernel_cpustat, kernel_cpustat);\n+DEFINE_PER_CPU(struct kernel_cpustat, kernel_cpustat) = {\n+#ifdef CONFIG_NO_HZ_COMMON\n+\t.idle_sleeptime_seq = SEQCNT_ZERO(kernel_cpustat.idle_sleeptime_seq)\n+#endif\n+};\n \n EXPORT_PER_CPU_SYMBOL(kstat);\n EXPORT_PER_CPU_SYMBOL(kernel_cpustat);\ndiff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c\nindex a5733789e0bd..4c00163b74b9 100644\n--- a/kernel/sched/cputime.c\n+++ b/kernel/sched/cputime.c\n@@ -2,6 +2,7 @@\n /*\n  * Simple CPU accounting cgroup controller\n  */\n+#include <linux/sched/clock.h>\n #include <linux/sched/cputime.h>\n #include <linux/tsacct_kern.h>\n #include \"sched.h\"\n@@ -420,22 +421,155 @@ static inline void irqtime_account_process_tick(struct task_struct *p, int user_\n #endif /* !CONFIG_IRQ_TIME_ACCOUNTING */\n \n #ifdef CONFIG_NO_HZ_COMMON\n-void kcpustat_dyntick_start(void)\n+static void kcpustat_idle_stop(struct kernel_cpustat *kc, u64 now)\n {\n-\tif (!vtime_generic_enabled_this_cpu()) {\n-\t\tvtime_dyntick_start();\n-\t\t__this_cpu_write(kernel_cpustat.idle_dyntick, 1);\n-\t}\n+\tu64 *cpustat = kc->cpustat;\n+\tu64 delta;\n+\n+\tif (!kc->idle_elapse)\n+\t\treturn;\n+\n+\tdelta = now - kc->idle_entrytime;\n+\n+\twrite_seqcount_begin(&kc->idle_sleeptime_seq);\n+\tif (nr_iowait_cpu(smp_processor_id()) > 0)\n+\t\tcpustat[CPUTIME_IOWAIT] += delta;\n+\telse\n+\t\tcpustat[CPUTIME_IDLE] += delta;\n+\n+\tkc->idle_entrytime = now;\n+\tkc->idle_elapse = false;\n+\twrite_seqcount_end(&kc->idle_sleeptime_seq);\n }\n \n-void kcpustat_dyntick_stop(void)\n+static void kcpustat_idle_start(struct kernel_cpustat *kc, u64 now)\n {\n+\twrite_seqcount_begin(&kc->idle_sleeptime_seq);\n+\tkc->idle_entrytime = now;\n+\tkc->idle_elapse = true;\n+\twrite_seqcount_end(&kc->idle_sleeptime_seq);\n+}\n+\n+void kcpustat_dyntick_stop(u64 now)\n+{\n+\tstruct kernel_cpustat *kc = kcpustat_this_cpu;\n+\n \tif (!vtime_generic_enabled_this_cpu()) {\n-\t\t__this_cpu_write(kernel_cpustat.idle_dyntick, 0);\n+\t\tWARN_ON_ONCE(!kc->idle_dyntick);\n+\t\tkcpustat_idle_stop(kc, now);\n+\t\tkc->idle_dyntick = false;\n \t\tvtime_dyntick_stop();\n \t\tsteal_account_process_time(ULONG_MAX);\n \t}\n }\n+\n+void kcpustat_dyntick_start(u64 now)\n+{\n+\tstruct kernel_cpustat *kc = kcpustat_this_cpu;\n+\n+\tif (!vtime_generic_enabled_this_cpu()) {\n+\t\tvtime_dyntick_start();\n+\t\tkc->idle_dyntick = true;\n+\t\tkcpustat_idle_start(kc, now);\n+\t}\n+}\n+\n+void kcpustat_irq_enter(u64 now)\n+{\n+\tstruct kernel_cpustat *kc = kcpustat_this_cpu;\n+\n+\tif (!vtime_generic_enabled_this_cpu())\n+\t\tkcpustat_idle_stop(kc, now);\n+}\n+\n+void kcpustat_irq_exit(u64 now)\n+{\n+\tstruct kernel_cpustat *kc = kcpustat_this_cpu;\n+\n+\tif (!vtime_generic_enabled_this_cpu())\n+\t\tkcpustat_idle_start(kc, now);\n+}\n+\n+static u64 get_cpu_sleep_time_us(int cpu, enum cpu_usage_stat idx,\n+\t\t\t\t bool compute_delta, u64 *last_update_time)\n+{\n+\tstruct kernel_cpustat *kc = &kcpustat_cpu(cpu);\n+\tu64 *cpustat = kc->cpustat;\n+\tunsigned int seq;\n+\tktime_t now;\n+\tu64 idle;\n+\n+\tnow = ktime_get();\n+\tif (last_update_time)\n+\t\t*last_update_time = ktime_to_us(now);\n+\n+\tif (vtime_generic_enabled_cpu(cpu)) {\n+\t\tidle = kcpustat_field(idx, cpu);\n+\t\tgoto to_us;\n+\t}\n+\n+\tdo {\n+\t\tseq = read_seqcount_begin(&kc->idle_sleeptime_seq);\n+\n+\t\tidle = cpustat[idx];\n+\t\tif (kc->idle_elapse && compute_delta && now > kc->idle_entrytime)\n+\t\t\tidle += (now - kc->idle_entrytime);\n+\t} while (read_seqcount_retry(&kc->idle_sleeptime_seq, seq));\n+\n+to_us:\n+\tdo_div(idle, NSEC_PER_USEC);\n+\n+\treturn idle;\n+}\n+\n+/**\n+ * get_cpu_idle_time_us - get the total idle time of a CPU\n+ * @cpu: CPU number to query\n+ * @last_update_time: variable to store update time in. Do not update\n+ * counters if NULL.\n+ *\n+ * Return the cumulative idle time (since boot) for a given\n+ * CPU, in microseconds. Note that this is partially broken due to\n+ * the counter of iowait tasks that can be remotely updated without\n+ * any synchronization. Therefore it is possible to observe backward\n+ * values within two consecutive reads.\n+ *\n+ * This time is measured via accounting rather than sampling,\n+ * and is as accurate as ktime_get() is.\n+ *\n+ * Return: -1 if generic vtime is enabled, else total idle time of the @cpu\n+ */\n+u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time)\n+{\n+\treturn get_cpu_sleep_time_us(cpu, CPUTIME_IDLE,\n+\t\t\t\t     !nr_iowait_cpu(cpu), last_update_time);\n+}\n+EXPORT_SYMBOL_GPL(get_cpu_idle_time_us);\n+\n+/**\n+ * get_cpu_iowait_time_us - get the total iowait time of a CPU\n+ * @cpu: CPU number to query\n+ * @last_update_time: variable to store update time in. Do not update\n+ * counters if NULL.\n+ *\n+ * Return the cumulative iowait time (since boot) for a given\n+ * CPU, in microseconds. Note this is partially broken due to\n+ * the counter of iowait tasks that can be remotely updated without\n+ * any synchronization. Therefore it is possible to observe backward\n+ * values within two consecutive reads.\n+ *\n+ * This time is measured via accounting rather than sampling,\n+ * and is as accurate as ktime_get() is.\n+ *\n+ * Return: -1 if generic vtime is enabled, else total iowait time of @cpu\n+ */\n+u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time)\n+{\n+\treturn get_cpu_sleep_time_us(cpu, CPUTIME_IOWAIT,\n+\t\t\t\t     nr_iowait_cpu(cpu), last_update_time);\n+}\n+EXPORT_SYMBOL_GPL(get_cpu_iowait_time_us);\n+\n #endif /* CONFIG_NO_HZ_COMMON */\n \n /*\ndiff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c\nindex cb235ec7d2d6..fa03cf7b3cec 100644\n--- a/kernel/time/tick-sched.c\n+++ b/kernel/time/tick-sched.c\n@@ -749,126 +749,6 @@ static void tick_nohz_update_jiffies(ktime_t now)\n \ttouch_softlockup_watchdog_sched();\n }\n \n-static void tick_nohz_stop_idle(struct tick_sched *ts, ktime_t now)\n-{\n-\tu64 *cpustat = kcpustat_this_cpu->cpustat;\n-\tktime_t delta;\n-\n-\tif (vtime_generic_enabled_this_cpu())\n-\t\treturn;\n-\n-\tif (WARN_ON_ONCE(!tick_sched_flag_test(ts, TS_FLAG_IDLE_ACTIVE)))\n-\t\treturn;\n-\n-\tdelta = ktime_sub(now, ts->idle_entrytime);\n-\n-\twrite_seqcount_begin(&ts->idle_sleeptime_seq);\n-\tif (nr_iowait_cpu(smp_processor_id()) > 0)\n-\t\tcpustat[CPUTIME_IOWAIT] = ktime_add(cpustat[CPUTIME_IOWAIT], delta);\n-\telse\n-\t\tcpustat[CPUTIME_IDLE] = ktime_add(cpustat[CPUTIME_IDLE], delta);\n-\n-\tts->idle_entrytime = now;\n-\ttick_sched_flag_clear(ts, TS_FLAG_IDLE_ACTIVE);\n-\twrite_seqcount_end(&ts->idle_sleeptime_seq);\n-\n-\tsched_clock_idle_wakeup_event();\n-}\n-\n-static void tick_nohz_start_idle(struct tick_sched *ts)\n-{\n-\tif (vtime_generic_enabled_this_cpu())\n-\t\treturn;\n-\n-\twrite_seqcount_begin(&ts->idle_sleeptime_seq);\n-\tts->idle_entrytime = ktime_get();\n-\ttick_sched_flag_set(ts, TS_FLAG_IDLE_ACTIVE);\n-\twrite_seqcount_end(&ts->idle_sleeptime_seq);\n-\tsched_clock_idle_sleep_event();\n-}\n-\n-static u64 get_cpu_sleep_time_us(int cpu, enum cpu_usage_stat idx,\n-\t\t\t\t bool compute_delta, u64 *last_update_time)\n-{\n-\tstruct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);\n-\tu64 *cpustat = kcpustat_cpu(cpu).cpustat;\n-\tktime_t now, idle;\n-\tunsigned int seq;\n-\n-\tnow = ktime_get();\n-\tif (last_update_time)\n-\t\t*last_update_time = ktime_to_us(now);\n-\n-\tif (vtime_generic_enabled_cpu(cpu)) {\n-\t\tidle = kcpustat_field(idx, cpu);\n-\t\treturn ktime_to_us(idle);\n-\t}\n-\n-\tdo {\n-\t\tktime_t delta = 0;\n-\n-\t\tseq = read_seqcount_begin(&ts->idle_sleeptime_seq);\n-\n-\t\tif (tick_sched_flag_test(ts, TS_FLAG_IDLE_ACTIVE) && compute_delta) {\n-\t\t\tif (now > ts->idle_entrytime)\n-\t\t\t\tdelta = ktime_sub(now, ts->idle_entrytime);\n-\t\t}\n-\n-\t\tidle = ktime_add(cpustat[idx], delta);\n-\t} while (read_seqcount_retry(&ts->idle_sleeptime_seq, seq));\n-\n-\treturn ktime_to_us(idle);\n-\n-}\n-\n-/**\n- * get_cpu_idle_time_us - get the total idle time of a CPU\n- * @cpu: CPU number to query\n- * @last_update_time: variable to store update time in. Do not update\n- * counters if NULL.\n- *\n- * Return the cumulative idle time (since boot) for a given\n- * CPU, in microseconds. Note that this is partially broken due to\n- * the counter of iowait tasks that can be remotely updated without\n- * any synchronization. Therefore it is possible to observe backward\n- * values within two consecutive reads.\n- *\n- * This time is measured via accounting rather than sampling,\n- * and is as accurate as ktime_get() is.\n- *\n- * Return: -1 if generic vtime is enabled, else total idle time of the @cpu\n- */\n-u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time)\n-{\n-\treturn get_cpu_sleep_time_us(cpu, CPUTIME_IDLE,\n-\t\t\t\t     !nr_iowait_cpu(cpu), last_update_time);\n-}\n-EXPORT_SYMBOL_GPL(get_cpu_idle_time_us);\n-\n-/**\n- * get_cpu_iowait_time_us - get the total iowait time of a CPU\n- * @cpu: CPU number to query\n- * @last_update_time: variable to store update time in. Do not update\n- * counters if NULL.\n- *\n- * Return the cumulative iowait time (since boot) for a given\n- * CPU, in microseconds. Note this is partially broken due to\n- * the counter of iowait tasks that can be remotely updated without\n- * any synchronization. Therefore it is possible to observe backward\n- * values within two consecutive reads.\n- *\n- * This time is measured via accounting rather than sampling,\n- * and is as accurate as ktime_get() is.\n- *\n- * Return: -1 if generic vtime is enabled, else total iowait time of @cpu\n- */\n-u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time)\n-{\n-\treturn get_cpu_sleep_time_us(cpu, CPUTIME_IOWAIT,\n-\t\t\t\t     nr_iowait_cpu(cpu), last_update_time);\n-}\n-EXPORT_SYMBOL_GPL(get_cpu_iowait_time_us);\n-\n /* Simplified variant of hrtimer_forward_now() */\n static ktime_t tick_forward_now(ktime_t expires, ktime_t now)\n {\n@@ -1289,6 +1169,20 @@ void tick_nohz_idle_retain_tick(void)\n \ttick_nohz_retain_tick(this_cpu_ptr(&tick_cpu_sched));\n }\n \n+static void tick_nohz_clock_sleep(struct tick_sched *ts)\n+{\n+\ttick_sched_flag_set(ts, TS_FLAG_IDLE_ACTIVE);\n+\tsched_clock_idle_sleep_event();\n+}\n+\n+static void tick_nohz_clock_wakeup(struct tick_sched *ts)\n+{\n+\tif (tick_sched_flag_test(ts, TS_FLAG_IDLE_ACTIVE)) {\n+\t\ttick_sched_flag_clear(ts, TS_FLAG_IDLE_ACTIVE);\n+\t\tsched_clock_idle_wakeup_event();\n+\t}\n+}\n+\n /**\n  * tick_nohz_idle_enter - prepare for entering idle on the current CPU\n  *\n@@ -1303,12 +1197,11 @@ void tick_nohz_idle_enter(void)\n \tlocal_irq_disable();\n \n \tts = this_cpu_ptr(&tick_cpu_sched);\n-\n \tWARN_ON_ONCE(ts->timer_expires_base);\n-\n \ttick_sched_flag_set(ts, TS_FLAG_INIDLE);\n-\tkcpustat_dyntick_start();\n-\ttick_nohz_start_idle(ts);\n+\tts->idle_entrytime = ktime_get();\n+\tkcpustat_dyntick_start(ts->idle_entrytime);\n+\ttick_nohz_clock_sleep(ts);\n \n \tlocal_irq_enable();\n }\n@@ -1336,10 +1229,13 @@ void tick_nohz_irq_exit(void)\n {\n \tstruct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched);\n \n-\tif (tick_sched_flag_test(ts, TS_FLAG_INIDLE))\n-\t\ttick_nohz_start_idle(ts);\n-\telse\n+\tif (tick_sched_flag_test(ts, TS_FLAG_INIDLE)) {\n+\t\tts->idle_entrytime = ktime_get();\n+\t\tkcpustat_irq_exit(ts->idle_entrytime);\n+\t\ttick_nohz_clock_sleep(ts);\n+\t} else {\n \t\ttick_nohz_full_update_tick(ts);\n+\t}\n }\n \n /**\n@@ -1484,11 +1380,11 @@ void tick_nohz_idle_exit(void)\n \t\tnow = ktime_get();\n \n \tif (idle_active)\n-\t\ttick_nohz_stop_idle(ts, now);\n+\t\ttick_nohz_clock_wakeup(ts);\n \n \tif (tick_stopped)\n \t\ttick_nohz_idle_update_tick(ts, now);\n-\tkcpustat_dyntick_stop();\n+\tkcpustat_dyntick_stop(now);\n \n \tlocal_irq_enable();\n }\n@@ -1545,9 +1441,14 @@ static inline void tick_nohz_irq_enter(void)\n \n \tif (!tick_sched_flag_test(ts, TS_FLAG_STOPPED | TS_FLAG_IDLE_ACTIVE))\n \t\treturn;\n+\n \tnow = ktime_get();\n-\tif (tick_sched_flag_test(ts, TS_FLAG_IDLE_ACTIVE))\n-\t\ttick_nohz_stop_idle(ts, now);\n+\n+\tif (tick_sched_flag_test(ts, TS_FLAG_IDLE_ACTIVE)) {\n+\t\ttick_nohz_clock_wakeup(ts);\n+\t\tkcpustat_irq_enter(now);\n+\t}\n+\n \t/*\n \t * If all CPUs are idle we may need to update a stale jiffies value.\n \t * Note nohz_full is a special case: a timekeeper is guaranteed to stay\n","prefixes":["09/15"]}